001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.events;
016    
017    import com.liferay.portal.im.AIMConnector;
018    import com.liferay.portal.im.ICQConnector;
019    import com.liferay.portal.im.MSNConnector;
020    import com.liferay.portal.im.YMConnector;
021    import com.liferay.portal.jcr.JCRFactoryUtil;
022    import com.liferay.portal.kernel.dao.db.DB;
023    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
024    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
025    import com.liferay.portal.kernel.deploy.hot.HotDeployUtil;
026    import com.liferay.portal.kernel.events.SimpleAction;
027    import com.liferay.portal.kernel.log.Jdk14LogFactoryImpl;
028    import com.liferay.portal.kernel.log.Log;
029    import com.liferay.portal.kernel.log.LogFactoryUtil;
030    import com.liferay.portal.kernel.scheduler.SchedulerEngineUtil;
031    import com.liferay.portal.kernel.util.GetterUtil;
032    import com.liferay.portal.kernel.util.PropsKeys;
033    import com.liferay.portal.kernel.util.ReflectionUtil;
034    import com.liferay.portal.kernel.util.ThreadLocalRegistry;
035    import com.liferay.portal.pop.POPServerUtil;
036    import com.liferay.portal.search.lucene.LuceneHelperUtil;
037    import com.liferay.portal.util.PropsUtil;
038    import com.liferay.portal.util.PropsValues;
039    import com.liferay.portlet.documentlibrary.util.DocumentConversionUtil;
040    import com.liferay.util.ThirdPartyThreadLocalRegistry;
041    
042    import java.sql.Connection;
043    import java.sql.Statement;
044    
045    import java.util.Timer;
046    
047    /**
048     * @author Brian Wing Shun Chan
049     */
050    public class GlobalShutdownAction extends SimpleAction {
051    
052            public void run(String[] ids) {
053    
054                    // Hot deploy
055    
056                    HotDeployUtil.unregisterListeners();
057    
058                    // Instant messenger AIM
059    
060                    try {
061                            if (_log.isDebugEnabled()) {
062                                    _log.debug("Shutting down AIM");
063                            }
064    
065                            AIMConnector.disconnect();
066                    }
067                    catch (Exception e) {
068                    }
069    
070                    // Instant messenger ICQ
071    
072                    try {
073                            if (_log.isDebugEnabled()) {
074                                    _log.debug("Shutting down ICQ");
075                            }
076    
077                            ICQConnector.disconnect();
078                    }
079                    catch (Exception e) {
080                    }
081    
082                    // Instant messenger MSN
083    
084                    try {
085                            if (_log.isDebugEnabled()) {
086                                    _log.debug("Shutting down MSN");
087                            }
088    
089                            MSNConnector.disconnect();
090                    }
091                    catch (Exception e) {
092                    }
093    
094                    // Instant messenger YM
095    
096                    try {
097                            if (_log.isDebugEnabled()) {
098                                    _log.debug("Shutting down YM");
099                            }
100    
101                            YMConnector.disconnect();
102                    }
103                    catch (Exception e) {
104                    }
105    
106                    // JCR
107    
108                    try {
109                            if (_log.isDebugEnabled()) {
110                                    _log.debug("Shutting down JCR");
111                            }
112    
113                            JCRFactoryUtil.shutdown();
114                    }
115                    catch (Exception e) {
116                    }
117    
118                    // Lucene
119    
120                    LuceneHelperUtil.shutdown();
121    
122                    // OpenOffice
123    
124                    DocumentConversionUtil.disconnect();
125    
126                    // POP server
127    
128                    if (PropsValues.POP_SERVER_NOTIFICATIONS_ENABLED) {
129                            POPServerUtil.stop();
130                    }
131    
132                    // Scheduler
133    
134                    try {
135                            SchedulerEngineUtil.shutdown();
136                    }
137                    catch (Exception e) {
138                    }
139    
140                    // Thread local registry
141    
142                    ThirdPartyThreadLocalRegistry.resetThreadLocals();
143                    ThreadLocalRegistry.resetThreadLocals();
144    
145                    clearReferences("com.mysql.jdbc.Connection", "cancelTimer");
146                    clearReferences("org.apache.axis.utils.XMLUtils", "documentBuilder");
147                    //clearReferences("org.joni.StackMachine", "stacks");
148    
149                    // Hypersonic
150    
151                    DB db = DBFactoryUtil.getDB();
152    
153                    if (db.getType().equals(DB.TYPE_HYPERSONIC)) {
154                            try {
155                                    Connection connection = DataAccess.getConnection();
156    
157                                    Statement statement = connection.createStatement();
158    
159                                    statement.executeUpdate("SHUTDOWN");
160    
161                                    statement.close();
162                            }
163                            catch (Exception e) {
164                                    _log.error(e, e);
165                            }
166                    }
167    
168                    // Reset log to default JDK 1.4 logger. This will allow WARs dependent
169                    // on the portal to still log events after the portal WAR has been
170                    // destroyed.
171    
172                    try {
173                            LogFactoryUtil.setLogFactory(new Jdk14LogFactoryImpl());
174                    }
175                    catch (Exception e) {
176                    }
177    
178                    // Wait 1 second so Quartz threads can cleanly shutdown
179    
180                    try {
181                            Thread.sleep(1000);
182                    }
183                    catch (Exception e) {
184                            e.printStackTrace();
185                    }
186    
187                    // Programmatically exit
188    
189                    if (GetterUtil.getBoolean(PropsUtil.get(
190                                    PropsKeys.SHUTDOWN_PROGRAMMATICALLY_EXIT))) {
191    
192                            Thread currentThread = Thread.currentThread();
193    
194                            ThreadGroup threadGroup = currentThread.getThreadGroup();
195    
196                            for (int i = 0; i < 10; i++) {
197                                    if (threadGroup.getParent() == null) {
198                                            break;
199                                    }
200                                    else {
201                                            threadGroup = threadGroup.getParent();
202                                    }
203                            }
204    
205                            Thread[] threads = new Thread[threadGroup.activeCount() * 2];
206    
207                            threadGroup.enumerate(threads);
208    
209                            for (Thread thread : threads) {
210                                    if ((thread == null) || (thread == currentThread)) {
211                                            continue;
212                                    }
213    
214                                    try {
215                                            thread.interrupt();
216                                    }
217                                    catch (Exception e) {
218                                    }
219                            }
220    
221                            threadGroup.destroy();
222                    }
223            }
224    
225            protected void clearReferences(String className, String fieldName) {
226                    Thread currentThread = Thread.currentThread();
227    
228                    ClassLoader contextClassLoader =
229                            currentThread.getContextClassLoader();
230    
231                    Class<?> classObj = null;
232    
233                    try {
234                            classObj = contextClassLoader.loadClass(className);
235    
236                            return;
237                    }
238                    catch (Exception e) {
239                    }
240    
241                    Object fieldValue = ReflectionUtil.getFieldValue(classObj, fieldName);
242    
243                    if (fieldValue == null) {
244                            return;
245                    }
246    
247                    if (fieldValue instanceof ThreadLocal<?>) {
248                            ThreadLocal<?> threadLocal = (ThreadLocal<?>)fieldValue;
249    
250                            threadLocal.remove();
251                    }
252                    else if (fieldValue instanceof Timer) {
253                            Timer timer = (Timer)fieldValue;
254    
255                            timer.cancel();
256                    }
257            }
258    
259            private static Log _log = LogFactoryUtil.getLog(GlobalShutdownAction.class);
260    
261    }