1 /*
2 * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package java.awt.event;
27
28 import java.awt.ActiveEvent;
29 import java.awt.AWTEvent;
30
31 /**
32 * An event which executes the <code>run()</code> method on a <code>Runnable
33 * </code> when dispatched by the AWT event dispatcher thread. This class can
34 * be used as a reference implementation of <code>ActiveEvent</code> rather
35 * than declaring a new class and defining <code>dispatch()</code>.<p>
36 *
37 * Instances of this class are placed on the <code>EventQueue</code> by calls
38 * to <code>invokeLater</code> and <code>invokeAndWait</code>. Client code
39 * can use this fact to write replacement functions for <code>invokeLater
40 * </code> and <code>invokeAndWait</code> without writing special-case code
41 * in any <code>AWTEventListener</code> objects.
42 * <p>
43 * An unspecified behavior will be caused if the {@code id} parameter
44 * of any particular {@code InvocationEvent} instance is not
45 * in the range from {@code INVOCATION_FIRST} to {@code INVOCATION_LAST}.
46 *
47 * @author Fred Ecks
48 * @author David Mendenhall
49 *
50 * @see java.awt.ActiveEvent
51 * @see java.awt.EventQueue#invokeLater
52 * @see java.awt.EventQueue#invokeAndWait
53 * @see AWTEventListener
54 *
55 * @since 1.2
56 */
57 public class InvocationEvent extends AWTEvent implements ActiveEvent {
58
59 /**
60 * Marks the first integer id for the range of invocation event ids.
61 */
62 public static final int INVOCATION_FIRST = 1200;
63
64 /**
65 * The default id for all InvocationEvents.
66 */
67 public static final int INVOCATION_DEFAULT = INVOCATION_FIRST;
68
69 /**
70 * Marks the last integer id for the range of invocation event ids.
71 */
72 public static final int INVOCATION_LAST = INVOCATION_DEFAULT;
73
74 /**
75 * The Runnable whose run() method will be called.
76 */
77 protected Runnable runnable;
78
79 /**
80 * The (potentially null) Object whose notifyAll() method will be called
81 * immediately after the Runnable.run() method returns.
82 */
83 protected Object notifier;
84
85 /**
86 * Set to true if dispatch() catches Throwable and stores it in the
87 * exception instance variable. If false, Throwables are propagated up
88 * to the EventDispatchThread's dispatch loop.
89 */
90 protected boolean catchExceptions;
91
92 /**
93 * The (potentially null) Exception thrown during execution of the
94 * Runnable.run() method. This variable will also be null if a particular
95 * instance does not catch exceptions.
96 */
97 private Exception exception = null;
98
99 /**
100 * The (potentially null) Throwable thrown during execution of the
101 * Runnable.run() method. This variable will also be null if a particular
102 * instance does not catch exceptions.
103 */
104 private Throwable throwable = null;
105
106 /**
107 * The timestamp of when this event occurred.
108 *
109 * @serial
110 * @see #getWhen
111 */
112 private long when;
113
114 /*
115 * JDK 1.1 serialVersionUID.
116 */
117 private static final long serialVersionUID = 436056344909459450L;
118
119 /**
120 * Constructs an <code>InvocationEvent</code> with the specified
121 * source which will execute the runnable's <code>run</code>
122 * method when dispatched.
123 * <p>This is a convenience constructor. An invocation of the form
124 * <tt>InvocationEvent(source, runnable)</tt>
125 * behaves in exactly the same way as the invocation of
126 * <tt>{@link #InvocationEvent(Object, Runnable, Object, boolean) InvocationEvent}(source, runnable, null, false)</tt>.
127 * <p> This method throws an <code>IllegalArgumentException</code>
128 * if <code>source</code> is <code>null</code>.
129 *
130 * @param source The <code>Object</code> that originated the event
131 * @param runnable The <code>Runnable</code> whose <code>run</code>
132 * method will be executed
133 * @throws IllegalArgumentException if <code>source</code> is null
134 *
135 * @see #getSource()
136 * @see #InvocationEvent(Object, Runnable, Object, boolean)
137 */
138 public InvocationEvent(Object source, Runnable runnable) {
139 this(source, runnable, null, false);
140 }
141
142 /**
143 * Constructs an <code>InvocationEvent</code> with the specified
144 * source which will execute the runnable's <code>run</code>
145 * method when dispatched. If notifier is non-<code>null</code>,
146 * <code>notifyAll()</code> will be called on it
147 * immediately after <code>run</code> returns.
148 * <p>An invocation of the form <tt>InvocationEvent(source,
149 * runnable, notifier, catchThrowables)</tt>
150 * behaves in exactly the same way as the invocation of
151 * <tt>{@link #InvocationEvent(Object, int, Runnable, Object, boolean) InvocationEvent}(source, InvocationEvent.INVOCATION_DEFAULT, runnable, notifier, catchThrowables)</tt>.
152 * <p>This method throws an <code>IllegalArgumentException</code>
153 * if <code>source</code> is <code>null</code>.
154 *
155 * @param source The <code>Object</code> that originated
156 * the event
157 * @param runnable The <code>Runnable</code> whose
158 * <code>run</code> method will be
159 * executed
160 * @param notifier The {@code Object} whose <code>notifyAll</code>
161 * method will be called after
162 * <code>Runnable.run</code> has returned
163 * @param catchThrowables Specifies whether <code>dispatch</code>
164 * should catch Throwable when executing
165 * the <code>Runnable</code>'s <code>run</code>
166 * method, or should instead propagate those
167 * Throwables to the EventDispatchThread's
168 * dispatch loop
169 * @throws IllegalArgumentException if <code>source</code> is null
170 *
171 * @see #getSource()
172 * @see #InvocationEvent(Object, int, Runnable, Object, boolean)
173 */
174 public InvocationEvent(Object source, Runnable runnable, Object notifier,
175 boolean catchThrowables) {
176 this(source, INVOCATION_DEFAULT, runnable, notifier, catchThrowables);
177 }
178
179 /**
180 * Constructs an <code>InvocationEvent</code> with the specified
181 * source and ID which will execute the runnable's <code>run</code>
182 * method when dispatched. If notifier is non-<code>null</code>,
183 * <code>notifyAll</code> will be called on it
184 * immediately after <code>run</code> returns.
185 * <p>This method throws an
186 * <code>IllegalArgumentException</code> if <code>source</code>
187 * is <code>null</code>.
188 *
189 * @param source The <code>Object</code> that originated
190 * the event
191 * @param id An integer indicating the type of event.
192 * For information on allowable values, see
193 * the class description for {@link InvocationEvent}
194 * @param runnable The <code>Runnable</code> whose
195 * <code>run</code> method will be executed
196 * @param notifier The <code>Object</code> whose <code>notifyAll</code>
197 * method will be called after
198 * <code>Runnable.run</code> has returned
199 * @param catchThrowables Specifies whether <code>dispatch</code>
200 * should catch Throwable when executing the
201 * <code>Runnable</code>'s <code>run</code>
202 * method, or should instead propagate those
203 * Throwables to the EventDispatchThread's
204 * dispatch loop
205 * @throws IllegalArgumentException if <code>source</code> is null
206 * @see #getSource()
207 * @see #getID()
208 */
209 protected InvocationEvent(Object source, int id, Runnable runnable,
210 Object notifier, boolean catchThrowables) {
211 super(source, id);
212 this.runnable = runnable;
213 this.notifier = notifier;
214 this.catchExceptions = catchThrowables;
215 this.when = System.currentTimeMillis();
216 }
217
218 /**
219 * Executes the Runnable's <code>run()</code> method and notifies the
220 * notifier (if any) when <code>run()</code> returns.
221 */
222 public void dispatch() {
223 if (catchExceptions) {
224 try {
225 runnable.run();
226 }
227 catch (Throwable t) {
228 if (t instanceof Exception) {
229 exception = (Exception) t;
230 }
231 throwable = t;
232 }
233 }
234 else {
235 runnable.run();
236 }
237
238 if (notifier != null) {
239 synchronized (notifier) {
240 notifier.notifyAll();
241 }
242 }
243 }
244
245 /**
246 * Returns any Exception caught while executing the Runnable's <code>run()
247 * </code> method.
248 *
249 * @return A reference to the Exception if one was thrown; null if no
250 * Exception was thrown or if this InvocationEvent does not
251 * catch exceptions
252 */
253 public Exception getException() {
254 return (catchExceptions) ? exception : null;
255 }
256
257 /**
258 * Returns any Throwable caught while executing the Runnable's <code>run()
259 * </code> method.
260 *
261 * @return A reference to the Throwable if one was thrown; null if no
262 * Throwable was thrown or if this InvocationEvent does not
263 * catch Throwables
264 * @since 1.5
265 */
266 public Throwable getThrowable() {
267 return (catchExceptions) ? throwable : null;
268 }
269
270 /**
271 * Returns the timestamp of when this event occurred.
272 *
273 * @return this event's timestamp
274 * @since 1.4
275 */
276 public long getWhen() {
277 return when;
278 }
279
280 /**
281 * Returns a parameter string identifying this event.
282 * This method is useful for event-logging and for debugging.
283 *
284 * @return A string identifying the event and its attributes
285 */
286 public String paramString() {
287 String typeStr;
288 switch(id) {
289 case INVOCATION_DEFAULT:
290 typeStr = "INVOCATION_DEFAULT";
291 break;
292 default:
293 typeStr = "unknown type";
294 }
295 return typeStr + ",runnable=" + runnable + ",notifier=" + notifier +
296 ",catchExceptions=" + catchExceptions + ",when=" + when;
297 }
298 }