1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.events;
24  
25  import com.liferay.lock.service.LockServiceUtil;
26  import com.liferay.portal.PortalException;
27  import com.liferay.portal.SystemException;
28  import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
29  import com.liferay.portal.kernel.cache.CacheRegistry;
30  import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
31  import com.liferay.portal.kernel.events.ActionException;
32  import com.liferay.portal.kernel.events.SimpleAction;
33  import com.liferay.portal.kernel.messaging.MessageBus;
34  import com.liferay.portal.kernel.messaging.MessageBusUtil;
35  import com.liferay.portal.kernel.messaging.sender.MessageSender;
36  import com.liferay.portal.kernel.messaging.sender.SynchronousMessageSender;
37  import com.liferay.portal.kernel.scheduler.SchedulerEngineUtil;
38  import com.liferay.portal.kernel.util.GetterUtil;
39  import com.liferay.portal.kernel.util.InstancePool;
40  import com.liferay.portal.kernel.util.ReleaseInfo;
41  import com.liferay.portal.model.CompanyConstants;
42  import com.liferay.portal.model.Release;
43  import com.liferay.portal.scheduler.SchedulerEngineProxy;
44  import com.liferay.portal.search.lucene.LuceneUtil;
45  import com.liferay.portal.service.ClassNameLocalServiceUtil;
46  import com.liferay.portal.service.ReleaseLocalServiceUtil;
47  import com.liferay.portal.tools.sql.DBUtil;
48  import com.liferay.portal.upgrade.UpgradeProcess;
49  import com.liferay.portal.util.PropsKeys;
50  import com.liferay.portal.util.PropsUtil;
51  import com.liferay.portal.velocity.LiferayResourceLoader;
52  import com.liferay.portal.verify.VerifyProcess;
53  
54  import java.io.IOException;
55  
56  import java.sql.SQLException;
57  
58  import javax.naming.NamingException;
59  
60  import org.apache.commons.collections.ExtendedProperties;
61  import org.apache.commons.logging.Log;
62  import org.apache.commons.logging.LogFactory;
63  import org.apache.velocity.app.Velocity;
64  import org.apache.velocity.runtime.RuntimeConstants;
65  
66  /**
67   * <a href="StartupAction.java.html"><b><i>View Source</i></b></a>
68   *
69   * @author Brian Wing Shun Chan
70   * @author Alexander Chow
71   *
72   */
73  public class StartupAction extends SimpleAction {
74  
75      public void run(String[] ids) throws ActionException {
76          try {
77              doRun(ids);
78          }
79          catch (RuntimeException re) {
80              throw re;
81          }
82          catch (Exception e) {
83              throw new ActionException(e);
84          }
85          finally {
86              LuceneUtil.checkLuceneDir(CompanyConstants.SYSTEM);
87          }
88      }
89  
90      protected void deleteTemporaryImages()
91          throws IOException, NamingException, SQLException {
92  
93          DBUtil dbUtil = DBUtil.getInstance();
94  
95          dbUtil.runSQL(_DELETE_TEMP_IMAGES_1);
96          dbUtil.runSQL(_DELETE_TEMP_IMAGES_2);
97      }
98  
99      protected void doRun(String[] ids) throws PortalException, SystemException {
100 
101         // Print release information
102 
103         System.out.println("Starting " + ReleaseInfo.getReleaseInfo());
104 
105         // Clear locks
106 
107         try {
108             LockServiceUtil.clear();
109         }
110         catch (Exception e) {
111             _log.error(e, e);
112         }
113 
114         // Add shutdown hook
115 
116         Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownHook()));
117 
118         // Velocity
119 
120         LiferayResourceLoader.setListeners(PropsUtil.getArray(
121             PropsKeys.VELOCITY_ENGINE_RESOURCE_LISTENERS));
122 
123         ExtendedProperties props = new ExtendedProperties();
124 
125         props.setProperty(RuntimeConstants.RESOURCE_LOADER, "servlet");
126 
127         props.setProperty(
128             "servlet." + RuntimeConstants.RESOURCE_LOADER + ".class",
129             LiferayResourceLoader.class.getName());
130 
131         props.setProperty(
132             RuntimeConstants.RESOURCE_MANAGER_CLASS,
133             PropsUtil.get(PropsKeys.VELOCITY_ENGINE_RESOURCE_MANAGER));
134 
135         props.setProperty(
136             RuntimeConstants.RESOURCE_MANAGER_CACHE_CLASS,
137             PropsUtil.get(PropsKeys.VELOCITY_ENGINE_RESOURCE_MANAGER_CACHE));
138 
139         props.setProperty(
140             "velocimacro.library",
141             PropsUtil.get(PropsKeys.VELOCITY_ENGINE_VELOCIMACRO_LIBRARY));
142 
143         props.setProperty(
144             RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
145             PropsUtil.get(PropsKeys.VELOCITY_ENGINE_LOGGER));
146 
147         props.setProperty(
148             "runtime.log.logsystem.log4j.category",
149             PropsUtil.get(PropsKeys.VELOCITY_ENGINE_LOGGER_CATEGORY));
150 
151         Velocity.setExtendedProperties(props);
152 
153         try {
154             Velocity.init();
155         }
156         catch (Exception e) {
157             _log.error(e, e);
158         }
159 
160         // Disable database caching before upgrade
161 
162         CacheRegistry.setActive(false);
163 
164         // Upgrade
165 
166         int buildNumber = ReleaseLocalServiceUtil.getBuildNumberOrCreate();
167 
168         if (buildNumber < ReleaseInfo.RELEASE_4_2_1_BUILD_NUMBER) {
169             String msg = "You must first upgrade to Liferay Portal 4.2.1";
170 
171             _log.fatal(msg);
172 
173             throw new RuntimeException(msg);
174         }
175 
176         boolean ranUpgradeProcess = false;
177 
178         String[] upgradeProcesses = PropsUtil.getArray(
179             PropsKeys.UPGRADE_PROCESSES);
180 
181         for (int i = 0; i < upgradeProcesses.length; i++) {
182             if (_log.isDebugEnabled()) {
183                 _log.debug("Initializing upgrade " + upgradeProcesses[i]);
184             }
185 
186             UpgradeProcess upgradeProcess = (UpgradeProcess)InstancePool.get(
187                 upgradeProcesses[i]);
188 
189             if (upgradeProcess == null) {
190                 _log.error(upgradeProcesses[i] + " cannot be found");
191 
192                 continue;
193             }
194 
195             if ((upgradeProcess.getThreshold() == 0) ||
196                 (upgradeProcess.getThreshold() > buildNumber)) {
197 
198                 if (_log.isInfoEnabled()) {
199                     _log.info("Running upgrade " + upgradeProcesses[i]);
200                 }
201 
202                 upgradeProcess.upgrade();
203 
204                 if (_log.isInfoEnabled()) {
205                     _log.info("Finished upgrade " + upgradeProcesses[i]);
206                 }
207 
208                 ranUpgradeProcess = true;
209             }
210             else {
211                 if (_log.isDebugEnabled()) {
212                     _log.debug(
213                         "Upgrade threshold " + upgradeProcess.getThreshold() +
214                             " will not trigger upgrade");
215 
216                     _log.debug("Skipping upgrade " + upgradeProcesses[i]);
217                 }
218             }
219         }
220 
221         // Class names
222 
223         ClassNameLocalServiceUtil.checkClassNames();
224 
225         // Delete temporary images
226 
227         try {
228             deleteTemporaryImages();
229         }
230         catch (Exception e) {
231             _log.error(e, e);
232         }
233 
234         // Update indexes
235 
236         if (ranUpgradeProcess) {
237             try {
238                 DBUtil.getInstance().runSQLTemplate("indexes.sql", false);
239             }
240             catch (Exception e) {
241                 _log.error(e, e);
242             }
243         }
244 
245         // Enable database caching after upgrade
246 
247         CacheRegistry.setActive(true);
248 
249         // Clear the caches only if the upgrade process was run
250 
251         if (ranUpgradeProcess) {
252             MultiVMPoolUtil.clear();
253         }
254 
255         // Messaging
256 
257         MessageBus messageBus = (MessageBus)PortalBeanLocatorUtil.locate(
258             MessageBus.class.getName());
259         MessageSender messageSender =
260             (MessageSender)PortalBeanLocatorUtil.locate(
261                 MessageSender.class.getName());
262         SynchronousMessageSender synchronousMessageSender =
263             (SynchronousMessageSender)PortalBeanLocatorUtil.locate(
264                 SynchronousMessageSender.class.getName());
265 
266         MessageBusUtil.init(
267             messageBus, messageSender, synchronousMessageSender);
268 
269         // Scheduler
270 
271         SchedulerEngineUtil.init(new SchedulerEngineProxy());
272 
273         SchedulerEngineUtil.start();
274 
275         // Verify
276 
277         Release release = ReleaseLocalServiceUtil.getRelease();
278 
279         int verifyFrequency = GetterUtil.getInteger(
280             PropsUtil.get(PropsKeys.VERIFY_FREQUENCY));
281         boolean verified = release.isVerified();
282 
283         if ((verifyFrequency == VerifyProcess.ALWAYS) ||
284             ((verifyFrequency == VerifyProcess.ONCE) && !verified) ||
285             (ranUpgradeProcess)) {
286 
287             String[] verifyProcesses = PropsUtil.getArray(
288                 PropsKeys.VERIFY_PROCESSES);
289 
290             for (int i = 0; i < verifyProcesses.length; i++) {
291                 if (_log.isDebugEnabled()) {
292                     _log.debug(
293                         "Initializing verification " + verifyProcesses[i]);
294                 }
295 
296                 try {
297                     VerifyProcess verifyProcess = (VerifyProcess)Class.forName(
298                         verifyProcesses[i]).newInstance();
299 
300                     if (_log.isInfoEnabled()) {
301                         _log.info("Running verification " + verifyProcesses[i]);
302                     }
303 
304                     verifyProcess.verify();
305 
306                     if (_log.isInfoEnabled()) {
307                         _log.info(
308                             "Finished verification " + verifyProcesses[i]);
309                     }
310 
311                     verified = true;
312                 }
313                 catch (ClassNotFoundException cnfe) {
314                     _log.error(verifyProcesses[i] + " cannot be found");
315                 }
316                 catch (IllegalAccessException iae) {
317                     _log.error(verifyProcesses[i] + " cannot be accessed");
318                 }
319                 catch (InstantiationException ie) {
320                     _log.error(verifyProcesses[i] + " cannot be initiated");
321                 }
322             }
323         }
324 
325         // Update release
326 
327         ReleaseLocalServiceUtil.updateRelease(verified);
328     }
329 
330     private static final String _DELETE_TEMP_IMAGES_1 =
331         "DELETE FROM Image WHERE imageId IN (SELECT articleImageId FROM " +
332             "JournalArticleImage WHERE tempImage = TRUE)";
333 
334     private static final String _DELETE_TEMP_IMAGES_2 =
335         "DELETE FROM JournalArticleImage where tempImage = TRUE";
336 
337     private static Log _log = LogFactory.getLog(StartupAction.class);
338 
339 }