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.exception.PortalException;
025 import com.liferay.portal.kernel.log.Log;
026 import com.liferay.portal.kernel.log.LogFactoryUtil;
027 import com.liferay.portal.kernel.spring.aop.Skip;
028 import com.liferay.portal.kernel.util.GetterUtil;
029 import com.liferay.portal.kernel.util.PropsKeys;
030 import com.liferay.portal.kernel.util.ReflectionUtil;
031 import com.liferay.portal.kernel.util.ReleaseInfo;
032 import com.liferay.portal.kernel.util.StringBundler;
033 import com.liferay.portal.kernel.util.Time;
034 import com.liferay.portal.model.Release;
035 import com.liferay.portal.model.ReleaseConstants;
036 import com.liferay.portal.service.ClassNameLocalServiceUtil;
037 import com.liferay.portal.service.ReleaseLocalServiceUtil;
038 import com.liferay.portal.service.ResourceActionLocalServiceUtil;
039 import com.liferay.portal.service.ResourceCodeLocalServiceUtil;
040 import com.liferay.portal.spring.aop.ServiceMethodAnnotationCache;
041 import com.liferay.portal.util.InitUtil;
042 import com.liferay.portal.util.PropsUtil;
043 import com.liferay.portal.util.PropsValues;
044 import com.liferay.util.dao.orm.CustomSQLUtil;
045
046 import java.lang.annotation.Annotation;
047 import java.lang.reflect.Field;
048
049 import java.sql.Connection;
050 import java.sql.Date;
051 import java.sql.PreparedStatement;
052 import java.sql.ResultSet;
053
054 import java.util.HashMap;
055 import java.util.concurrent.ConcurrentHashMap;
056
057 import org.aopalliance.intercept.MethodInvocation;
058
059 import org.apache.commons.lang.time.StopWatch;
060
061
065 public class DBUpgrader {
066
067 public static void main(String[] args) {
068 try {
069 StopWatch stopWatch = new StopWatch();
070
071 stopWatch.start();
072
073 InitUtil.initWithSpring();
074
075 upgrade();
076 verify();
077
078 System.out.println(
079 "\nSuccessfully completed upgrade process in " +
080 (stopWatch.getTime() / Time.SECOND) + " seconds.");
081
082 System.exit(0);
083 }
084 catch (Exception e) {
085 e.printStackTrace();
086
087 System.exit(1);
088 }
089 }
090
091 public static void upgrade() throws Exception {
092
093
094
095 if (_log.isDebugEnabled()) {
096 _log.debug("Disable cache registry");
097 }
098
099 CacheRegistryUtil.setActive(false);
100
101
102
103 int buildNumber = ReleaseLocalServiceUtil.getBuildNumberOrCreate();
104
105 if (buildNumber > ReleaseInfo.getParentBuildNumber()) {
106 StringBundler sb = new StringBundler(6);
107
108 sb.append("Attempting to deploy an older Liferay Portal version. ");
109 sb.append("Current build version is ");
110 sb.append(buildNumber);
111 sb.append(" and attempting to deploy version ");
112 sb.append(ReleaseInfo.getParentBuildNumber());
113 sb.append(".");
114
115 throw new IllegalStateException(sb.toString());
116 }
117 else if (buildNumber < ReleaseInfo.RELEASE_5_0_0_BUILD_NUMBER) {
118 String msg = "You must first upgrade to Liferay Portal 5.0.0";
119
120 System.out.println(msg);
121
122 throw new RuntimeException(msg);
123 }
124
125
126
127 CustomSQLUtil.reloadCustomSQL();
128 SQLTransformer.reloadSQLTransformer();
129
130
131
132 if (_log.isDebugEnabled()) {
133 _log.debug("Update build " + buildNumber);
134 }
135
136 _checkReleaseState();
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("Check resource codes");
186 }
187
188 ResourceCodeLocalServiceUtil.checkResourceCodes();
189
190
191
192 if (_log.isDebugEnabled()) {
193 _log.debug("Delete temporary images");
194 }
195
196 _deleteTempImages();
197
198
199
200 if (_log.isDebugEnabled()) {
201 _log.debug("Clear cache if upgrade process was run");
202 }
203
204 if (StartupHelperUtil.isUpgraded()) {
205 MultiVMPoolUtil.clear();
206 }
207 }
208
209 public static void verify() throws Exception {
210
211
212
213 Release release = null;
214
215 try {
216 release = ReleaseLocalServiceUtil.getRelease(
217 ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME,
218 ReleaseInfo.getParentBuildNumber());
219 }
220 catch (PortalException pe) {
221 release = ReleaseLocalServiceUtil.addRelease(
222 ReleaseConstants.DEFAULT_SERVLET_CONTEXT_NAME,
223 ReleaseInfo.getParentBuildNumber());
224 }
225
226 _checkReleaseState();
227
228
229
230 if (PropsValues.DATABASE_INDEXES_UPDATE_ON_STARTUP) {
231 StartupHelperUtil.setDropIndexes(true);
232
233 StartupHelperUtil.updateIndexes();
234 }
235 else if (StartupHelperUtil.isUpgraded()) {
236 StartupHelperUtil.updateIndexes();
237 }
238
239
240
241 if (PropsValues.VERIFY_DATABASE_TRANSACTIONS_DISABLED) {
242 _disableTransactions();
243 }
244
245 try {
246 StartupHelperUtil.verifyProcess(release.isVerified());
247 }
248 catch (Exception e) {
249 _updateReleaseState(ReleaseConstants.STATE_VERIFY_FAILURE);
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 _checkReleaseState() throws Exception {
285 int state = _getReleaseState();
286
287 if (state == ReleaseConstants.STATE_GOOD) {
288 return;
289 }
290
291 StringBundler sb = new StringBundler(6);
292
293 sb.append("The database contains changes from a previous ");
294 sb.append("upgrade attempt that failed. Please restore the old ");
295 sb.append("database and file system and retry the upgrade. A ");
296 sb.append("patch may be required if the upgrade failed due to a");
297 sb.append(" bug or an unforeseen data permutation that resulted ");
298 sb.append("from a corrupt database.");
299
300 throw new IllegalStateException(sb.toString());
301 }
302
303 private static void _deleteTempImages() throws Exception {
304 DB db = DBFactoryUtil.getDB();
305
306 db.runSQL(_DELETE_TEMP_IMAGES_1);
307 db.runSQL(_DELETE_TEMP_IMAGES_2);
308 }
309
310 private static void _disableTransactions() throws Exception {
311 if (_log.isDebugEnabled()) {
312 _log.debug("Disable transactions");
313 }
314
315 PropsValues.SPRING_HIBERNATE_SESSION_DELEGATED = false;
316
317 Field field = ReflectionUtil.getDeclaredField(
318 ServiceMethodAnnotationCache.class, "_annotations");
319
320 field.set(
321 null,
322 new HashMap<MethodInvocation, Annotation[]>() {
323
324 @Override
325 public Annotation[] get(Object key) {
326 return _annotations;
327 }
328
329 private Annotation[] _annotations = new Annotation[] {
330 new Skip() {
331
332 @Override
333 public Class<? extends Annotation> annotationType() {
334 return Skip.class;
335 }
336
337 }
338 };
339
340 }
341 );
342 }
343
344 private static void _enableTransactions() throws Exception {
345 if (_log.isDebugEnabled()) {
346 _log.debug("Enable transactions");
347 }
348
349 PropsValues.SPRING_HIBERNATE_SESSION_DELEGATED = GetterUtil.getBoolean(
350 PropsUtil.get(PropsKeys.SPRING_HIBERNATE_SESSION_DELEGATED));
351
352 Field field = ReflectionUtil.getDeclaredField(
353 ServiceMethodAnnotationCache.class, "_annotations");
354
355 field.set(
356 null, new ConcurrentHashMap<MethodInvocation, Annotation[]>());
357 }
358
359 private static int _getReleaseState() throws Exception {
360 Connection con = null;
361 PreparedStatement ps = null;
362 ResultSet rs = null;
363
364 try {
365 con = DataAccess.getConnection();
366
367 ps = con.prepareStatement(
368 "select state_ from Release_ where releaseId = ?");
369
370 ps.setLong(1, ReleaseConstants.DEFAULT_ID);
371
372 rs = ps.executeQuery();
373
374 if (rs.next()) {
375 return rs.getInt("state_");
376 }
377
378 throw new IllegalArgumentException(
379 "No Release exists with the primary key " +
380 ReleaseConstants.DEFAULT_ID);
381 }
382 finally {
383 DataAccess.cleanUp(con, ps, rs);
384 }
385 }
386
387 private static void _updateCompanyKey() throws Exception {
388 DB db = DBFactoryUtil.getDB();
389
390 db.runSQL("update Company set key_ = null");
391 }
392
393 private static void _updateReleaseState(int state) throws Exception {
394 Connection con = null;
395 PreparedStatement ps = null;
396
397 try {
398 con = DataAccess.getConnection();
399
400 ps = con.prepareStatement(
401 "update Release_ set modifiedDate = ?, state_ = ? where " +
402 "releaseId = ?");
403
404 ps.setDate(1, new Date(System.currentTimeMillis()));
405 ps.setInt(2, state);
406 ps.setLong(3, ReleaseConstants.DEFAULT_ID);
407
408 ps.executeUpdate();
409 }
410 finally {
411 DataAccess.cleanUp(con, ps);
412 }
413 }
414
415 private static final String _DELETE_TEMP_IMAGES_1 =
416 "delete from Image where imageId IN (SELECT articleImageId FROM " +
417 "JournalArticleImage where tempImage = TRUE)";
418
419 private static final String _DELETE_TEMP_IMAGES_2 =
420 "delete from JournalArticleImage where tempImage = TRUE";
421
422 private static Log _log = LogFactoryUtil.getLog(DBUpgrader.class);
423
424 }