001
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.log.Log;
025 import com.liferay.portal.kernel.log.LogFactoryUtil;
026 import com.liferay.portal.kernel.spring.aop.Skip;
027 import com.liferay.portal.kernel.util.GetterUtil;
028 import com.liferay.portal.kernel.util.PropsKeys;
029 import com.liferay.portal.kernel.util.ReflectionUtil;
030 import com.liferay.portal.kernel.util.ReleaseInfo;
031 import com.liferay.portal.kernel.util.StringBundler;
032 import com.liferay.portal.kernel.util.Time;
033 import com.liferay.portal.model.Release;
034 import com.liferay.portal.model.ReleaseConstants;
035 import com.liferay.portal.service.ClassNameLocalServiceUtil;
036 import com.liferay.portal.service.ReleaseLocalServiceUtil;
037 import com.liferay.portal.service.ResourceActionLocalServiceUtil;
038 import com.liferay.portal.spring.aop.ServiceBeanAopCacheManager;
039 import com.liferay.portal.spring.aop.ServiceBeanAopCacheManagerUtil;
040 import com.liferay.portal.util.InitUtil;
041 import com.liferay.portal.util.PropsUtil;
042 import com.liferay.portal.util.PropsValues;
043 import com.liferay.util.dao.orm.CustomSQLUtil;
044
045 import java.lang.annotation.Annotation;
046 import java.lang.reflect.Field;
047
048 import java.sql.Connection;
049 import java.sql.Date;
050 import java.sql.PreparedStatement;
051 import java.sql.ResultSet;
052
053 import java.util.HashMap;
054 import java.util.concurrent.ConcurrentHashMap;
055
056 import org.aopalliance.intercept.MethodInvocation;
057
058 import org.apache.commons.lang.time.StopWatch;
059
060
064 public class DBUpgrader {
065
066 public static void main(String[] args) {
067 try {
068 StopWatch stopWatch = new StopWatch();
069
070 stopWatch.start();
071
072 InitUtil.initWithSpring();
073
074 upgrade();
075 verify();
076
077 System.out.println(
078 "\nSuccessfully completed upgrade process in " +
079 (stopWatch.getTime() / Time.SECOND) + " seconds.");
080
081 System.exit(0);
082 }
083 catch (Exception e) {
084 e.printStackTrace();
085
086 System.exit(1);
087 }
088 }
089
090 public static void upgrade() throws Exception {
091
092
093
094 if (_log.isDebugEnabled()) {
095 _log.debug("Disable cache registry");
096 }
097
098 CacheRegistryUtil.setActive(false);
099
100
101
102 int buildNumber = ReleaseLocalServiceUtil.getBuildNumberOrCreate();
103
104 if (buildNumber > ReleaseInfo.getParentBuildNumber()) {
105 StringBundler sb = new StringBundler(6);
106
107 sb.append("Attempting to deploy an older Liferay Portal version. ");
108 sb.append("Current build version is ");
109 sb.append(buildNumber);
110 sb.append(" and attempting to deploy version ");
111 sb.append(ReleaseInfo.getParentBuildNumber());
112 sb.append(".");
113
114 throw new IllegalStateException(sb.toString());
115 }
116 else if (buildNumber < ReleaseInfo.RELEASE_5_2_3_BUILD_NUMBER) {
117 String msg = "You must first upgrade to Liferay Portal 5.2.3";
118
119 System.out.println(msg);
120
121 throw new RuntimeException(msg);
122 }
123
124
125
126 CustomSQLUtil.reloadCustomSQL();
127 SQLTransformer.reloadSQLTransformer();
128
129
130
131 if (_log.isDebugEnabled()) {
132 _log.debug("Update build " + buildNumber);
133 }
134
135 _checkPermissionAlgorithm();
136 _checkReleaseState(_getReleaseState());
137
138 if (PropsValues.UPGRADE_DATABASE_TRANSACTIONS_DISABLED) {
139 _disableTransactions();
140 }
141
142 try {
143 StartupHelperUtil.upgradeProcess(buildNumber);
144 }
145 catch (Exception e) {
146 _updateReleaseState(ReleaseConstants.STATE_UPGRADE_FAILURE);
147
148 throw e;
149 }
150 finally {
151 if (PropsValues.UPGRADE_DATABASE_TRANSACTIONS_DISABLED) {
152 _enableTransactions();
153 }
154 }
155
156
157
158 if (StartupHelperUtil.isUpgraded()) {
159 if (_log.isDebugEnabled()) {
160 _log.debug("Update company key");
161 }
162
163 _updateCompanyKey();
164 }
165
166
167
168 if (_log.isDebugEnabled()) {
169 _log.debug("Check class names");
170 }
171
172 ClassNameLocalServiceUtil.checkClassNames();
173
174
175
176 if (_log.isDebugEnabled()) {
177 _log.debug("Check resource actions");
178 }
179
180 ResourceActionLocalServiceUtil.checkResourceActions();
181
182
183
184 if (_log.isDebugEnabled()) {
185 _log.debug("Delete temporary images");
186 }
187
188 _deleteTempImages();
189
190
191
192 if (_log.isDebugEnabled()) {
193 _log.debug("Clear cache if upgrade process was run");
194 }
195
196 if (StartupHelperUtil.isUpgraded()) {
197 MultiVMPoolUtil.clear();
198 }
199 }
200
201 public static void verify() throws Exception {
202
203
204
205 Release release = ReleaseLocalServiceUtil.fetchRelease(
206 ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME);
207
208 if (release == null) {
209 release = ReleaseLocalServiceUtil.addRelease(
210 ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME,
211 ReleaseInfo.getParentBuildNumber());
212 }
213
214 _checkReleaseState(release.getState());
215
216
217
218 if (PropsValues.DATABASE_INDEXES_UPDATE_ON_STARTUP) {
219 StartupHelperUtil.setDropIndexes(true);
220
221 StartupHelperUtil.updateIndexes();
222 }
223 else if (StartupHelperUtil.isUpgraded()) {
224 StartupHelperUtil.updateIndexes();
225 }
226
227
228
229 if (PropsValues.VERIFY_DATABASE_TRANSACTIONS_DISABLED) {
230 _disableTransactions();
231 }
232
233 boolean newBuildNumber = false;
234
235 if (ReleaseInfo.getBuildNumber() > release.getBuildNumber()) {
236 newBuildNumber = true;
237 }
238
239 try {
240 StartupHelperUtil.verifyProcess(
241 newBuildNumber, release.isVerified());
242 }
243 catch (Exception e) {
244 _updateReleaseState(ReleaseConstants.STATE_VERIFY_FAILURE);
245
246 if (_log.isErrorEnabled()) {
247 _log.error(
248 "Unable to execute verify process: " + e.getMessage(), e);
249 }
250
251 throw e;
252 }
253 finally {
254 if (PropsValues.VERIFY_DATABASE_TRANSACTIONS_DISABLED) {
255 _enableTransactions();
256 }
257 }
258
259
260
261 if (PropsValues.DATABASE_INDEXES_UPDATE_ON_STARTUP ||
262 StartupHelperUtil.isUpgraded()) {
263
264 StartupHelperUtil.updateIndexes(false);
265 }
266
267
268
269 boolean verified = StartupHelperUtil.isVerified();
270
271 if (release.isVerified()) {
272 verified = true;
273 }
274
275 ReleaseLocalServiceUtil.updateRelease(
276 release.getReleaseId(), ReleaseInfo.getParentBuildNumber(),
277 ReleaseInfo.getBuildDate(), verified);
278
279
280
281 CacheRegistryUtil.setActive(true);
282 }
283
284 private static void _checkPermissionAlgorithm() throws Exception {
285 long count = _getResourceCodesCount();
286
287 if (count == 0) {
288 return;
289 }
290
291 StringBundler sb = new StringBundler(8);
292
293 sb.append("Permission conversion to algorithm 6 has not been ");
294 sb.append("completed. Please complete the conversion prior to ");
295 sb.append("starting the portal. The conversion process is ");
296 sb.append("available in portal versions starting with ");
297 sb.append(ReleaseInfo.RELEASE_5_2_3_BUILD_NUMBER);
298 sb.append(" and prior to ");
299 sb.append(ReleaseInfo.RELEASE_6_2_0_BUILD_NUMBER);
300 sb.append(".");
301
302 throw new IllegalStateException(sb.toString());
303 }
304
305 private static void _checkReleaseState(int state) throws Exception {
306 if (state == ReleaseConstants.STATE_GOOD) {
307 return;
308 }
309
310 StringBundler sb = new StringBundler(6);
311
312 sb.append("The database contains changes from a previous ");
313 sb.append("upgrade attempt that failed. Please restore the old ");
314 sb.append("database and file system and retry the upgrade. A ");
315 sb.append("patch may be required if the upgrade failed due to a");
316 sb.append(" bug or an unforeseen data permutation that resulted ");
317 sb.append("from a corrupt database.");
318
319 throw new IllegalStateException(sb.toString());
320 }
321
322 private static void _deleteTempImages() throws Exception {
323 DB db = DBFactoryUtil.getDB();
324
325 db.runSQL(_DELETE_TEMP_IMAGES_1);
326 db.runSQL(_DELETE_TEMP_IMAGES_2);
327 }
328
329 private static void _disableTransactions() throws Exception {
330 if (_log.isDebugEnabled()) {
331 _log.debug("Disable transactions");
332 }
333
334 PropsValues.SPRING_HIBERNATE_SESSION_DELEGATED = false;
335
336 Field field = ReflectionUtil.getDeclaredField(
337 ServiceBeanAopCacheManager.class, "_annotations");
338
339 field.set(
340 null,
341 new HashMap<MethodInvocation, Annotation[]>() {
342
343 @Override
344 public Annotation[] get(Object key) {
345 return _annotations;
346 }
347
348 private Annotation[] _annotations = new Annotation[] {
349 new Skip() {
350
351 @Override
352 public Class<? extends Annotation> annotationType() {
353 return Skip.class;
354 }
355
356 }
357 };
358
359 }
360 );
361 }
362
363 private static void _enableTransactions() throws Exception {
364 if (_log.isDebugEnabled()) {
365 _log.debug("Enable transactions");
366 }
367
368 PropsValues.SPRING_HIBERNATE_SESSION_DELEGATED = GetterUtil.getBoolean(
369 PropsUtil.get(PropsKeys.SPRING_HIBERNATE_SESSION_DELEGATED));
370
371 Field field = ReflectionUtil.getDeclaredField(
372 ServiceBeanAopCacheManager.class, "_annotations");
373
374 field.set(
375 null, new ConcurrentHashMap<MethodInvocation, Annotation[]>());
376
377 ServiceBeanAopCacheManagerUtil.reset();
378 }
379
380 private static int _getReleaseState() throws Exception {
381 Connection con = null;
382 PreparedStatement ps = null;
383 ResultSet rs = null;
384
385 try {
386 con = DataAccess.getConnection();
387
388 ps = con.prepareStatement(
389 "select state_ from Release_ where releaseId = ?");
390
391 ps.setLong(1, ReleaseConstants.DEFAULT_ID);
392
393 rs = ps.executeQuery();
394
395 if (rs.next()) {
396 return rs.getInt("state_");
397 }
398
399 throw new IllegalArgumentException(
400 "No Release exists with the primary key " +
401 ReleaseConstants.DEFAULT_ID);
402 }
403 finally {
404 DataAccess.cleanUp(con, ps, rs);
405 }
406 }
407
408 private static long _getResourceCodesCount() throws Exception {
409 Connection con = null;
410 PreparedStatement ps = null;
411 ResultSet rs = null;
412
413 try {
414 con = DataAccess.getConnection();
415
416 ps = con.prepareStatement("select count(*) from ResourceCode");
417
418 rs = ps.executeQuery();
419
420 if (rs.next()) {
421 int count = rs.getInt(1);
422
423 return count;
424 }
425
426 return 0;
427 }
428 catch (Exception e) {
429 return 0;
430 }
431 finally {
432 DataAccess.cleanUp(con, ps, rs);
433 }
434 }
435
436 private static void _updateCompanyKey() throws Exception {
437 DB db = DBFactoryUtil.getDB();
438
439 db.runSQL("update Company set key_ = null");
440 }
441
442 private static void _updateReleaseState(int state) throws Exception {
443 Connection con = null;
444 PreparedStatement ps = null;
445
446 try {
447 con = DataAccess.getConnection();
448
449 ps = con.prepareStatement(
450 "update Release_ set modifiedDate = ?, state_ = ? where " +
451 "releaseId = ?");
452
453 ps.setDate(1, new Date(System.currentTimeMillis()));
454 ps.setInt(2, state);
455 ps.setLong(3, ReleaseConstants.DEFAULT_ID);
456
457 ps.executeUpdate();
458 }
459 finally {
460 DataAccess.cleanUp(con, ps);
461 }
462 }
463
464 private static final String _DELETE_TEMP_IMAGES_1 =
465 "delete from Image where imageId IN (SELECT articleImageId FROM " +
466 "JournalArticleImage where tempImage = TRUE)";
467
468 private static final String _DELETE_TEMP_IMAGES_2 =
469 "delete from JournalArticleImage where tempImage = TRUE";
470
471 private static Log _log = LogFactoryUtil.getLog(DBUpgrader.class);
472
473 }