KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > core > shutdown > ShutdownManager


1 // The contents of this file are subject to the Mozilla Public License Version
2
// 1.1
3
//(the "License"); you may not use this file except in compliance with the
4
//License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
5
//
6
//Software distributed under the License is distributed on an "AS IS" basis,
7
//WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
8
//for the specific language governing rights and
9
//limitations under the License.
10
//
11
//The Original Code is "The Columba Project"
12
//
13
//The Initial Developers of the Original Code are Frederik Dietz and Timo
14
// Stich.
15
//Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
16
//
17
//All Rights Reserved.
18
package org.columba.core.shutdown;
19
20 import java.awt.Component JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.LinkedList JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.logging.Logger JavaDoc;
25
26 import javax.swing.JFrame JavaDoc;
27 import javax.swing.JOptionPane JavaDoc;
28
29 import org.columba.api.shutdown.IShutdownManager;
30 import org.columba.core.backgroundtask.BackgroundTaskManager;
31 import org.columba.core.command.Command;
32 import org.columba.core.command.CommandProcessor;
33 import org.columba.core.command.TaskManager;
34 import org.columba.core.logging.Logging;
35 import org.columba.core.main.ColumbaServer;
36 import org.columba.core.resourceloader.GlobalResourceLoader;
37
38 /**
39  * Manages all tasks which are responsible for doing clean-up work when shutting
40  * down Columba.
41  * <p>
42  * This includes saving the xml configuration, saving folder data, etc.
43  * <p>
44  * Tasks use <code>register</code> to the managers shutdown queue.
45  * <p>
46  * When shutting down Columba, the tasks will be running in the opposite order
47  * the have registered at. <br>
48  * Currently this is the following: <br>
49  * <ul>
50  * <li>addressbook folders header cache</li>
51  * <li>POP3 header cache</li>
52  * <li>email folders header cache</li>
53  * <li>core tasks (no core tasks used currently)!</li>
54  * <ul>
55  * <p>
56  * Note, that I used the opposite ordering to make sure that core tasks are
57  * executed first. But, currently there are no core tasks available which would
58  * demand this behaviour.
59  * <p>
60  * Saving email folder header cache is running as a {@link Command}. Its
61  * therefore a background thread, where we don't know when its finished. This is
62  * the reason why we use
63  * <code>MainInterface.processor.getTaskManager().count()</code> to check if
64  * no more commands are running.
65  * <p>
66  * Finally, note that the {@link ColumbaServer}is stopped first, then the
67  * background manager, afterwards all registered shutdown tasks and finally the
68  * xml configuration is saved. Note, that the xml configuration has to be saved
69  * <b>after </b> the email folders where saved.
70  *
71  * @author fdietz
72  */

