001    /**
002     * Copyright (c) 2000-2012 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.tools;
016    
017    import com.liferay.portal.dao.orm.common.SQLTransformer;
018    import com.liferay.portal.events.StartupHelperUtil;
019    import com.liferay.portal.kernel.cache.CacheRegistryUtil;
020    import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
021    import com.liferay.portal.kernel.dao.db.DB;
022    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
023    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
024    import com.liferay.portal.kernel.exception.PortalException;
025    import com.liferay.portal.kernel.log.Log;
026    import com.liferay.portal.kernel.log.LogFactoryUtil;
027    import com.liferay.portal.kernel.util.ReleaseInfo;
028    import com.liferay.portal.kernel.util.StringBundler;
029    import com.liferay.portal.kernel.util.Time;
030    import com.liferay.portal.model.Release;
031    import com.liferay.portal.model.ReleaseConstants;
032    import com.liferay.portal.service.ClassNameLocalServiceUtil;
033    import com.liferay.portal.service.ReleaseLocalServiceUtil;
034    import com.liferay.portal.service.ResourceActionLocalServiceUtil;
035    import com.liferay.portal.service.ResourceCodeLocalServiceUtil;
036    import com.liferay.portal.util.InitUtil;
037    import com.liferay.portal.util.PropsValues;
038    import com.liferay.util.dao.orm.CustomSQLUtil;
039    
040    import java.sql.Connection;
041    import java.sql.Date;
042    import java.sql.PreparedStatement;
043    import java.sql.ResultSet;
044    
045    import org.apache.commons.lang.time.StopWatch;
046    
047    /**
048     * @author Michael C. Han
049     * @author Brian Wing Shun Chan
050     */
051    public class DBUpgrader {
052    
053            public static void main(String[] args) {
054                    try {
055                            StopWatch stopWatch = new StopWatch();
056    
057                            stopWatch.start();
058    
059                            InitUtil.initWithSpring();
060    
061                            upgrade();
062                            verify();
063    
064                            System.out.println(
065                                    "\nSuccessfully completed upgrade process in " +
066                                            (stopWatch.getTime() / Time.SECOND) + " seconds.");
067    
068                            System.exit(0);
069                    }
070                    catch (Exception e) {
071                            e.printStackTrace();
072    
073                            System.exit(1);
074                    }
075            }
076    
077            public static void upgrade() throws Exception {
078    
079                    // Disable database caching before upgrade
080    
081                    if (_log.isDebugEnabled()) {
082                            _log.debug("Disable cache registry");
083                    }
084    
085                    CacheRegistryUtil.setActive(false);
086    
087                    // Upgrade
088    
089                    if (_log.isDebugEnabled()) {
090                            _log.debug("Run upgrade process");
091                    }
092    
093                    int buildNumber = ReleaseLocalServiceUtil.getBuildNumberOrCreate();
094    
095                    if (buildNumber > ReleaseInfo.getParentBuildNumber()) {
096                            StringBundler sb = new StringBundler(6);
097    
098                            sb.append("Attempting to deploy an older Liferay Portal version. ");
099                            sb.append("Current build version is ");
100                            sb.append(buildNumber);
101                            sb.append(" and attempting to deploy version ");
102                            sb.append(ReleaseInfo.getParentBuildNumber());
103                            sb.append(".");
104    
105                            throw new IllegalStateException(sb.toString());
106                    }
107                    else if (buildNumber < ReleaseInfo.RELEASE_5_0_0_BUILD_NUMBER) {
108                            String msg = "You must first upgrade to Liferay Portal 5.0.0";
109    
110                            System.out.println(msg);
111    
112                            throw new RuntimeException(msg);
113                    }
114    
115                    // Reload SQL
116    
117                    CustomSQLUtil.reloadCustomSQL();
118                    SQLTransformer.reloadSQLTransformer();
119    
120                    // Upgrade build
121    
122                    if (_log.isDebugEnabled()) {
123                            _log.debug("Update build " + buildNumber);
124                    }
125    
126                    _checkReleaseState();
127    
128                    try {
129                            StartupHelperUtil.upgradeProcess(buildNumber);
130                    }
131                    catch (Exception e) {
132                            _updateReleaseState(ReleaseConstants.STATE_UPGRADE_FAILURE);
133    
134                            throw e;
135                    }
136    
137                    // Update company key
138    
139                    if (StartupHelperUtil.isUpgraded()) {
140                            if (_log.isDebugEnabled()) {
141                                    _log.debug("Update company key");
142                            }
143    
144                            _updateCompanyKey();
145                    }
146    
147                    // Class names
148    
149                    if (_log.isDebugEnabled()) {
150                            _log.debug("Check class names");
151                    }
152    
153                    ClassNameLocalServiceUtil.checkClassNames();
154    
155                    // Resource actions
156    
157                    if (_log.isDebugEnabled()) {
158                            _log.debug("Check resource actions");
159                    }
160    
161                    ResourceActionLocalServiceUtil.checkResourceActions();
162    
163                    // Resource codes
164    
165                    if (_log.isDebugEnabled()) {
166                            _log.debug("Check resource codes");
167                    }
168    
169                    ResourceCodeLocalServiceUtil.checkResourceCodes();
170    
171                    // Delete temporary images
172    
173                    if (_log.isDebugEnabled()) {
174                            _log.debug("Delete temporary images");
175                    }
176    
177                    _deleteTempImages();
178    
179                    // Clear the caches only if the upgrade process was run
180    
181                    if (_log.isDebugEnabled()) {
182                            _log.debug("Clear cache if upgrade process was run");
183                    }
184    
185                    if (StartupHelperUtil.isUpgraded()) {
186                            MultiVMPoolUtil.clear();
187                    }
188            }
189    
190            public static void verify() throws Exception {
191    
192                    // Verify
193    
194                    Release release = null;
195    
196                    try {
197                            release = ReleaseLocalServiceUtil.getRelease(
198                                    ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME,
199                                    ReleaseInfo.getParentBuildNumber());
200                    }
201                    catch (PortalException pe) {
202                            release = ReleaseLocalServiceUtil.addRelease(
203                                    ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME,
204                                    ReleaseInfo.getParentBuildNumber());
205                    }
206    
207                    _checkReleaseState();
208    
209                    try {
210                            StartupHelperUtil.verifyProcess(release.isVerified());
211                    }
212                    catch (Exception e) {
213                            _updateReleaseState(ReleaseConstants.STATE_VERIFY_FAILURE);
214    
215                            throw e;
216                    }
217    
218                    // Update indexes
219    
220                    if (PropsValues.DATABASE_INDEXES_UPDATE_ON_STARTUP) {
221                            StartupHelperUtil.setDropIndexes(true);
222    
223                            StartupHelperUtil.updateIndexes();
224                    }
225                    else if (StartupHelperUtil.isUpgraded()) {
226                            StartupHelperUtil.updateIndexes();
227                    }
228    
229                    // Update release
230    
231                    boolean verified = StartupHelperUtil.isVerified();
232    
233                    if (release.isVerified()) {
234                            verified = true;
235                    }
236    
237                    ReleaseLocalServiceUtil.updateRelease(
238                            release.getReleaseId(), ReleaseInfo.getParentBuildNumber(),
239                            ReleaseInfo.getBuildDate(), verified);
240    
241                    // Enable database caching after verify
242    
243                    CacheRegistryUtil.setActive(true);
244            }
245    
246            private static void _checkReleaseState() throws Exception {
247                    int state = _getReleaseState();
248    
249                    if (state == ReleaseConstants.STATE_GOOD) {
250                            return;
251                    }
252    
253                    StringBundler sb = new StringBundler(6);
254    
255                    sb.append("The database contains changes from a previous ");
256                    sb.append("upgrade attempt that failed. Please restore the old ");
257                    sb.append("database and file system and retry the upgrade. A ");
258                    sb.append("patch may be required if the upgrade failed due to a");
259                    sb.append(" bug or an unforeseen data permutation that resulted ");
260                    sb.append("from a corrupt database.");
261    
262                    throw new IllegalStateException(sb.toString());
263            }
264    
265            private static void _deleteTempImages() throws Exception {
266                    DB db = DBFactoryUtil.getDB();
267    
268                    db.runSQL(_DELETE_TEMP_IMAGES_1);
269                    db.runSQL(_DELETE_TEMP_IMAGES_2);
270            }
271    
272            private static int _getReleaseState() throws Exception {
273                    Connection con = null;
274                    PreparedStatement ps = null;
275                    ResultSet rs = null;
276    
277                    try {
278                            con = DataAccess.getConnection();
279    
280                            ps = con.prepareStatement(
281                                    "select state_ from Release_ where releaseId = ?");
282    
283                            ps.setLong(1, ReleaseConstants.DEFAULT_ID);
284    
285                            rs = ps.executeQuery();
286    
287                            if (rs.next()) {
288                                    return rs.getInt("state_");
289                            }
290    
291                            throw new IllegalArgumentException(
292                                    "No Release exists with the primary key " +
293                                            ReleaseConstants.DEFAULT_ID);
294                    }
295                    finally {
296                            DataAccess.cleanUp(con, ps, rs);
297                    }
298            }
299    
300            private static void _updateCompanyKey() throws Exception {
301                    DB db = DBFactoryUtil.getDB();
302    
303                    db.runSQL("update Company set key_ = null");
304            }
305    
306            private static void _updateReleaseState(int state) throws Exception {
307                    Connection con = null;
308                    PreparedStatement ps = null;
309    
310                    try {
311                            con = DataAccess.getConnection();
312    
313                            ps = con.prepareStatement(
314                                    "update Release_ set modifiedDate = ?, state_ = ? where " +
315                                            "releaseId = ?");
316    
317                            ps.setDate(1, new Date(System.currentTimeMillis()));
318                            ps.setInt(2, state);
319                            ps.setLong(3, ReleaseConstants.DEFAULT_ID);
320    
321                            ps.executeUpdate();
322                    }
323                    finally {
324                            DataAccess.cleanUp(con, ps);
325                    }
326            }
327    
328            private static final String _DELETE_TEMP_IMAGES_1 =
329                    "delete from Image where imageId IN (SELECT articleImageId FROM " +
330                            "JournalArticleImage where tempImage = TRUE)";
331    
332            private static final String _DELETE_TEMP_IMAGES_2 =
333                    "delete from JournalArticleImage where tempImage = TRUE";
334    
335            private static Log _log = LogFactoryUtil.getLog(DBUpgrader.class);
336    
337    }