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