1. /*
  2. * @(#)InvocationEvent.java 1.18 04/02/05
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt.event;
  8. import java.awt.ActiveEvent;
  9. import java.awt.AWTEvent;
  10. /**
  11. * An event which executes the <code>run()</code> method on a <code>Runnable
  12. * </code> when dispatched by the AWT event dispatcher thread. This class can
  13. * be used as a reference implementation of <code>ActiveEvent</code> rather
  14. * than declaring a new class and defining <code>dispatch()</code>.<p>
  15. *
  16. * Instances of this class are placed on the <code>EventQueue</code> by calls
  17. * to <code>invokeLater</code> and <code>invokeAndWait</code>. Client code
  18. * can use this fact to write replacement functions for <code>invokeLater
  19. * </code> and <code>invokeAndWait</code> without writing special-case code
  20. * in any <code>AWTEventListener</code> objects.
  21. *
  22. * @author Fred Ecks
  23. * @author David Mendenhall
  24. * @version 1.18, 02/05/04
  25. *
  26. * @see java.awt.ActiveEvent
  27. * @see java.awt.EventQueue#invokeLater
  28. * @see java.awt.EventQueue#invokeAndWait
  29. * @see AWTEventListener
  30. *
  31. * @since 1.2
  32. */
  33. public class InvocationEvent extends AWTEvent implements ActiveEvent {
  34. /**
  35. * Marks the first integer id for the range of invocation event ids.
  36. */
  37. public static final int INVOCATION_FIRST = 1200;
  38. /**
  39. * The default id for all InvocationEvents.
  40. */
  41. public static final int INVOCATION_DEFAULT = INVOCATION_FIRST;
  42. /**
  43. * Marks the last integer id for the range of invocation event ids.
  44. */
  45. public static final int INVOCATION_LAST = INVOCATION_DEFAULT;
  46. /**
  47. * The Runnable whose run() method will be called.
  48. */
  49. protected Runnable runnable;
  50. /**
  51. * The (potentially null) Object whose notifyAll() method will be called
  52. * immediately after the Runnable.run() method returns.
  53. */
  54. protected Object notifier;
  55. /**
  56. * Set to true if dispatch() catches Throwable and stores it in the
  57. * exception instance variable. If false, Throwables are propagated up
  58. * to the EventDispatchThread's dispatch loop.
  59. */
  60. protected boolean catchExceptions;
  61. /**
  62. * The (potentially null) Exception thrown during execution of the
  63. * Runnable.run() method. This variable will also be null if a particular
  64. * instance does not catch exceptions.
  65. */
  66. private Exception exception = null;
  67. /**
  68. * The (potentially null) Throwable thrown during execution of the
  69. * Runnable.run() method. This variable will also be null if a particular
  70. * instance does not catch exceptions.
  71. */
  72. private Throwable throwable = null;
  73. /**
  74. * The timestamp of when this event occurred.
  75. *
  76. * @serial
  77. * @see #getWhen
  78. */
  79. private long when;
  80. /*
  81. * JDK 1.1 serialVersionUID.
  82. */
  83. private static final long serialVersionUID = 436056344909459450L;
  84. /**
  85. * Constructs an <code>InvocationEvent</code> with the specified
  86. * source which will execute the runnable's <code>run</code>
  87. * method when dispatched.
  88. * <p>This is a convenience constructor. An invocation of the form
  89. * <tt>InvocationEvent(source, runnable)</tt>
  90. * behaves in exactly the same way as the invocation of
  91. * <tt>{@link #InvocationEvent(Object, Runnable, Object, boolean) InvocationEvent}(source, runnable, null, false)</tt>.
  92. * <p> This method throws an <code>IllegalArgumentException</code>
  93. * if <code>source</code> is <code>null</code>.
  94. *
  95. * @param source the <code>Object</code> that originated the event
  96. * @param runnable the <code>Runnable</code> whose <code>run</code>
  97. * method will be executed
  98. * @throws IllegalArgumentException if <code>source</code> is null
  99. *
  100. * @see #InvocationEvent(Object, Runnable, Object, boolean)
  101. */
  102. public InvocationEvent(Object source, Runnable runnable) {
  103. this(source, runnable, null, false);
  104. }
  105. /**
  106. * Constructs an <code>InvocationEvent</code> with the specified
  107. * source which will execute the runnable's <code>run</code>
  108. * method when dispatched. If notifier is non-<code>null</code>,
  109. * <code>notifyAll()</code> will be called on it
  110. * immediately after <code>run</code> returns.
  111. * <p>An invocation of the form <tt>InvocationEvent(source,
  112. * runnable, notifier, catchThrowables)</tt>
  113. * behaves in exactly the same way as the invocation of
  114. * <tt>{@link #InvocationEvent(Object, int, Runnable, Object, boolean) InvocationEvent}(source, InvocationEvent.INVOCATION_DEFAULT, runnable, notifier, catchThrowables)</tt>.
  115. * <p>This method throws an <code>IllegalArgumentException</code>
  116. * if <code>source</code> is <code>null</code>.
  117. *
  118. * @param source the <code>Object</code> that originated
  119. * the event
  120. * @param runnable the <code>Runnable</code> whose
  121. * <code>run</code> method will be
  122. * executed
  123. * @param notifier the Object whose <code>notifyAll</code>
  124. * method will be called after
  125. * <code>Runnable.run</code> has returned
  126. * @param catchThrowables specifies whether <code>dispatch</code>
  127. * should catch Throwable when executing
  128. * the <code>Runnable</code>'s <code>run</code>
  129. * method, or should instead propagate those
  130. * Throwables to the EventDispatchThread's
  131. * dispatch loop
  132. * @throws IllegalArgumentException if <code>source</code> is null
  133. *
  134. * @see #InvocationEvent(Object, int, Runnable, Object, boolean)
  135. */
  136. public InvocationEvent(Object source, Runnable runnable, Object notifier,
  137. boolean catchThrowables) {
  138. this(source, INVOCATION_DEFAULT, runnable, notifier, catchThrowables);
  139. }
  140. /**
  141. * Constructs an <code>InvocationEvent</code> with the specified
  142. * source and ID which will execute the runnable's <code>run</code>
  143. * method when dispatched. If notifier is non-<code>null</code>,
  144. * <code>notifyAll</code> will be called on it
  145. * immediately after <code>run</code> returns.
  146. * <p>Note that passing in an invalid <code>id</code> results in
  147. * unspecified behavior. This method throws an
  148. * <code>IllegalArgumentException</code> if <code>source</code>
  149. * is <code>null</code>.
  150. *
  151. * @param source the <code>Object</code> that originated
  152. * the event
  153. * @param id the ID for the event
  154. * @param runnable the <code>Runnable</code> whose
  155. * <code>run</code> method will be executed
  156. * @param notifier the <code>Object whose <code>notifyAll</code>
  157. * method will be called after
  158. * <code>Runnable.run</code> has returned
  159. * @param catchThrowables specifies whether <code>dispatch</code>
  160. * should catch Throwable when executing the
  161. * <code>Runnable</code>'s <code>run</code>
  162. * method, or should instead propagate those
  163. * Throwables to the EventDispatchThread's
  164. * dispatch loop
  165. * @throws IllegalArgumentException if <code>source</code> is null
  166. */
  167. protected InvocationEvent(Object source, int id, Runnable runnable,
  168. Object notifier, boolean catchThrowables) {
  169. super(source, id);
  170. this.runnable = runnable;
  171. this.notifier = notifier;
  172. this.catchExceptions = catchThrowables;
  173. this.when = System.currentTimeMillis();
  174. }
  175. /**
  176. * Executes the Runnable's <code>run()</code> method and notifies the
  177. * notifier (if any) when <code>run()</code> returns.
  178. */
  179. public void dispatch() {
  180. if (catchExceptions) {
  181. try {
  182. runnable.run();
  183. }
  184. catch (Throwable t) {
  185. if (t instanceof Exception) {
  186. exception = (Exception) t;
  187. }
  188. throwable = t;
  189. }
  190. }
  191. else {
  192. runnable.run();
  193. }
  194. if (notifier != null) {
  195. synchronized (notifier) {
  196. notifier.notifyAll();
  197. }
  198. }
  199. }
  200. /**
  201. * Returns any Exception caught while executing the Runnable's <code>run()
  202. * </code> method.
  203. *
  204. * @return A reference to the Exception if one was thrown; null if no
  205. * Exception was thrown or if this InvocationEvent does not
  206. * catch exceptions
  207. */
  208. public Exception getException() {
  209. return (catchExceptions) ? exception : null;
  210. }
  211. /**
  212. * Returns any Throwable caught while executing the Runnable's <code>run()
  213. * </code> method.
  214. *
  215. * @return A reference to the Throwable if one was thrown; null if no
  216. * Throwable was thrown or if this InvocationEvent does not
  217. * catch Throwables
  218. */
  219. public Throwable getThrowable() {
  220. return (catchExceptions) ? throwable : null;
  221. }
  222. /**
  223. * Returns the timestamp of when this event occurred.
  224. *
  225. * @return this event's timestamp
  226. * @since 1.4
  227. */
  228. public long getWhen() {
  229. return when;
  230. }
  231. /**
  232. * Returns a parameter string identifying this event.
  233. * This method is useful for event-logging and for debugging.
  234. *
  235. * @return A string identifying the event and its attributes
  236. */
  237. public String paramString() {
  238. String typeStr;
  239. switch(id) {
  240. case INVOCATION_DEFAULT:
  241. typeStr = "INVOCATION_DEFAULT";
  242. break;
  243. default:
  244. typeStr = "unknown type";
  245. }
  246. return typeStr + ",runnable=" + runnable + ",notifier=" + notifier +
  247. ",catchExceptions=" + catchExceptions + ",when=" + when;
  248. }
  249. }