001    /**
002     * Copyright (c) 2000-present 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.deploy.RequiredPluginsUtil;
018    import com.liferay.portal.fabric.server.FabricServerUtil;
019    import com.liferay.portal.im.AIMConnector;
020    import com.liferay.portal.im.ICQConnector;
021    import com.liferay.portal.im.MSNConnector;
022    import com.liferay.portal.im.YMConnector;
023    import com.liferay.portal.jcr.JCRFactoryUtil;
024    import com.liferay.portal.kernel.dao.db.DB;
025    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
026    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
027    import com.liferay.portal.kernel.deploy.auto.AutoDeployDir;
028    import com.liferay.portal.kernel.deploy.auto.AutoDeployUtil;
029    import com.liferay.portal.kernel.deploy.hot.HotDeployUtil;
030    import com.liferay.portal.kernel.deploy.sandbox.SandboxDeployDir;
031    import com.liferay.portal.kernel.deploy.sandbox.SandboxDeployUtil;
032    import com.liferay.portal.kernel.events.SimpleAction;
033    import com.liferay.portal.kernel.executor.PortalExecutorManagerUtil;
034    import com.liferay.portal.kernel.javadoc.JavadocManagerUtil;
035    import com.liferay.portal.kernel.log.Jdk14LogFactoryImpl;
036    import com.liferay.portal.kernel.log.Log;
037    import com.liferay.portal.kernel.log.LogFactoryUtil;
038    import com.liferay.portal.kernel.messaging.MessageBusUtil;
039    import com.liferay.portal.kernel.resiliency.mpi.MPIHelperUtil;
040    import com.liferay.portal.kernel.scheduler.SchedulerEngineHelperUtil;
041    import com.liferay.portal.kernel.template.TemplateManagerUtil;
042    import com.liferay.portal.kernel.template.TemplateResourceLoaderUtil;
043    import com.liferay.portal.kernel.util.CentralizedThreadLocal;
044    import com.liferay.portal.kernel.util.GetterUtil;
045    import com.liferay.portal.kernel.util.PropsKeys;
046    import com.liferay.portal.kernel.util.StringPool;
047    import com.liferay.portal.search.lucene.LuceneHelperUtil;
048    import com.liferay.portal.util.PropsUtil;
049    import com.liferay.portal.util.PropsValues;
050    import com.liferay.portlet.documentlibrary.util.DocumentConversionUtil;
051    import com.liferay.util.ThirdPartyThreadLocalRegistry;
052    
053    import java.sql.Connection;
054    import java.sql.Statement;
055    
056    /**
057     * @author Brian Wing Shun Chan
058     */
059    public class GlobalShutdownAction extends SimpleAction {
060    
061            @Override
062            public void run(String[] ids) {
063    
064                    // Lower shutdown levels have dependences on higher levels, therefore
065                    // lower ones need to shutdown before higher ones. Components within the
066                    // same shutdown level should not depend on each other.
067    
068                    shutdownLevel1();
069                    shutdownLevel2();
070                    shutdownLevel3();
071                    shutdownLevel4();
072                    shutdownLevel5();
073                    shutdownLevel6();
074                    shutdownLevel7();
075            }
076    
077            protected ThreadGroup getThreadGroup() {
078                    Thread currentThread = Thread.currentThread();
079    
080                    ThreadGroup threadGroup = currentThread.getThreadGroup();
081    
082                    for (int i = 0; i < 10; i++) {
083                            if (threadGroup.getParent() == null) {
084                                    break;
085                            }
086                            else {
087                                    threadGroup = threadGroup.getParent();
088                            }
089                    }
090    
091                    return threadGroup;
092            }
093    
094            protected Thread[] getThreads(ThreadGroup threadGroup) {
095                    Thread[] threads = new Thread[threadGroup.activeCount() * 2];
096    
097                    threadGroup.enumerate(threads);
098    
099                    return threads;
100            }
101    
102            protected void shutdownLevel1() {
103    
104                    // Instant messenger AIM
105    
106                    try {
107                            if (_log.isDebugEnabled()) {
108                                    _log.debug("Shutting down AIM");
109                            }
110    
111                            AIMConnector.disconnect();
112                    }
113                    catch (Exception e) {
114                    }
115    
116                    // Instant messenger ICQ
117    
118                    try {
119                            if (_log.isDebugEnabled()) {
120                                    _log.debug("Shutting down ICQ");
121                            }
122    
123                            ICQConnector.disconnect();
124                    }
125                    catch (Exception e) {
126                    }
127    
128                    // Instant messenger MSN
129    
130                    try {
131                            if (_log.isDebugEnabled()) {
132                                    _log.debug("Shutting down MSN");
133                            }
134    
135                            MSNConnector.disconnect();
136                    }
137                    catch (Exception e) {
138                    }
139    
140                    // Instant messenger YM
141    
142                    try {
143                            if (_log.isDebugEnabled()) {
144                                    _log.debug("Shutting down YM");
145                            }
146    
147                            YMConnector.disconnect();
148                    }
149                    catch (Exception e) {
150                    }
151    
152                    // Javadoc
153    
154                    JavadocManagerUtil.unload(StringPool.BLANK);
155    
156                    // JCR
157    
158                    try {
159                            if (_log.isDebugEnabled()) {
160                                    _log.debug("Shutting down JCR");
161                            }
162    
163                            JCRFactoryUtil.shutdown();
164                    }
165                    catch (Exception e) {
166                    }
167    
168                    // Lucene
169    
170                    LuceneHelperUtil.shutdown();
171    
172                    // OpenOffice
173    
174                    DocumentConversionUtil.disconnect();
175    
176                    // Plugins
177    
178                    RequiredPluginsUtil.stopCheckingRequiredPlugins();
179    
180                    // Scheduler engine
181    
182                    try {
183                            SchedulerEngineHelperUtil.shutdown();
184                    }
185                    catch (Exception e) {
186                    }
187    
188                    // Wait 1 second so Quartz threads can cleanly shutdown
189    
190                    try {
191                            Thread.sleep(1000);
192                    }
193                    catch (Exception e) {
194                            e.printStackTrace();
195                    }
196    
197                    // Template manager
198    
199                    try {
200                            TemplateManagerUtil.destroy();
201                    }
202                    catch (Exception e) {
203                    }
204    
205                    // Template resource loader
206    
207                    try {
208                            TemplateResourceLoaderUtil.destroy();
209                    }
210                    catch (Exception e) {
211                    }
212            }
213    
214            protected void shutdownLevel2() {
215    
216                    // Auto deploy
217    
218                    AutoDeployUtil.unregisterDir(AutoDeployDir.DEFAULT_NAME);
219    
220                    // Hot deploy
221    
222                    HotDeployUtil.unregisterListeners();
223    
224                    // Sandbox deploy
225    
226                    SandboxDeployUtil.unregisterDir(SandboxDeployDir.DEFAULT_NAME);
227            }
228    
229            protected void shutdownLevel3() {
230    
231                    // Messaging
232    
233                    MessageBusUtil.shutdown(true);
234    
235                    // Portal fabric
236    
237                    if (PropsValues.PORTAL_FABRIC_ENABLED) {
238                            try {
239                                    FabricServerUtil.stop();
240                            }
241                            catch (Exception e) {
242                                    _log.error("Unable to stop fabric server", e);
243                            }
244                    }
245            }
246    
247            protected void shutdownLevel4() {
248    
249                    // Hypersonic
250    
251                    DB db = DBFactoryUtil.getDB();
252    
253                    String dbType = db.getType();
254    
255                    if (dbType.equals(DB.TYPE_HYPERSONIC)) {
256                            Connection connection = null;
257                            Statement statement = null;
258    
259                            try {
260                                    connection = DataAccess.getConnection();
261    
262                                    statement = connection.createStatement();
263    
264                                    statement.executeUpdate("SHUTDOWN");
265                            }
266                            catch (Exception e) {
267                                    _log.error(e, e);
268                            }
269                            finally {
270                                    DataAccess.cleanUp(connection, statement);
271                            }
272                    }
273    
274                    // Portal Resiliency
275    
276                    MPIHelperUtil.shutdown();
277            }
278    
279            protected void shutdownLevel5() {
280    
281                    // Portal executors
282    
283                    PortalExecutorManagerUtil.shutdown(true);
284            }
285    
286            protected void shutdownLevel6() {
287    
288                    // Reset log to default JDK 1.4 logger. This will allow WARs dependent
289                    // on the portal to still log events after the portal WAR has been
290                    // destroyed.
291    
292                    try {
293                            LogFactoryUtil.setLogFactory(new Jdk14LogFactoryImpl());
294                    }
295                    catch (Exception e) {
296                    }
297    
298                    // Thread local registry
299    
300                    ThirdPartyThreadLocalRegistry.resetThreadLocals();
301                    CentralizedThreadLocal.clearShortLivedThreadLocals();
302            }
303    
304            protected void shutdownLevel7() {
305    
306                    // Programmatically exit
307    
308                    if (GetterUtil.getBoolean(
309                                    PropsUtil.get(PropsKeys.SHUTDOWN_PROGRAMMATICALLY_EXIT))) {
310    
311                            Thread currentThread = Thread.currentThread();
312    
313                            ThreadGroup threadGroup = getThreadGroup();
314    
315                            Thread[] threads = getThreads(threadGroup);
316    
317                            for (Thread thread : threads) {
318                                    if ((thread == null) || (thread == currentThread)) {
319                                            continue;
320                                    }
321    
322                                    try {
323                                            thread.interrupt();
324                                    }
325                                    catch (Exception e) {
326                                    }
327                            }
328    
329                            threadGroup.destroy();
330                    }
331            }
332    
333            private static Log _log = LogFactoryUtil.getLog(GlobalShutdownAction.class);
334    
335    }