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("Clear cache if upgrade process was run");
190 }
191
192 if (StartupHelperUtil.isUpgraded()) {
193 MultiVMPoolUtil.clear();
194 }
195 }
196
197 public static void verify() throws Exception {
198
199
200
201 Release release = ReleaseLocalServiceUtil.fetchRelease(
202 ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME);
203
204 if (release == null) {
205 release = ReleaseLocalServiceUtil.addRelease(
206 ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME,
207 ReleaseInfo.getParentBuildNumber());
208 }
209
210 _checkReleaseState(release.getState());
211
212
213
214 if (PropsValues.DATABASE_INDEXES_UPDATE_ON_STARTUP) {
215 StartupHelperUtil.setDropIndexes(true);
216
217 StartupHelperUtil.updateIndexes();
218 }
219 else if (StartupHelperUtil.isUpgraded()) {
220 StartupHelperUtil.updateIndexes();
221 }
222
223
224
225 if (PropsValues.VERIFY_DATABASE_TRANSACTIONS_DISABLED) {
226 _disableTransactions();
227 }
228
229 boolean newBuildNumber = false;
230
231 if (ReleaseInfo.getBuildNumber() > release.getBuildNumber()) {
232 newBuildNumber = true;
233 }
234
235 try {
236 StartupHelperUtil.verifyProcess(
237 newBuildNumber, release.isVerified());
238 }
239 catch (Exception e) {
240 _updateReleaseState(ReleaseConstants.STATE_VERIFY_FAILURE);
241
242 _log.error(
243 "Unable to execute verify process: " + e.getMessage(), e);
244
245 throw e;
246 }
247 finally {
248 if (PropsValues.VERIFY_DATABASE_TRANSACTIONS_DISABLED) {
249 _enableTransactions();
250 }
251 }
252
253
254
255 if (PropsValues.DATABASE_INDEXES_UPDATE_ON_STARTUP ||
256 StartupHelperUtil.isUpgraded()) {
257
258 StartupHelperUtil.updateIndexes(false);
259 }
260
261
262
263 boolean verified = StartupHelperUtil.isVerified();
264
265 if (release.isVerified()) {
266 verified = true;
267 }
268
269 release = ReleaseLocalServiceUtil.updateRelease(
270 release.getReleaseId(), ReleaseInfo.getParentBuildNumber(),
271 ReleaseInfo.getBuildDate(), verified);
272
273
274
275 CacheRegistryUtil.setActive(true);
276
277
278
279 Registry registry = RegistryUtil.getRegistry();
280
281 ServiceRegistrar<Release> serviceRegistrar =
282 registry.getServiceRegistrar(Release.class);
283
284 Map<String, Object> properties = new HashMap<>();
285
286 properties.put("build.date", release.getBuildDate());
287 properties.put("build.number", release.getBuildNumber());
288 properties.put("servlet.context.name", release.getServletContextName());
289
290 serviceRegistrar.registerService(Release.class, release, properties);
291 }
292
293 private static void _checkPermissionAlgorithm() throws Exception {
294 long count = _getResourceCodesCount();
295
296 if (count == 0) {
297 return;
298 }
299
300 StringBundler sb = new StringBundler(8);
301
302 sb.append("Permission conversion to algorithm 6 has not been ");
303 sb.append("completed. Please complete the conversion prior to ");
304 sb.append("starting the portal. The conversion process is ");
305 sb.append("available in portal versions starting with ");
306 sb.append(ReleaseInfo.RELEASE_5_2_3_BUILD_NUMBER);
307 sb.append(" and prior to ");
308 sb.append(ReleaseInfo.RELEASE_6_2_0_BUILD_NUMBER);
309 sb.append(".");
310
311 throw new IllegalStateException(sb.toString());
312 }
313
314 private static void _checkReleaseState(int state) throws Exception {
315 if (state == ReleaseConstants.STATE_GOOD) {
316 return;
317 }
318
319 StringBundler sb = new StringBundler(6);
320
321 sb.append("The database contains changes from a previous ");
322 sb.append("upgrade attempt that failed. Please restore the old ");
323 sb.append("database and file system and retry the upgrade. A ");
324 sb.append("patch may be required if the upgrade failed due to a");
325 sb.append(" bug or an unforeseen data permutation that resulted ");
326 sb.append("from a corrupt database.");
327
328 throw new IllegalStateException(sb.toString());
329 }
330
331 private static void _disableTransactions() throws Exception {
332 if (_log.isDebugEnabled()) {
333 _log.debug("Disable transactions");
334 }
335
336 PropsValues.SPRING_HIBERNATE_SESSION_DELEGATED = false;
337
338 Field field = ReflectionUtil.getDeclaredField(
339 ServiceBeanAopCacheManager.class, "_annotations");
340
341 field.set(
342 null,
343 new HashMap<MethodInvocation, Annotation[]>() {
344
345 @Override
346 public Annotation[] get(Object key) {
347 return _annotations;
348 }
349
350 private Annotation[] _annotations = new Annotation[] {
351 new Skip() {
352
353 @Override
354 public Class<? extends Annotation> annotationType() {
355 return Skip.class;
356 }
357
358 }
359 };
360
361 }
362 );
363 }
364
365 private static void _enableTransactions() throws Exception {
366 if (_log.isDebugEnabled()) {
367 _log.debug("Enable transactions");
368 }
369
370 PropsValues.SPRING_HIBERNATE_SESSION_DELEGATED = GetterUtil.getBoolean(
371 PropsUtil.get(PropsKeys.SPRING_HIBERNATE_SESSION_DELEGATED));
372
373 Field field = ReflectionUtil.getDeclaredField(
374 ServiceBeanAopCacheManager.class, "_annotations");
375
376 field.set(
377 null, new ConcurrentHashMap<MethodInvocation, Annotation[]>());
378
379 ServiceBeanAopCacheManagerUtil.reset();
380 }
381
382 private static int _getReleaseState() throws Exception {
383 Connection con = null;
384 PreparedStatement ps = null;
385 ResultSet rs = null;
386
387 try {
388 con = DataAccess.getConnection();
389
390 ps = con.prepareStatement(
391 "select state_ from Release_ where releaseId = ?");
392
393 ps.setLong(1, ReleaseConstants.DEFAULT_ID);
394
395 rs = ps.executeQuery();
396
397 if (rs.next()) {
398 return rs.getInt("state_");
399 }
400
401 throw new IllegalArgumentException(
402 "No Release exists with the primary key " +
403 ReleaseConstants.DEFAULT_ID);
404 }
405 finally {
406 DataAccess.cleanUp(con, ps, rs);
407 }
408 }
409
410 private static long _getResourceCodesCount() throws Exception {
411 Connection con = null;
412 PreparedStatement ps = null;
413 ResultSet rs = null;
414
415 try {
416 con = DataAccess.getConnection();
417
418 ps = con.prepareStatement("select count(*) from ResourceCode");
419
420 rs = ps.executeQuery();
421
422 if (rs.next()) {
423 int count = rs.getInt(1);
424
425 return count;
426 }
427
428 return 0;
429 }
430 catch (Exception e) {
431 return 0;
432 }
433 finally {
434 DataAccess.cleanUp(con, ps, rs);
435 }
436 }
437
438 private static void _updateCompanyKey() throws Exception {
439 DB db = DBFactoryUtil.getDB();
440
441 db.runSQL("update Company set key_ = null");
442 }
443
444 private static void _updateReleaseState(int state) throws Exception {
445 Connection con = null;
446 PreparedStatement ps = null;
447
448 try {
449 con = DataAccess.getConnection();
450
451 ps = con.prepareStatement(
452 "update Release_ set modifiedDate = ?, state_ = ? where " +
453 "releaseId = ?");
454
455 ps.setDate(1, new Date(System.currentTimeMillis()));
456 ps.setInt(2, state);
457 ps.setLong(3, ReleaseConstants.DEFAULT_ID);
458
459 ps.executeUpdate();
460 }
461 finally {
462 DataAccess.cleanUp(con, ps);
463 }
464 }
465
466 private static final Log _log = LogFactoryUtil.getLog(DBUpgrader.class);
467
468 }