73 public class ShutdownManager implements IShutdownManager {
74
75     private static final Logger JavaDoc LOG = Logger
76             .getLogger("org.columba.core.shutdown");
77
78     protected static final String JavaDoc RESOURCE_PATH = "org.columba.core.i18n.dialog";
79
80     /**
81      * The singleton instance of this class.
82      */

83     private static IShutdownManager instance;
84
85     /**
86      * Indicates whether this ShutdownManager instance is registered as a system
87      * shutdown hook.
88      */

89     private boolean shutdownHook = false;
90
91     /**
92      * The thread performing the actual shutdown procedure.
93      */

94     protected final Thread JavaDoc shutdownThread;
95
96     /**
97      * The list of runnable plugins that should be executed on shutdown.
98      */

99     protected List JavaDoc list = new LinkedList JavaDoc();
100
101     private boolean shuttingDown;
102
103     /**
104      * This constructor is only to be accessed by getInstance() and by
105      * subclasses.
106      */

107     protected ShutdownManager() {
108         shutdownThread = new Thread JavaDoc(new Runnable JavaDoc() {
109
110             public void run() {
111                 // stop background-manager so it doesn't interfere with
112
// shutdown manager
113
BackgroundTaskManager.getInstance().stop();
114
115                 CommandProcessor.getInstance().stop();
116                 
117                 while (!isShutdownHook()
118                         && (TaskManager.getInstance().count() > 0)) {
119                     // ask user to kill pending running commands or wait
120
Object JavaDoc[] options = {
121                             GlobalResourceLoader.getString(RESOURCE_PATH,
122                                     "session", "tasks_wait"),
123                             GlobalResourceLoader.getString(RESOURCE_PATH,
124                                     "session", "tasks_exit") };
125                     int n = JOptionPane.showOptionDialog(null,
126                             GlobalResourceLoader.getString(RESOURCE_PATH,
127                                     "session", "tasks_msg"),
128                             GlobalResourceLoader.getString(RESOURCE_PATH,
129                                     "session", "tasks_title"),
130                             JOptionPane.YES_NO_OPTION,
131                             JOptionPane.QUESTION_MESSAGE, null, options,
132                             options[0]);
133
134                     if (n == 0) {
135                         // wait 10 seconds and check for pending commands again
136
// this is useful if a command causes a deadlock
137
for (int i = 0; i < 10; i++) {
138                             try {
139                                 Thread.sleep(1000);
140                             } catch (InterruptedException JavaDoc ie) {
141                             }
142                         }
143                     } else {
144                         // don't wait, just continue shutdown procedure,
145
// commands will be killed
146
break;
147                     }
148                 }
149
150                 ShutdownDialog dialog = (ShutdownDialog) openShutdownDialog();
151
152                 Iterator JavaDoc iterator = list.iterator();
153                 Runnable JavaDoc plugin;
154
155                 while (iterator.hasNext()) {
156                     plugin = (Runnable JavaDoc) iterator.next();
157
158                     try {
159                         plugin.run();
160                     } catch (Exception JavaDoc e) {
161                         LOG.severe(e.getMessage());
162
163                         // TODO (@author javaprog): better exception handling
164
}
165                 }
166
167                 // we don't need to check for running commands here because
168
// there aren't any, shutdown plugins only use this thread
169
if (dialog != null)
170                     dialog.close();
171             }
172         }, "ShutdownManager");
173         setShutdownHook(true);
174
175         shuttingDown = false;
176     }
177
178     /*
179      * (non-Javadoc)
180      *
181      * @see org.columba.core.shutdown.IShutdownManager#register(java.lang.Runnable)
182      */

183     public void register(Runnable JavaDoc plugin) {
184         list.add(0, plugin);
185     }
186
187     /**
188      * Returns whether this ShutdownManager instance runs inside a system
189      * shutdown hook.
190      */

191     public synchronized boolean isShutdownHook() {
192         return shutdownHook;
193     }
194
195     /**
196      * Registers or unregisters this ShutdownManager instance as a system
197      * shutdown hook.
198      */

199     protected synchronized void setShutdownHook(boolean b) {
200         if (shutdownHook == b) {
201             return;
202         }
203
204         if (b) {
205             Runtime.getRuntime().addShutdownHook(shutdownThread);
206         } else {
207             Runtime.getRuntime().removeShutdownHook(shutdownThread);
208         }
209
210         shutdownHook = b;
211     }
212
213     /*
214      * (non-Javadoc)
215      *
216      * @see org.columba.core.shutdown.IShutdownManager#shutdown(int)
217      */

218     public synchronized void shutdown(final int status) {
219         if (!shuttingDown) {
220             setShutdownHook(false);
221             new Thread JavaDoc(new Runnable JavaDoc() {
222
223                 public void run() {
224                     shutdownThread.run();
225                     System.exit(status);
226                 }
227             }, "ShutdownManager").start();
228
229             shuttingDown = true;
230         }
231     }
232
233     /**
234      * Returns a component notifying the user of the shutdown procedure.
235      */

236     protected Component JavaDoc openShutdownDialog() {
237         JFrame JavaDoc dialog = null;
238         try {
239             dialog = new ShutdownDialog();
240         } catch (Exception JavaDoc e) {
241             if (Logging.DEBUG)
242                 e.printStackTrace();
243         }
244         return dialog;
245     }
246
247     /**
248      * Returns the singleton instance of this class.
249      */

250     public static synchronized IShutdownManager getInstance() {
251         if (instance == null) {
252             instance = new ShutdownManager();
253         }
254
255         return instance;
256     }
257 }
258
Popular Tags