1 8 9 package foxtrot.pumps; 10 11 import java.lang.reflect.Method ; 12 import java.lang.reflect.InvocationHandler ; 13 import java.lang.reflect.Proxy ; 14 import java.lang.reflect.InvocationTargetException ; 15 import java.security.AccessController ; 16 import java.security.PrivilegedExceptionAction ; 17 import java.security.PrivilegedAction ; 18 import java.awt.AWTEvent ; 19 import java.awt.EventQueue ; 20 import java.awt.Toolkit ; 21 22 import foxtrot.EventPump; 23 import foxtrot.Task; 24 25 31 public class ConditionalEventPump implements EventPump, EventFilterable 32 { 33 private static Class conditionalClass; 34 private static Method pumpEventsMethod; 35 static final boolean debug = false; 36 37 static 38 { 39 try 40 { 41 AccessController.doPrivileged(new PrivilegedExceptionAction () 42 { 43 public Object run() throws ClassNotFoundException , NoSuchMethodException 44 { 45 ClassLoader loader = ClassLoader.getSystemClassLoader(); 46 conditionalClass = loader.loadClass("java.awt.Conditional"); 47 Class dispatchThreadClass = loader.loadClass("java.awt.EventDispatchThread"); 48 pumpEventsMethod = dispatchThreadClass.getDeclaredMethod("pumpEvents", new Class []{conditionalClass}); 49 pumpEventsMethod.setAccessible(true); 50 51 String property = "sun.awt.exception.handler"; 53 String handler = System.getProperty(property); 54 if (handler == null) 55 { 56 handler = ThrowableHandler.class.getName(); 57 System.setProperty(property, handler); 58 if (debug) System.out.println("[ConditionalEventPump] Installing AWT Throwable Handler " + handler); 59 } 60 else 61 { 62 if (debug) System.out.println("[ConditionalEventPump] Using already installed AWT Throwable Handler " + handler); 63 } 64 return null; 65 } 66 }); 67 } 68 catch (Throwable x) 69 { 70 if (debug) x.printStackTrace(); 71 throw new Error (x.toString()); 72 } 73 } 74 75 private EventFilter filter; 76 77 public void setEventFilter(EventFilter filter) 78 { 79 this.filter = filter; 80 } 81 82 public EventFilter getEventFilter() 83 { 84 return filter; 85 } 86 87 public void pumpEvents(Task task) 88 { 89 if (task == null) return; 91 92 try 93 { 94 if (debug) System.out.println("[ConditionalEventPump] Start pumping events - Pump is " + this + " - Task is " + task); 95 96 Object conditional = Proxy.newProxyInstance(conditionalClass.getClassLoader(), new Class []{conditionalClass}, new Conditional(task)); 98 pumpEventsMethod.invoke(Thread.currentThread(), new Object []{conditional}); 99 } 100 catch (InvocationTargetException x) 101 { 102 Throwable t = x.getTargetException(); 105 System.err.println("[ConditionalEventPump] Exception occurred during event dispatching:"); 106 t.printStackTrace(); 107 108 if (t instanceof RuntimeException ) 111 throw (RuntimeException )t; 112 else 113 throw (Error )t; 114 } 115 catch (Throwable x) 116 { 117 System.err.println("[ConditionalEventPump] PANIC: uncaught exception in Foxtrot code"); 119 x.printStackTrace(); 120 } 121 finally 122 { 123 waitForTask(task); 127 128 if (debug) System.out.println("[ConditionalEventPump] Stop pumping events - Pump is " + this + " - Task is " + task); 129 } 130 } 131 132 private void waitForTask(Task task) 133 { 134 try 135 { 136 synchronized (task) 137 { 138 while (!task.isCompleted()) 139 { 140 if (debug) System.out.println("[ConditionalEventPump] Waiting for Task " + task + " to complete (GUI freeze)"); 141 task.wait(); 142 } 143 if (debug) System.out.println("[ConditionalEventPump] Task " + task + " is completed"); 144 } 145 } 146 catch (InterruptedException x) 147 { 148 Thread.currentThread().interrupt(); 150 } 151 } 152 153 159 private Boolean pumpEvent(Task task) 160 { 161 Boolean completed = task.isCompleted() ? Boolean.TRUE : Boolean.FALSE; 162 if (completed.booleanValue()) return Boolean.FALSE; 164 165 while (true) 166 { 167 AWTEvent nextEvent = waitForEvent(); 169 if (nextEvent == null) return Boolean.FALSE; 170 if (debug) System.out.println("[ConditionalEventPump] Next Event: " + nextEvent); 171 172 if (!canPumpEvent(nextEvent)) return Boolean.FALSE; 175 176 if (filter == null || filter.accept(nextEvent)) return Boolean.TRUE; 178 179 nextEvent = getNextEvent(); 182 if (nextEvent == null) return Boolean.FALSE; 183 if (debug) System.out.println("[ConditionalEventPump] Filtered out AWT Event: " + nextEvent + " by filter " + filter); 184 } 185 } 186 187 199 protected boolean canPumpEvent(AWTEvent event) 200 { 201 return true; 202 } 203 204 private EventQueue getEventQueue() 205 { 206 return (EventQueue )AccessController.doPrivileged(new PrivilegedAction () 207 { 208 public Object run() 209 { 210 return Toolkit.getDefaultToolkit().getSystemEventQueue(); 211 } 212 }); 213 } 214 215 private AWTEvent getNextEvent() 216 { 217 try 218 { 219 return getEventQueue().getNextEvent(); 220 } 221 catch (InterruptedException x) 222 { 223 Thread.currentThread().interrupt(); 224 return null; 225 } 226 } 227 228 235 private AWTEvent waitForEvent() 236 { 237 EventQueue queue = getEventQueue(); 238 AWTEvent nextEvent = null; 239 synchronized (queue) 240 { 241 while ((nextEvent = peekEvent(queue)) == null) 242 { 243 if (debug) System.out.println("[ConditionalEventPump] Waiting for events..."); 244 try 245 { 246 queue.wait(); 247 } 248 catch (InterruptedException x) 249 { 250 Thread.currentThread().interrupt(); 251 return null; 252 } 253 } 254 } 255 return nextEvent; 256 } 257 258 261 protected AWTEvent peekEvent(EventQueue queue) 262 { 263 return queue.peekEvent(); 264 } 265 266 270 private class Conditional implements InvocationHandler 271 { 272 private final Task task; 273 274 277 private Conditional(Task task) 278 { 279 this.task = task; 280 } 281 282 285 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable 286 { 287 return pumpEvent(task); 288 } 289 } 290 291 300 public static class ThrowableHandler 301 { 302 307 public void handle(Throwable t) 308 { 309 System.err.println("[ConditionalEventPump] Exception occurred during event dispatching:"); 310 t.printStackTrace(); 311 } 312 } 313 } 314 | Popular Tags |