001    /**
002     * Copyright (c) 2000-present 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.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 Igor Beslic
041     * @author Zolt??n Tak??cs
042     */
043    @DoPrivileged
044    public class PatcherImpl implements Patcher {
045    
046            @Override
047            public boolean applyPatch(File patchFile) {
048                    File patchDirectory = getPatchDirectory();
049    
050                    if (patchDirectory == null) {
051                            return false;
052                    }
053    
054                    try {
055                            FileUtil.copyFile(
056                                    patchFile,
057                                    new File(
058                                            patchDirectory + StringPool.SLASH + patchFile.getName()));
059    
060                            return true;
061                    }
062                    catch (Exception e) {
063                            _log.error(
064                                    "Unable to copy " + patchFile.getAbsolutePath() + " to " +
065                                            patchDirectory.getAbsolutePath());
066    
067                            return false;
068                    }
069            }
070    
071            @Override
072            public String[] getFixedIssues() {
073                    if (_fixedIssueKeys != null) {
074                            return _fixedIssueKeys;
075                    }
076    
077                    Properties properties = getProperties();
078    
079                    _fixedIssueKeys = StringUtil.split(
080                            properties.getProperty(PROPERTY_FIXED_ISSUES));
081    
082                    return _fixedIssueKeys;
083            }
084    
085            @Override
086            public String[] getInstalledPatches() {
087                    if (_installedPatchNames != null) {
088                            return _installedPatchNames;
089                    }
090    
091                    return _getInstalledPatches(null);
092            }
093    
094            @Override
095            public File getPatchDirectory() {
096                    if (_patchDirectory != null) {
097                            return _patchDirectory;
098                    }
099    
100                    Properties properties = getProperties();
101    
102                    String patchDirectoryName = properties.getProperty(
103                            PROPERTY_PATCH_DIRECTORY);
104    
105                    if (Validator.isNotNull(patchDirectoryName)) {
106                            _patchDirectory = new File(patchDirectoryName);
107    
108                            if (!_patchDirectory.exists()) {
109                                    _log.error("The patch directory does not exist");
110                            }
111                    }
112                    else {
113                            _log.error("The patch directory is not specified");
114                    }
115    
116                    return _patchDirectory;
117            }
118    
119            @Override
120            public int getPatchingToolVersion() {
121                    if (_patchingToolVersion != 0) {
122                            return _patchingToolVersion;
123                    }
124    
125                    Properties properties = getProperties();
126    
127                    if (properties.containsKey(PROPERTY_PATCHING_TOOL_VERSION)) {
128                            _patchingToolVersion = GetterUtil.getInteger(
129                                    properties.getProperty(PROPERTY_PATCHING_TOOL_VERSION));
130                    }
131    
132                    return _patchingToolVersion;
133            }
134    
135            @Override
136            public String[] getPatchLevels() {
137                    if (_patchLevels != null) {
138                            return _patchLevels;
139                    }
140    
141                    Properties properties = getProperties();
142    
143                    _patchLevels = StringUtil.split(
144                            properties.getProperty(PROPERTY_PATCH_LEVELS));
145    
146                    return _patchLevels;
147            }
148    
149            @Override
150            public Properties getProperties() {
151                    if (_properties != null) {
152                            return _properties;
153                    }
154    
155                    return _getProperties(PATCHER_PROPERTIES);
156            }
157    
158            @Override
159            public boolean hasInconsistentPatchLevels() {
160                    return _inconsistentPatchLevels;
161            }
162    
163            @Override
164            public boolean isConfigured() {
165                    return _configured;
166            }
167    
168            @Override
169            public void verifyPatchLevels() throws PatchInconsistencyException {
170                    Properties portalImplJARProperties = _getProperties(PATCHER_PROPERTIES);
171    
172                    String[] portalImplJARPatches = _getInstalledPatches(
173                            portalImplJARProperties);
174    
175                    Arrays.sort(portalImplJARPatches);
176    
177                    Properties portalServiceJARProperties = _getProperties(
178                            PATCHER_SERVICE_PROPERTIES);
179    
180                    String[] serviceJARPatches = _getInstalledPatches(
181                            portalServiceJARProperties);
182    
183                    Arrays.sort(serviceJARPatches);
184    
185                    if (!Arrays.equals(portalImplJARPatches, serviceJARPatches)) {
186                            _log.error("Inconsistent patch level detected");
187    
188                            if (_log.isWarnEnabled()) {
189                                    if (ArrayUtil.isEmpty(portalImplJARPatches)) {
190                                            _log.warn(
191                                                    "There are no patches installed on portal-impl.jar");
192                                    }
193                                    else {
194                                            _log.warn(
195                                                    "Patch level on portal-impl.jar: " +
196                                                            Arrays.toString(portalImplJARPatches));
197                                    }
198    
199                                    if (ArrayUtil.isEmpty(serviceJARPatches)) {
200                                            _log.warn(
201                                                    "There are no patches installed on portal-service.jar");
202                                    }
203                                    else {
204                                            _log.warn(
205                                                    "Patch level on portal-service.jar: " +
206                                                            Arrays.toString(serviceJARPatches));
207                                    }
208                            }
209    
210                            _inconsistentPatchLevels = true;
211    
212                            throw new PatchInconsistencyException();
213                    }
214            }
215    
216            private String[] _getInstalledPatches(Properties properties) {
217                    if (properties == null) {
218                            properties = getProperties();
219                    }
220    
221                    _installedPatchNames = StringUtil.split(
222                            properties.getProperty(PROPERTY_INSTALLED_PATCHES));
223    
224                    return _installedPatchNames;
225            }
226    
227            private Properties _getProperties(String fileName) {
228                    if (Validator.isNull(fileName)) {
229                            fileName = PATCHER_PROPERTIES;
230                    }
231    
232                    Properties properties = new Properties();
233    
234                    Class<?> clazz = getClass();
235    
236                    if (Validator.equals(fileName, PATCHER_SERVICE_PROPERTIES)) {
237                            clazz = clazz.getInterfaces()[0];
238                    }
239    
240                    ClassLoader classLoader = clazz.getClassLoader();
241    
242                    InputStream inputStream = classLoader.getResourceAsStream(fileName);
243    
244                    if (inputStream == null) {
245                            if (_log.isDebugEnabled()) {
246                                    _log.debug("Unable to load " + fileName);
247                            }
248                    }
249                    else {
250                            try {
251                                    properties.load(inputStream);
252    
253                                    _configured = true;
254                            }
255                            catch (IOException ioe) {
256                                    _log.error(ioe, ioe);
257                            }
258                            finally {
259                                    StreamUtil.cleanUp(inputStream);
260                            }
261                    }
262    
263                    _properties = properties;
264    
265                    return _properties;
266            }
267    
268            private static final Log _log = LogFactoryUtil.getLog(PatcherImpl.class);
269    
270            private boolean _configured;
271            private String[] _fixedIssueKeys;
272            private boolean _inconsistentPatchLevels;
273            private String[] _installedPatchNames;
274            private File _patchDirectory;
275            private int _patchingToolVersion;
276            private String[] _patchLevels;
277            private Properties _properties;
278    
279    }