0N/A/*
2362N/A * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage java.awt.event;
0N/A
0N/Aimport java.awt.ActiveEvent;
0N/Aimport java.awt.AWTEvent;
0N/A
0N/A/**
0N/A * An event which executes the <code>run()</code> method on a <code>Runnable
0N/A * </code> when dispatched by the AWT event dispatcher thread. This class can
0N/A * be used as a reference implementation of <code>ActiveEvent</code> rather
0N/A * than declaring a new class and defining <code>dispatch()</code>.<p>
0N/A *
0N/A * Instances of this class are placed on the <code>EventQueue</code> by calls
0N/A * to <code>invokeLater</code> and <code>invokeAndWait</code>. Client code
0N/A * can use this fact to write replacement functions for <code>invokeLater
0N/A * </code> and <code>invokeAndWait</code> without writing special-case code
0N/A * in any <code>AWTEventListener</code> objects.
217N/A * <p>
217N/A * An unspecified behavior will be caused if the {@code id} parameter
217N/A * of any particular {@code InvocationEvent} instance is not
217N/A * in the range from {@code INVOCATION_FIRST} to {@code INVOCATION_LAST}.
0N/A *
0N/A * @author Fred Ecks
0N/A * @author David Mendenhall
0N/A *
0N/A * @see java.awt.ActiveEvent
0N/A * @see java.awt.EventQueue#invokeLater
0N/A * @see java.awt.EventQueue#invokeAndWait
0N/A * @see AWTEventListener
0N/A *
0N/A * @since 1.2
0N/A */
0N/Apublic class InvocationEvent extends AWTEvent implements ActiveEvent {
0N/A
0N/A /**
0N/A * Marks the first integer id for the range of invocation event ids.
0N/A */
0N/A public static final int INVOCATION_FIRST = 1200;
0N/A
0N/A /**
0N/A * The default id for all InvocationEvents.
0N/A */
0N/A public static final int INVOCATION_DEFAULT = INVOCATION_FIRST;
0N/A
0N/A /**
0N/A * Marks the last integer id for the range of invocation event ids.
0N/A */
0N/A public static final int INVOCATION_LAST = INVOCATION_DEFAULT;
0N/A
0N/A /**
0N/A * The Runnable whose run() method will be called.
0N/A */
0N/A protected Runnable runnable;
0N/A
0N/A /**
0N/A * The (potentially null) Object whose notifyAll() method will be called
1898N/A * immediately after the Runnable.run() method has returned or thrown an exception.
1898N/A *
1898N/A * @see #isDispatched
0N/A */
0N/A protected Object notifier;
0N/A
0N/A /**
1898N/A * Indicates whether the <code>run()</code> method of the <code>runnable</code>
1898N/A * was executed or not.
1898N/A *
1898N/A * @see #isDispatched
1898N/A * @since 1.7
1898N/A */
1898N/A private volatile boolean dispatched = false;
1898N/A
1898N/A /**
0N/A * Set to true if dispatch() catches Throwable and stores it in the
0N/A * exception instance variable. If false, Throwables are propagated up
0N/A * to the EventDispatchThread's dispatch loop.
0N/A */
0N/A protected boolean catchExceptions;
0N/A
0N/A /**
0N/A * The (potentially null) Exception thrown during execution of the
0N/A * Runnable.run() method. This variable will also be null if a particular
0N/A * instance does not catch exceptions.
0N/A */
0N/A private Exception exception = null;
0N/A
0N/A /**
0N/A * The (potentially null) Throwable thrown during execution of the
0N/A * Runnable.run() method. This variable will also be null if a particular
0N/A * instance does not catch exceptions.
0N/A */
0N/A private Throwable throwable = null;
0N/A
0N/A /**
0N/A * The timestamp of when this event occurred.
0N/A *
0N/A * @serial
0N/A * @see #getWhen
0N/A */
0N/A private long when;
0N/A
0N/A /*
0N/A * JDK 1.1 serialVersionUID.
0N/A */
0N/A private static final long serialVersionUID = 436056344909459450L;
0N/A
0N/A /**
0N/A * Constructs an <code>InvocationEvent</code> with the specified
0N/A * source which will execute the runnable's <code>run</code>
0N/A * method when dispatched.
0N/A * <p>This is a convenience constructor. An invocation of the form
0N/A * <tt>InvocationEvent(source, runnable)</tt>
0N/A * behaves in exactly the same way as the invocation of
0N/A * <tt>{@link #InvocationEvent(Object, Runnable, Object, boolean) InvocationEvent}(source, runnable, null, false)</tt>.
0N/A * <p> This method throws an <code>IllegalArgumentException</code>
0N/A * if <code>source</code> is <code>null</code>.
0N/A *
217N/A * @param source The <code>Object</code> that originated the event
217N/A * @param runnable The <code>Runnable</code> whose <code>run</code>
0N/A * method will be executed
0N/A * @throws IllegalArgumentException if <code>source</code> is null
0N/A *
217N/A * @see #getSource()
217N/A * @see #InvocationEvent(Object, Runnable, Object, boolean)
0N/A */
0N/A public InvocationEvent(Object source, Runnable runnable) {
0N/A this(source, runnable, null, false);
0N/A }
0N/A
0N/A /**
0N/A * Constructs an <code>InvocationEvent</code> with the specified
0N/A * source which will execute the runnable's <code>run</code>
0N/A * method when dispatched. If notifier is non-<code>null</code>,
0N/A * <code>notifyAll()</code> will be called on it
1898N/A * immediately after <code>run</code> has returned or thrown an exception.
0N/A * <p>An invocation of the form <tt>InvocationEvent(source,
0N/A * runnable, notifier, catchThrowables)</tt>
0N/A * behaves in exactly the same way as the invocation of
0N/A * <tt>{@link #InvocationEvent(Object, int, Runnable, Object, boolean) InvocationEvent}(source, InvocationEvent.INVOCATION_DEFAULT, runnable, notifier, catchThrowables)</tt>.
0N/A * <p>This method throws an <code>IllegalArgumentException</code>
0N/A * if <code>source</code> is <code>null</code>.
0N/A *
217N/A * @param source The <code>Object</code> that originated
0N/A * the event
217N/A * @param runnable The <code>Runnable</code> whose
0N/A * <code>run</code> method will be
0N/A * executed
217N/A * @param notifier The {@code Object} whose <code>notifyAll</code>
0N/A * method will be called after
1898N/A * <code>Runnable.run</code> has returned or
1898N/A * thrown an exception
217N/A * @param catchThrowables Specifies whether <code>dispatch</code>
0N/A * should catch Throwable when executing
0N/A * the <code>Runnable</code>'s <code>run</code>
0N/A * method, or should instead propagate those
0N/A * Throwables to the EventDispatchThread's
0N/A * dispatch loop
0N/A * @throws IllegalArgumentException if <code>source</code> is null
0N/A *
217N/A * @see #getSource()
0N/A * @see #InvocationEvent(Object, int, Runnable, Object, boolean)
0N/A */
0N/A public InvocationEvent(Object source, Runnable runnable, Object notifier,
0N/A boolean catchThrowables) {
0N/A this(source, INVOCATION_DEFAULT, runnable, notifier, catchThrowables);
0N/A }
0N/A
0N/A /**
0N/A * Constructs an <code>InvocationEvent</code> with the specified
0N/A * source and ID which will execute the runnable's <code>run</code>
0N/A * method when dispatched. If notifier is non-<code>null</code>,
1898N/A * <code>notifyAll</code> will be called on it immediately after
1898N/A * <code>run</code> has returned or thrown an exception.
217N/A * <p>This method throws an
0N/A * <code>IllegalArgumentException</code> if <code>source</code>
0N/A * is <code>null</code>.
0N/A *
217N/A * @param source The <code>Object</code> that originated
0N/A * the event
217N/A * @param id An integer indicating the type of event.
217N/A * For information on allowable values, see
217N/A * the class description for {@link InvocationEvent}
217N/A * @param runnable The <code>Runnable</code> whose
0N/A * <code>run</code> method will be executed
217N/A * @param notifier The <code>Object</code> whose <code>notifyAll</code>
0N/A * method will be called after
1898N/A * <code>Runnable.run</code> has returned or
1898N/A * thrown an exception
217N/A * @param catchThrowables Specifies whether <code>dispatch</code>
0N/A * should catch Throwable when executing the
0N/A * <code>Runnable</code>'s <code>run</code>
0N/A * method, or should instead propagate those
0N/A * Throwables to the EventDispatchThread's
0N/A * dispatch loop
0N/A * @throws IllegalArgumentException if <code>source</code> is null
217N/A * @see #getSource()
217N/A * @see #getID()
0N/A */
0N/A protected InvocationEvent(Object source, int id, Runnable runnable,
0N/A Object notifier, boolean catchThrowables) {
0N/A super(source, id);
0N/A this.runnable = runnable;
0N/A this.notifier = notifier;
0N/A this.catchExceptions = catchThrowables;
0N/A this.when = System.currentTimeMillis();
0N/A }
0N/A
0N/A /**
0N/A * Executes the Runnable's <code>run()</code> method and notifies the
1898N/A * notifier (if any) when <code>run()</code> has returned or thrown an exception.
1898N/A *
1898N/A * @see #isDispatched
0N/A */
0N/A public void dispatch() {
1898N/A try {
1898N/A if (catchExceptions) {
1898N/A try {
1898N/A runnable.run();
1898N/A }
1898N/A catch (Throwable t) {
1898N/A if (t instanceof Exception) {
1898N/A exception = (Exception) t;
1898N/A }
1898N/A throwable = t;
1898N/A }
1898N/A }
1898N/A else {
0N/A runnable.run();
0N/A }
1898N/A } finally {
5222N/A dispatched = true;
1898N/A
5222N/A if (notifier != null) {
5222N/A synchronized (notifier) {
5222N/A notifier.notifyAll();
5222N/A }
5222N/A }
5222N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns any Exception caught while executing the Runnable's <code>run()
0N/A * </code> method.
0N/A *
0N/A * @return A reference to the Exception if one was thrown; null if no
0N/A * Exception was thrown or if this InvocationEvent does not
0N/A * catch exceptions
0N/A */
0N/A public Exception getException() {
0N/A return (catchExceptions) ? exception : null;
0N/A }
0N/A
0N/A /**
0N/A * Returns any Throwable caught while executing the Runnable's <code>run()
0N/A * </code> method.
0N/A *
0N/A * @return A reference to the Throwable if one was thrown; null if no
0N/A * Throwable was thrown or if this InvocationEvent does not
0N/A * catch Throwables
0N/A * @since 1.5
0N/A */
0N/A public Throwable getThrowable() {
0N/A return (catchExceptions) ? throwable : null;
0N/A }
0N/A
0N/A /**
0N/A * Returns the timestamp of when this event occurred.
0N/A *
0N/A * @return this event's timestamp
0N/A * @since 1.4
0N/A */
0N/A public long getWhen() {
0N/A return when;
0N/A }
0N/A
0N/A /**
1898N/A * Returns {@code true} if the event is dispatched or any exception is
1898N/A * thrown while dispatching, {@code false} otherwise. The method should
1898N/A * be called by a waiting thread that calls the {@code notifier.wait()} method.
1898N/A * Since spurious wakeups are possible (as explained in {@link Object#wait()}),
1898N/A * this method should be used in a waiting loop to ensure that the event
1898N/A * got dispatched:
1898N/A * <pre>
1898N/A * while (!event.isDispatched()) {
1898N/A * notifier.wait();
1898N/A * }
1898N/A * </pre>
1898N/A * If the waiting thread wakes up without dispatching the event,
1898N/A * the {@code isDispatched()} method returns {@code false}, and
1898N/A * the {@code while} loop executes once more, thus, causing
1898N/A * the awakened thread to revert to the waiting mode.
1898N/A * <p>
1898N/A * If the {@code notifier.notifyAll()} happens before the waiting thread
1898N/A * enters the {@code notifier.wait()} method, the {@code while} loop ensures
1898N/A * that the waiting thread will not enter the {@code notifier.wait()} method.
1898N/A * Otherwise, there is no guarantee that the waiting thread will ever be woken
1898N/A * from the wait.
1898N/A *
1898N/A * @return {@code true} if the event has been dispatched, or any exception
1898N/A * has been thrown while dispatching, {@code false} otherwise
1898N/A * @see #dispatch
1898N/A * @see #notifier
1898N/A * @see #catchExceptions
1898N/A * @since 1.7
1898N/A */
1898N/A public boolean isDispatched() {
1898N/A return dispatched;
1898N/A }
1898N/A
1898N/A /**
0N/A * Returns a parameter string identifying this event.
0N/A * This method is useful for event-logging and for debugging.
0N/A *
0N/A * @return A string identifying the event and its attributes
0N/A */
0N/A public String paramString() {
0N/A String typeStr;
0N/A switch(id) {
0N/A case INVOCATION_DEFAULT:
0N/A typeStr = "INVOCATION_DEFAULT";
0N/A break;
0N/A default:
0N/A typeStr = "unknown type";
0N/A }
0N/A return typeStr + ",runnable=" + runnable + ",notifier=" + notifier +
0N/A ",catchExceptions=" + catchExceptions + ",when=" + when;
0N/A }
0N/A}