1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.events;
16  
17  import com.liferay.portal.im.AIMConnector;
18  import com.liferay.portal.im.ICQConnector;
19  import com.liferay.portal.im.MSNConnector;
20  import com.liferay.portal.im.YMConnector;
21  import com.liferay.portal.jcr.JCRFactoryUtil;
22  import com.liferay.portal.kernel.dao.db.DB;
23  import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
24  import com.liferay.portal.kernel.dao.jdbc.DataAccess;
25  import com.liferay.portal.kernel.deploy.hot.HotDeployUtil;
26  import com.liferay.portal.kernel.events.SimpleAction;
27  import com.liferay.portal.kernel.log.Jdk14LogFactoryImpl;
28  import com.liferay.portal.kernel.log.Log;
29  import com.liferay.portal.kernel.log.LogFactoryUtil;
30  import com.liferay.portal.kernel.scheduler.SchedulerEngineUtil;
31  import com.liferay.portal.kernel.util.GetterUtil;
32  import com.liferay.portal.kernel.util.PropsKeys;
33  import com.liferay.portal.kernel.util.ReflectionUtil;
34  import com.liferay.portal.kernel.util.ThreadLocalRegistry;
35  import com.liferay.portal.pop.POPServerUtil;
36  import com.liferay.portal.search.lucene.LuceneHelperUtil;
37  import com.liferay.portal.util.PropsUtil;
38  import com.liferay.portal.util.PropsValues;
39  import com.liferay.portlet.documentlibrary.util.DocumentConversionUtil;
40  import com.liferay.util.ThirdPartyThreadLocalRegistry;
41  
42  import java.sql.Connection;
43  import java.sql.Statement;
44  
45  import java.util.Timer;
46  
47  /**
48   * <a href="GlobalShutdownAction.java.html"><b><i>View Source</i></b></a>
49   *
50   * @author Brian Wing Shun Chan
51   */
52  public class GlobalShutdownAction extends SimpleAction {
53  
54      public void run(String[] ids) {
55  
56          // Hot deploy
57  
58          HotDeployUtil.unregisterListeners();
59  
60          // Instant messenger AIM
61  
62          try {
63              if (_log.isDebugEnabled()) {
64                  _log.debug("Shutting down AIM");
65              }
66  
67              AIMConnector.disconnect();
68          }
69          catch (Exception e) {
70          }
71  
72          // Instant messenger ICQ
73  
74          try {
75              if (_log.isDebugEnabled()) {
76                  _log.debug("Shutting down ICQ");
77              }
78  
79              ICQConnector.disconnect();
80          }
81          catch (Exception e) {
82          }
83  
84          // Instant messenger MSN
85  
86          try {
87              if (_log.isDebugEnabled()) {
88                  _log.debug("Shutting down MSN");
89              }
90  
91              MSNConnector.disconnect();
92          }
93          catch (Exception e) {
94          }
95  
96          // Instant messenger YM
97  
98          try {
99              if (_log.isDebugEnabled()) {
100                 _log.debug("Shutting down YM");
101             }
102 
103             YMConnector.disconnect();
104         }
105         catch (Exception e) {
106         }
107 
108         // JCR
109 
110         try {
111             if (_log.isDebugEnabled()) {
112                 _log.debug("Shutting down JCR");
113             }
114 
115             JCRFactoryUtil.shutdown();
116         }
117         catch (Exception e) {
118         }
119 
120         // Lucene
121 
122         LuceneHelperUtil.shutdown();
123 
124         // OpenOffice
125 
126         DocumentConversionUtil.disconnect();
127 
128         // POP server
129 
130         if (PropsValues.POP_SERVER_NOTIFICATIONS_ENABLED) {
131             POPServerUtil.stop();
132         }
133 
134         // Scheduler
135 
136         try {
137             SchedulerEngineUtil.shutdown();
138         }
139         catch (Exception e) {
140         }
141 
142         // Thread local registry
143 
144         ThirdPartyThreadLocalRegistry.resetThreadLocals();
145         ThreadLocalRegistry.resetThreadLocals();
146 
147         clearReferences("com.mysql.jdbc.Connection", "cancelTimer");
148         clearReferences("org.apache.axis.utils.XMLUtils", "documentBuilder");
149         //clearReferences("org.joni.StackMachine", "stacks");
150 
151         // Hypersonic
152 
153         DB db = DBFactoryUtil.getDB();
154 
155         if (db.getType().equals(DB.TYPE_HYPERSONIC)) {
156             try {
157                 Connection connection = DataAccess.getConnection();
158 
159                 Statement statement = connection.createStatement();
160 
161                 statement.executeUpdate("SHUTDOWN");
162 
163                 statement.close();
164             }
165             catch (Exception e) {
166                 _log.error(e, e);
167             }
168         }
169 
170         // Reset log to default JDK 1.4 logger. This will allow WARs dependent
171         // on the portal to still log events after the portal WAR has been
172         // destroyed.
173 
174         try {
175             LogFactoryUtil.setLogFactory(new Jdk14LogFactoryImpl());
176         }
177         catch (Exception e) {
178         }
179 
180         // Wait 1 second so Quartz threads can cleanly shutdown
181 
182         try {
183             Thread.sleep(1000);
184         }
185         catch (Exception e) {
186             e.printStackTrace();
187         }
188 
189         // Programmatically exit
190 
191         if (GetterUtil.getBoolean(PropsUtil.get(
192                 PropsKeys.SHUTDOWN_PROGRAMMATICALLY_EXIT))) {
193 
194             Thread currentThread = Thread.currentThread();
195 
196             ThreadGroup threadGroup = currentThread.getThreadGroup();
197 
198             for (int i = 0; i < 10; i++) {
199                 if (threadGroup.getParent() == null) {
200                     break;
201                 }
202                 else {
203                     threadGroup = threadGroup.getParent();
204                 }
205             }
206 
207             Thread[] threads = new Thread[threadGroup.activeCount() * 2];
208 
209             threadGroup.enumerate(threads);
210 
211             for (Thread thread : threads) {
212                 if ((thread == null) || (thread == currentThread)) {
213                     continue;
214                 }
215 
216                 try {
217                     thread.interrupt();
218                 }
219                 catch (Exception e) {
220                 }
221             }
222 
223             threadGroup.destroy();
224         }
225     }
226 
227     protected void clearReferences(String className, String fieldName) {
228         Thread currentThread = Thread.currentThread();
229 
230         ClassLoader contextClassLoader =
231             currentThread.getContextClassLoader();
232 
233         Class<?> classObj = null;
234 
235         try {
236             classObj = contextClassLoader.loadClass(className);
237 
238             return;
239         }
240         catch (Exception e) {
241         }
242 
243         Object fieldValue = ReflectionUtil.getFieldValue(classObj, fieldName);
244 
245         if (fieldValue == null) {
246             return;
247         }
248 
249         if (fieldValue instanceof ThreadLocal<?>) {
250             ThreadLocal<?> threadLocal = (ThreadLocal<?>)fieldValue;
251 
252             threadLocal.remove();
253         }
254         else if (fieldValue instanceof Timer) {
255             Timer timer = (Timer)fieldValue;
256 
257             timer.cancel();
258         }
259     }
260 
261     private static Log _log = LogFactoryUtil.getLog(GlobalShutdownAction.class);
262 
263 }