001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.patcher;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.patcher.PatchInconsistencyException;
020    import com.liferay.portal.kernel.patcher.Patcher;
021    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
022    import com.liferay.portal.kernel.util.ArrayUtil;
023    import com.liferay.portal.kernel.util.FileUtil;
024    import com.liferay.portal.kernel.util.StreamUtil;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.StringUtil;
027    import com.liferay.portal.kernel.util.Validator;
028    
029    import java.io.File;
030    import java.io.IOException;
031    import java.io.InputStream;
032    
033    import java.util.Arrays;
034    import java.util.Properties;
035    
036    /**
037     * @author Zsolt Balogh
038     * @author Brian Wing Shun Chan
039     * @author Zolt??n Tak??cs
040     */
041    @DoPrivileged
042    public class PatcherImpl implements Patcher {
043    
044            @Override
045            public boolean applyPatch(File patchFile) {
046                    File patchDirectory = getPatchDirectory();
047    
048                    if (patchDirectory == null) {
049                            return false;
050                    }
051    
052                    try {
053                            FileUtil.copyFile(
054                                    patchFile,
055                                    new File(
056                                            patchDirectory + StringPool.SLASH + patchFile.getName()));
057    
058                            return true;
059                    }
060                    catch (Exception e) {
061                            _log.error(
062                                    "Unable to copy " + patchFile.getAbsolutePath() + " to " +
063                                            patchDirectory.getAbsolutePath());
064    
065                            return false;
066                    }
067            }
068    
069            @Override
070            public String[] getFixedIssues() {
071                    if (_fixedIssueKeys != null) {
072                            return _fixedIssueKeys;
073                    }
074    
075                    Properties properties = getProperties();
076    
077                    _fixedIssueKeys = StringUtil.split(
078                            properties.getProperty(PROPERTY_FIXED_ISSUES));
079    
080                    return _fixedIssueKeys;
081            }
082    
083            @Override
084            public String[] getInstalledPatches() {
085                    if (_installedPatchNames != null) {
086                            return _installedPatchNames;
087                    }
088    
089                    return _getInstalledPatches(null);
090            }
091    
092            @Override
093            public File getPatchDirectory() {
094                    if (_patchDirectory != null) {
095                            return _patchDirectory;
096                    }
097    
098                    Properties properties = getProperties();
099    
100                    String patchDirectoryName = properties.getProperty(
101                            PROPERTY_PATCH_DIRECTORY);
102    
103                    if (Validator.isNotNull(patchDirectoryName)) {
104                            _patchDirectory = new File(patchDirectoryName);
105    
106                            if (!_patchDirectory.exists()) {
107                                    _log.error("The patch directory does not exist");
108                            }
109                    }
110                    else {
111                            _log.error("The patch directory is not specified");
112                    }
113    
114                    return _patchDirectory;
115            }
116    
117            @Override
118            public String[] getPatchLevels() {
119                    if (_patchLevels != null) {
120                            return _patchLevels;
121                    }
122    
123                    Properties properties = getProperties();
124    
125                    _patchLevels = StringUtil.split(
126                            properties.getProperty(PROPERTY_PATCH_LEVELS));
127    
128                    return _patchLevels;
129            }
130    
131            @Override
132            public Properties getProperties() {
133                    if (_properties != null) {
134                            return _properties;
135                    }
136    
137                    return _getProperties(PATCHER_PROPERTIES);
138            }
139    
140            @Override
141            public boolean isConfigured() {
142                    return _configured;
143            }
144    
145            @Override
146            public boolean hasInconsistentPatchLevels() {
147                    return _inconsistentPatchLevels;
148            }
149    
150            @Override
151            public void verifyPatchLevels() throws PatchInconsistencyException {
152                    Properties portalImplJARProperties = _getProperties(PATCHER_PROPERTIES);
153    
154                    String[] portalImplJARPatches = _getInstalledPatches(
155                            portalImplJARProperties);
156    
157                    Arrays.sort(portalImplJARPatches);
158    
159                    Properties portalServiceJARProperties = _getProperties(
160                            PATCHER_SERVICE_PROPERTIES);
161    
162                    String[] serviceJARPatches = _getInstalledPatches(
163                            portalServiceJARProperties);
164    
165                    Arrays.sort(serviceJARPatches);
166    
167                    if (!Arrays.equals(portalImplJARPatches, serviceJARPatches)) {
168                            _log.error("Inconsistent patch level detected");
169    
170                            if (_log.isWarnEnabled()) {
171                                    if (ArrayUtil.isEmpty(portalImplJARPatches)) {
172                                            _log.warn(
173                                                    "There are no patches installed on portal-impl.jar");
174                                    }
175                                    else {
176                                            _log.warn(
177                                                    "Patch level on portal-impl.jar: " +
178                                                            Arrays.toString(portalImplJARPatches));
179                                    }
180    
181                                    if (ArrayUtil.isEmpty(serviceJARPatches)) {
182                                            _log.warn(
183                                                    "There are no patches installed on portal-service.jar");
184                                    }
185                                    else {
186                                            _log.warn(
187                                                    "Patch level on portal-service.jar: " +
188                                                            Arrays.toString(serviceJARPatches));
189                                    }
190                            }
191    
192                            _inconsistentPatchLevels = true;
193    
194                            throw new PatchInconsistencyException();
195                    }
196            }
197    
198            private String[] _getInstalledPatches(Properties properties) {
199                    if (properties == null) {
200                            properties = getProperties();
201                    }
202    
203                    _installedPatchNames = StringUtil.split(
204                            properties.getProperty(PROPERTY_INSTALLED_PATCHES));
205    
206                    return _installedPatchNames;
207            }
208    
209            private Properties _getProperties(String fileName) {
210                    if (Validator.isNull(fileName)) {
211                            fileName = PATCHER_PROPERTIES;
212                    }
213    
214                    Properties properties = new Properties();
215    
216                    Class<?> clazz = getClass();
217    
218                    if (Validator.equals(fileName, PATCHER_SERVICE_PROPERTIES)) {
219                            clazz = clazz.getInterfaces()[0];
220                    }
221    
222                    ClassLoader classLoader = clazz.getClassLoader();
223    
224                    InputStream inputStream = classLoader.getResourceAsStream(fileName);
225    
226                    if (inputStream == null) {
227                            if (_log.isDebugEnabled()) {
228                                    _log.debug("Unable to load " + fileName);
229                            }
230                    }
231                    else {
232                            try {
233                                    properties.load(inputStream);
234    
235                                    _configured = true;
236                            }
237                            catch (IOException ioe) {
238                                    _log.error(ioe, ioe);
239                            }
240                            finally {
241                                    StreamUtil.cleanUp(inputStream);
242                            }
243                    }
244    
245                    _properties = properties;
246    
247                    return _properties;
248            }
249    
250            private static Log _log = LogFactoryUtil.getLog(PatcherImpl.class);
251    
252            private static boolean _configured;
253            private static String[] _fixedIssueKeys;
254            private static boolean _inconsistentPatchLevels;
255            private static String[] _installedPatchNames;
256            private static File _patchDirectory;
257            private static String[] _patchLevels;
258            private static Properties _properties;
259    
260    }