KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > vladium > util > exit > ExitHookManager


1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2  *
3  * This program and the accompanying materials are made available under
4  * the terms of the Common Public License v1.0 which accompanies this distribution,
5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
6  *
7  * $Id: ExitHookManager.java,v 1.1.1.1 2004/05/09 16:57:58 vlad_r Exp $
8  */

9 package com.vladium.util.exit;
10
11 import java.util.HashMap JavaDoc;
12 import java.util.Map JavaDoc;
13
14 import sun.misc.Signal;
15 import sun.misc.SignalHandler;
16
17 import com.vladium.util.IJREVersion;
18 import com.vladium.util.Property;
19 import com.vladium.emma.IAppConstants;
20
21 // ----------------------------------------------------------------------------
22
/**
23  * @author Vlad Roubtsov, (C) 2003
24  */

25 public
26 abstract class ExitHookManager implements IJREVersion
27 {
28     // public: ................................................................
29

30     // TOTO: handle thread groups as well?
31

32     public abstract boolean addExitHook (Runnable JavaDoc runnable);
33     public abstract boolean removeExitHook (Runnable JavaDoc runnable);
34     
35     public static synchronized ExitHookManager getSingleton ()
36     {
37         if (s_singleton == null)
38         {
39             if (JRE_1_3_PLUS)
40             {
41                 s_singleton = new JRE13ExitHookManager ();
42             }
43             else if (JRE_SUN_SIGNAL_COMPATIBLE)
44             {
45                 s_singleton = new SunJREExitHookManager ();
46             }
47             else
48             {
49                 throw new UnsupportedOperationException JavaDoc ("no shutdown hook manager available [JVM: " + Property.getSystemFingerprint () + "]");
50             }
51         }
52         
53         return s_singleton;
54     }
55     
56     // protected: .............................................................
57

58     
59     protected ExitHookManager () {}
60
61     // package: ...............................................................
62

63     // private: ...............................................................
64

65     
66     private static final class JRE13ExitHookManager extends ExitHookManager
67     {
68         public synchronized boolean addExitHook (final Runnable JavaDoc runnable)
69         {
70             if ((runnable != null) && ! m_exitThreadMap.containsKey (runnable))
71             {
72                 final Thread JavaDoc exitThread = new Thread JavaDoc (runnable, IAppConstants.APP_NAME + " shutdown handler thread");
73                 
74                 try
75                 {
76                     Runtime.getRuntime ().addShutdownHook (exitThread);
77                     m_exitThreadMap.put (runnable, exitThread); // TODO: use identity here
78

79                     return true;
80                 }
81                 catch (Exception JavaDoc e)
82                 {
83                     System.out.println ("exception caught while adding a shutdown hook:");
84                     e.printStackTrace (System.out);
85                 }
86             }
87             
88             return false;
89         }
90         
91         public synchronized boolean removeExitHook (final Runnable JavaDoc runnable)
92         {
93             if (runnable != null)
94             {
95                 final Thread JavaDoc exitThread = (Thread JavaDoc) m_exitThreadMap.get (runnable); // TODO: use identity here
96

97                 if (exitThread != null)
98                 {
99                     try
100                     {
101                         Runtime.getRuntime ().removeShutdownHook (exitThread);
102                         m_exitThreadMap.remove (runnable);
103                         
104                         return true;
105                     }
106                     catch (Exception JavaDoc e)
107                     {
108                         System.out.println ("exception caught while removing a shutdown hook:");
109                         e.printStackTrace (System.out);
110                     }
111                 }
112             }
113             
114             return false;
115         }
116         
117         JRE13ExitHookManager ()
118         {
119             m_exitThreadMap = new HashMap JavaDoc ();
120         }
121         
122         
123         private final Map JavaDoc /* Runnable->Thread */ m_exitThreadMap;
124         
125     } // end of nested class
126

127     
128     private static final class SunJREExitHookManager extends ExitHookManager
129     {
130         public synchronized boolean addExitHook (final Runnable JavaDoc runnable)
131         {
132             if ((runnable != null) && ! m_signalHandlerMap.containsKey (runnable))
133             {
134                 final INTSignalHandler handler = new INTSignalHandler (runnable);
135                 
136                 try
137                 {
138                     handler.register ();
139                     m_signalHandlerMap.put (runnable, handler); // TODO: use identity here
140

141                     return true;
142                 }
143                 catch (Throwable JavaDoc t)
144                 {
145                     System.out.println ("exception caught while adding a shutdown hook:");
146                     t.printStackTrace (System.out);
147                 }
148             }
149             
150             return false;
151         }
152         
153         public synchronized boolean removeExitHook (final Runnable JavaDoc runnable)
154         {
155             if (runnable != null)
156             {
157                 final INTSignalHandler handler = (INTSignalHandler) m_signalHandlerMap.get (runnable); // TODO: use identity here
158
if (handler != null)
159                 {
160                     try
161                     {
162                         handler.unregister ();
163                         m_signalHandlerMap.remove (runnable);
164                         
165                         return true;
166                     }
167                     catch (Exception JavaDoc e)
168                     {
169                         System.out.println ("exception caught while removing a shutdown hook:");
170                         e.printStackTrace (System.out);
171                     }
172                 }
173             }
174             
175             return false;
176         }
177         
178         SunJREExitHookManager ()
179         {
180             m_signalHandlerMap = new HashMap JavaDoc ();
181         }
182         
183         
184         private final Map JavaDoc /* Runnable->INTSignalHandler */ m_signalHandlerMap;
185         
186     } // end of nested class
187

188     
189     private static final class INTSignalHandler implements SignalHandler
190     {
191         public synchronized void handle (final Signal signal)
192         {
193             if (m_runnable != null)
194             {
195                 try
196                 {
197                     m_runnable.run ();
198                 }
199                 catch (Throwable JavaDoc ignore) {}
200             }
201             m_runnable = null;
202             
203             if ((m_previous != null) && (m_previous != SIG_DFL) && (m_previous != SIG_IGN))
204             {
205                 try
206                 {
207                     // this does not work:
208
//Signal.handle (signal, m_previous);
209
//Signal.raise (signal);
210

211                     m_previous.handle (signal);
212                 }
213                 catch (Throwable JavaDoc ignore) {}
214             }
215             else
216             {
217                 System.exit (0);
218             }
219         }
220         
221         INTSignalHandler (final Runnable JavaDoc runnable)
222         {
223             m_runnable = runnable;
224         }
225        
226         synchronized void register ()
227         {
228             m_previous = Signal.handle (new Signal ("INT"), this);
229         }
230         
231         synchronized void unregister ()
232         {
233 // if (m_previous != null)
234
// {
235
// Signal.handle (new Signal ("INT"), m_previous);
236
// m_previous = null;
237
// }
238

239             m_runnable = null;
240         }
241
242
243         private Runnable JavaDoc m_runnable;
244         private SignalHandler m_previous;
245         
246     } // end of nested class
247

248     
249     private static ExitHookManager s_singleton;
250     
251 } // end of class
252
// ----------------------------------------------------------------------------
Popular Tags