001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.GetterUtil;
025    import com.liferay.portal.kernel.util.StreamUtil;
026    import com.liferay.portal.kernel.util.StringPool;
027    import com.liferay.portal.kernel.util.StringUtil;
028    import com.liferay.portal.kernel.util.Validator;
029    
030    import java.io.File;
031    import java.io.IOException;
032    import java.io.InputStream;
033    
034    import java.util.Arrays;
035    import java.util.Properties;
036    
037    /**
038     * @author Zsolt Balogh
039     * @author Brian Wing Shun Chan
040     * @author Zolt??n Tak??cs
041     */
042    @DoPrivileged
043    public class PatcherImpl implements Patcher {
044    
045            @Override
046            public boolean applyPatch(File patchFile) {
047                    File patchDirectory = getPatchDirectory();
048    
049                    if (patchDirectory == null) {
050                            return false;
051                    }
052    
053                    try {
054                            FileUtil.copyFile(
055                                    patchFile,
056                                    new File(
057                                            patchDirectory + StringPool.SLASH + patchFile.getName()));
058    
059                            return true;
060                    }
061                    catch (Exception e) {
062                            _log.error(
063                                    "Unable to copy " + patchFile.getAbsolutePath() + " to " +
064                                            patchDirectory.getAbsolutePath());
065    
066                            return false;
067                    }
068            }
069    
070            @Override
071            public String[] getFixedIssues() {
072                    if (_fixedIssueKeys != null) {
073                            return _fixedIssueKeys;
074                    }
075    
076                    Properties properties = getProperties();
077    
078                    _fixedIssueKeys = StringUtil.split(
079                            properties.getProperty(PROPERTY_FIXED_ISSUES));
080    
081                    return _fixedIssueKeys;
082            }
083    
084            @Override
085            public String[] getInstalledPatches() {
086                    if (_installedPatchNames != null) {
087                            return _installedPatchNames;
088                    }
089    
090                    return _getInstalledPatches(null);
091            }
092    
093            @Override
094            public File getPatchDirectory() {
095                    if (_patchDirectory != null) {
096                            return _patchDirectory;
097                    }
098    
099                    Properties properties = getProperties();
100    
101                    String patchDirectoryName = properties.getProperty(
102                            PROPERTY_PATCH_DIRECTORY);
103    
104                    if (Validator.isNotNull(patchDirectoryName)) {
105                            _patchDirectory = new File(patchDirectoryName);
106    
107                            if (!_patchDirectory.exists()) {
108                                    _log.error("The patch directory does not exist");
109                            }
110                    }
111                    else {
112                            _log.error("The patch directory is not specified");
113                    }
114    
115                    return _patchDirectory;
116            }
117    
118            @Override
119            public int getPatchingToolVersion() {
120                    if (_patchingToolVersion != 0) {
121                            return _patchingToolVersion;
122                    }
123    
124                    Properties properties = getProperties();
125    
126                    if (properties.containsKey(PROPERTY_PATCHING_TOOL_VERSION)) {
127                            _patchingToolVersion = GetterUtil.getInteger(
128                                    properties.getProperty(PROPERTY_PATCHING_TOOL_VERSION));
129                    }
130    
131                    return _patchingToolVersion;
132            }
133    
134            @Override
135            public String getPatchingToolVersionDisplayName() {
136                    if (_patchingToolVersionDisplayName != null) {
137                            return _patchingToolVersionDisplayName;
138                    }
139    
140                    Properties properties = getProperties();
141    
142                    if (properties.containsKey(
143                                    PROPERTY_PATCHING_TOOL_VERSION_DISPLAY_NAME)) {
144    
145                            _patchingToolVersionDisplayName = properties.getProperty(
146                                    PROPERTY_PATCHING_TOOL_VERSION_DISPLAY_NAME);
147                    }
148                    else {
149                            _patchingToolVersionDisplayName = "1.0." + getPatchingToolVersion();
150                    }
151    
152                    return _patchingToolVersionDisplayName;
153            }
154    
155            @Override
156            public String[] getPatchLevels() {
157                    if (_patchLevels != null) {
158                            return _patchLevels;
159                    }
160    
161                    Properties properties = getProperties();
162    
163                    _patchLevels = StringUtil.split(
164                            properties.getProperty(PROPERTY_PATCH_LEVELS));
165    
166                    return _patchLevels;
167            }
168    
169            @Override
170            public Properties getProperties() {
171                    if (_properties != null) {
172                            return _properties;
173                    }
174    
175                    return _getProperties(PATCHER_PROPERTIES);
176            }
177    
178            @Override
179            public boolean isConfigured() {
180                    return _configured;
181            }
182    
183            @Override
184            public boolean hasInconsistentPatchLevels() {
185                    return _inconsistentPatchLevels;
186            }
187    
188            @Override
189            public void verifyPatchLevels() throws PatchInconsistencyException {
190                    Properties portalImplJARProperties = _getProperties(PATCHER_PROPERTIES);
191    
192                    String[] portalImplJARPatches = _getInstalledPatches(
193                            portalImplJARProperties);
194    
195                    Arrays.sort(portalImplJARPatches);
196    
197                    Properties portalServiceJARProperties = _getProperties(
198                            PATCHER_SERVICE_PROPERTIES);
199    
200                    String[] serviceJARPatches = _getInstalledPatches(
201                            portalServiceJARProperties);
202    
203                    Arrays.sort(serviceJARPatches);
204    
205                    if (!Arrays.equals(portalImplJARPatches, serviceJARPatches)) {
206                            _log.error("Inconsistent patch level detected");
207    
208                            if (_log.isWarnEnabled()) {
209                                    if (ArrayUtil.isEmpty(portalImplJARPatches)) {
210                                            _log.warn(
211                                                    "There are no patches installed on portal-impl.jar");
212                                    }
213                                    else {
214                                            _log.warn(
215                                                    "Patch level on portal-impl.jar: " +
216                                                            Arrays.toString(portalImplJARPatches));
217                                    }
218    
219                                    if (ArrayUtil.isEmpty(serviceJARPatches)) {
220                                            _log.warn(
221                                                    "There are no patches installed on portal-service.jar");
222                                    }
223                                    else {
224                                            _log.warn(
225                                                    "Patch level on portal-service.jar: " +
226                                                            Arrays.toString(serviceJARPatches));
227                                    }
228                            }
229    
230                            _inconsistentPatchLevels = true;
231    
232                            throw new PatchInconsistencyException();
233                    }
234            }
235    
236            private String[] _getInstalledPatches(Properties properties) {
237                    if (properties == null) {
238                            properties = getProperties();
239                    }
240    
241                    _installedPatchNames = StringUtil.split(
242                            properties.getProperty(PROPERTY_INSTALLED_PATCHES));
243    
244                    return _installedPatchNames;
245            }
246    
247            private Properties _getProperties(String fileName) {
248                    if (Validator.isNull(fileName)) {
249                            fileName = PATCHER_PROPERTIES;
250                    }
251    
252                    Properties properties = new Properties();
253    
254                    Class<?> clazz = getClass();
255    
256                    if (Validator.equals(fileName, PATCHER_SERVICE_PROPERTIES)) {
257                            clazz = clazz.getInterfaces()[0];
258                    }
259    
260                    ClassLoader classLoader = clazz.getClassLoader();
261    
262                    InputStream inputStream = classLoader.getResourceAsStream(fileName);
263    
264                    if (inputStream == null) {
265                            if (_log.isDebugEnabled()) {
266                                    _log.debug("Unable to load " + fileName);
267                            }
268                    }
269                    else {
270                            try {
271                                    properties.load(inputStream);
272    
273                                    _configured = true;
274                            }
275                            catch (IOException ioe) {
276                                    _log.error(ioe, ioe);
277                            }
278                            finally {
279                                    StreamUtil.cleanUp(inputStream);
280                            }
281                    }
282    
283                    _properties = properties;
284    
285                    return _properties;
286            }
287    
288            private static Log _log = LogFactoryUtil.getLog(PatcherImpl.class);
289    
290            private boolean _configured;
291            private String[] _fixedIssueKeys;
292            private boolean _inconsistentPatchLevels;
293            private String[] _installedPatchNames;
294            private File _patchDirectory;
295            private int _patchingToolVersion;
296            private String _patchingToolVersionDisplayName;
297            private String[] _patchLevels;
298            private Properties _properties;
299    
300    }