1 9 package com.vladium.util.exit; 10 11 import java.util.HashMap ; 12 import java.util.Map ; 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 25 public 26 abstract class ExitHookManager implements IJREVersion 27 { 28 30 32 public abstract boolean addExitHook (Runnable runnable); 33 public abstract boolean removeExitHook (Runnable 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 ("no shutdown hook manager available [JVM: " + Property.getSystemFingerprint () + "]"); 50 } 51 } 52 53 return s_singleton; 54 } 55 56 58 59 protected ExitHookManager () {} 60 61 63 65 66 private static final class JRE13ExitHookManager extends ExitHookManager 67 { 68 public synchronized boolean addExitHook (final Runnable runnable) 69 { 70 if ((runnable != null) && ! m_exitThreadMap.containsKey (runnable)) 71 { 72 final Thread exitThread = new Thread (runnable, IAppConstants.APP_NAME + " shutdown handler thread"); 73 74 try 75 { 76 Runtime.getRuntime ().addShutdownHook (exitThread); 77 m_exitThreadMap.put (runnable, exitThread); 79 return true; 80 } 81 catch (Exception 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 runnable) 92 { 93 if (runnable != null) 94 { 95 final Thread exitThread = (Thread ) m_exitThreadMap.get (runnable); 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 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 (); 120 } 121 122 123 private final Map m_exitThreadMap; 124 125 } 127 128 private static final class SunJREExitHookManager extends ExitHookManager 129 { 130 public synchronized boolean addExitHook (final Runnable 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); 141 return true; 142 } 143 catch (Throwable 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 runnable) 154 { 155 if (runnable != null) 156 { 157 final INTSignalHandler handler = (INTSignalHandler) m_signalHandlerMap.get (runnable); if (handler != null) 159 { 160 try 161 { 162 handler.unregister (); 163 m_signalHandlerMap.remove (runnable); 164 165 return true; 166 } 167 catch (Exception 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 (); 181 } 182 183 184 private final Map m_signalHandlerMap; 185 186 } 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 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 211 m_previous.handle (signal); 212 } 213 catch (Throwable ignore) {} 214 } 215 else 216 { 217 System.exit (0); 218 } 219 } 220 221 INTSignalHandler (final Runnable 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 239 m_runnable = null; 240 } 241 242 243 private Runnable m_runnable; 244 private SignalHandler m_previous; 245 246 } 248 249 private static ExitHookManager s_singleton; 250 251 } | Popular Tags |