LANG-580: Add Event Support Utilities

Applying documentation patch "commons-lang-event-support-docs.patch" from Michael Wooten.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@978864 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
James W. Carman 2010-07-24 12:49:38 +00:00
parent b1ba66c46e
commit 9a40cd0194
1 changed files with 89 additions and 28 deletions

View File

@ -17,56 +17,88 @@
package org.apache.commons.lang3.event;
import org.apache.commons.lang3.Validate;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.commons.lang3.Validate;
/**
* An EventListenerSupport object can be used to manage a list of event listeners of a particular type.
* An EventListenerSupport object can be used to manage a list of event
* listeners of a particular type. The class provides
* {@link #addListener(Object)} and {@link #removeListener(Object)} methods
* for registering listeners, as well as a {@link #fire()} method for firing
* events to the listeners.
*
* <p/>
* To use this class, suppose you want to support ActionEvents. You would do:
* <pre>
* <code><pre>
* public class MyActionEventSource
* {
* private EventListenerSupport<ActionListener> actionListeners = EventListenerSupport.create(ActionListener.class);
* <p/>
* private EventListenerSupport<ActionListener> actionListeners =
* EventListenerSupport.create(ActionListener.class);
*
* public void someMethodThatFiresAction()
* {
* ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "somethingCool");
* actionListeners.fire().actionPerformed(e);
* }
* }
* </pre>
* </pre></code>
*
* @param <L> The event listener type
* @param <L> the type of event listener that is supported by this proxy.
*
* @since 3.0
* @version $Id$
*/
public class EventListenerSupport<L>
{
/**
* The list used to hold the registered listeners. This list is
* intentionally a thread-safe copy-on-write-array so that traversals over
* the list of listeners will be atomic.
*/
private final List<L> listeners = new CopyOnWriteArrayList<L>();
/**
* The proxy representing the collection of listeners. Calls to this proxy
* object will sent to all registered listeners.
*/
private final L proxy;
/**
* Creates an EventListenerSupport object which supports the specified listener type.
* Creates an EventListenerSupport object which supports the specified
* listener type.
*
* @param listenerType the listener type
* @return an EventListenerSupport object which supports the specified listener type
* @param listenerInterface the type of listener interface that will receive
* events posted using this class.
*
* @return an EventListenerSupport object which supports the specified
* listener type.
*
* @throws NullPointerException if <code>listenerInterface</code> is
* <code>null</code>.
* @throws IllegalArgumentException if <code>listenerInterface</code> is
* not an interface.
*/
public static <T> EventListenerSupport<T> create(Class<T> listenerType)
public static <T> EventListenerSupport<T> create(Class<T> listenerInterface)
{
return new EventListenerSupport<T>(listenerType);
return new EventListenerSupport<T>(listenerInterface);
}
/**
* Creates an EventListenerSupport object which supports the provided listener interface.
* Creates an EventListenerSupport object which supports the provided
* listener interface.
*
* @param listenerInterface the listener interface
* @param listenerInterface the type of listener interface that will receive
* events posted using this class.
*
* @throws NullPointerException if <code>listenerInterface</code> is
* <code>null</code>.
* @throws IllegalArgumentException if <code>listenerInterface</code> is
* not an interface.
*/
public EventListenerSupport(Class<L> listenerInterface)
{
@ -74,25 +106,37 @@ public class EventListenerSupport<L>
}
/**
* Creates an EventListenerSupport object which supports the provided listener interface using the specified
* class loader to create the JDK dynamic proxy.
* Creates an EventListenerSupport object which supports the provided
* listener interface using the specified class loader to create the JDK
* dynamic proxy.
*
* @param listenerInterface the listener interface
* @param classLoader the class loader
* @param listenerInterface the listener interface.
* @param classLoader the class loader.
*
* @throws NullPointerException if <code>listenerInterface</code> or
* <code>classLoader</code> is <code>null</code>.
* @throws IllegalArgumentException if <code>listenerInterface</code> is
* not an interface.
*/
public EventListenerSupport(Class<L> listenerInterface, ClassLoader classLoader)
{
Validate.notNull(listenerInterface, "Listener interface cannot be null.");
Validate.notNull(classLoader, "ClassLoader cannot be null.");
Validate.isTrue(listenerInterface.isInterface(), "Class {0} is not an interface", listenerInterface.getName());
proxy = listenerInterface.cast(Proxy.newProxyInstance(classLoader, new Class[]{listenerInterface},
Validate.isTrue(listenerInterface.isInterface(),
"Class {0} is not an interface",
listenerInterface.getName());
proxy = listenerInterface.cast(Proxy.newProxyInstance(classLoader,
new Class[]{listenerInterface},
new ProxyInvocationHandler()));
}
/**
* Returns a proxy object which can be used to call listener methods on all of the registered event listeners.
* Returns a proxy object which can be used to call listener methods on all
* of the registered event listeners. All calls made to this proxy will be
* forwarded to all registered listeners.
*
* @return a proxy object which can be used to call listener methods on all of the registered event listeners
* @return a proxy object which can be used to call listener methods on all
* of the registered event listeners
*/
public L fire()
{
@ -106,7 +150,10 @@ public class EventListenerSupport<L>
/**
* Registers an event listener.
*
* @param listener the event listener
* @param listener the event listener (may not be <code>null</code>).
*
* @throws NullPointerException if <code>listener</code> is
* <code>null</code>.
*/
public void addListener(L listener)
{
@ -117,9 +164,9 @@ public class EventListenerSupport<L>
/**
* Returns the number of registered listeners.
*
* @return the number of registered listeners
* @return the number of registered listeners.
*/
public int getListenerCount()
int getListenerCount()
{
return listeners.size();
}
@ -127,7 +174,10 @@ public class EventListenerSupport<L>
/**
* Unregisters an event listener.
*
* @param listener the event listener
* @param listener the event listener (may not be <code>null</code>).
*
* @throws NullPointerException if <code>listener</code> is
* <code>null</code>.
*/
public void removeListener(L listener)
{
@ -140,7 +190,18 @@ public class EventListenerSupport<L>
*/
private class ProxyInvocationHandler implements InvocationHandler
{
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
/**
* Propagates the method call to all registered listeners in place of
* the proxy listener object.
*
* @param proxy the proxy object representing a listener on which the
* invocation was called.
* @param method the listener method that will be called on all of the
* listeners.
* @param args event arguments to propogate to the listeners.
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
for (L listener : listeners)
{