commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bay...@apache.org
Subject svn commit: r965165 - in /commons/proper/lang/trunk/src: main/java/org/apache/commons/lang3/event/ test/java/org/apache/commons/lang3/event/
Date Sun, 18 Jul 2010 06:05:52 GMT
Author: bayard
Date: Sun Jul 18 06:05:51 2010
New Revision: 965165

URL: http://svn.apache.org/viewvc?rev=965165&view=rev
Log:
Adding Michael Wooten's event support utilities from LANG-580

Added:
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/AbstractEventSupport.java
  (with props)
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/EventSupport.java
  (with props)
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/ReflectiveEventSupport.java
  (with props)
    commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/event/
    commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/event/AbstractEventSupportTest.java
  (with props)
    commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/event/ReflectiveEventSupportTest.java
  (with props)

Added: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/AbstractEventSupport.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/AbstractEventSupport.java?rev=965165&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/AbstractEventSupport.java
(added)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/AbstractEventSupport.java
Sun Jul 18 06:05:51 2010
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.lang3.event;
+
+import java.io.Serializable;
+import java.util.EventListener;
+import java.util.EventObject;
+import java.util.Iterator;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.commons.lang3.Validate;
+
+/**
+ * <p>
+ * The AbstractEventSupport class provides an abstract base class framework for
+ * managing {@link EventListener} objects and for firing {@link EventObject}s to
+ * those listeners. The class provides the ability to register a "source" object
+ * that should be used as the source of the events, as well as the ability to 
+ * register and unregister listeners in a thread-safe manner. The class also 
+ * provides support for iterating over the registered listeners.
+ * </p>
+ * 
+ * <p>
+ * Subclasses of the AbstractEventSupport class are designed to implement 
+ * methods for firing events. The implementations can make use of both the 
+ * iterable functionality and use the associated source object as the source 
+ * of the events.
+ * </p>
+ * 
+ * <p>
+ * Example:
+ * <code><pre>
+ * public WindowSupport extends AbstractEventSupport<WindowListener> {
+ *     
+ *     public WindowSupport(Window source) {
+ *         super(source);
+ *     }
+ *     
+ *     public void fireWindowOpened(int windowId, int oldState, int newState) {
+ *         WindowEvent windowEvent = 
+ *             new WindowEvent((Window) getSource(), windowId, oldState, newState);
+ *         for (WindowListener listener : this) 
+ *         {
+ *             listener.windowOpened(windowEvent);
+ *         }
+ *     }
+ * }
+ * </pre></code>
+ * </p>
+ * 
+ * @author <a href="mailto:mwooten.dev@gmail.com">Michael Wooten</a>
+ *
+ * @param <L> the subclass of {@link EventListener} that this event support
+ *        class can register.
+ * 
+ * @since 3.0
+ */
+public abstract class AbstractEventSupport<L extends EventListener> 
+    implements EventSupport<L>, Iterable<L>, Serializable {
+
+    /**
+     * The serialization unique version identifier.
+     */
+    private static final long serialVersionUID = 20100310L;
+
+    /**
+     * 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 CopyOnWriteArrayList<L> listeners;
+    
+    /**
+     * The object registered as the source of events fired to the listeners.
+     */
+    private final Object source;
+    
+    /**
+     * Constructs a new AbstractEventSupport object and associates it with the
+     * object that will be used as the source of all events sent to the 
+     * listeners.
+     * 
+     * @param source the object that will be used as the source of all events
+     *        posted to the listeners.
+     *        
+     * @throws NullPointerException if <code>source</code> is 
+     *         <code>null</code>.
+     */
+    protected AbstractEventSupport(Object source) {
+        Validate.notNull(source, "source cannot be null");
+        this.source = source;
+        this.listeners = new CopyOnWriteArrayList<L>();
+    }
+    
+    /**
+     * Registers a listener to receive events posted the by the supported class.
+     * 
+     * @param listener the listener to register for posted events. Values of 
+     *        <code>null</code> will be ignored.
+     */
+    public void addListener(L listener) {
+        if (listener != null)
+        {
+            this.listeners.add(listener);
+        }
+    }
+    
+    /**
+     * Unregisters a listener from receiving events posted by the supported 
+     * class.
+     * 
+     * @param listener the listener to stop posting events to. Values of 
+     *        <code>null</code> will be ignored.
+     */
+    public void removeListener(L listener) {
+        if (listener != null)
+        {
+            this.listeners.remove(listener);
+        }
+    }
+    
+    /**
+     * Returns a reference to the object registered as the source of events 
+     * broadcast to the listeners.
+     * 
+     * @return the object that was initially registered to be the source of all
+     *         events sent to the listeners.
+     */
+    public Object getSource() {
+        return this.source;
+    }
+    
+    /**
+     * Returns an iterator over the current list of listeners. This iterator is
+     * immutable and does not support {@link Iterator#remove()} operations.
+     * 
+     * @return an iterator to iterate over the currently registered listeners.
+     */
+    public Iterator<L> iterator() {
+        return this.listeners.iterator();
+    }
+}

Propchange: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/AbstractEventSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/EventSupport.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/EventSupport.java?rev=965165&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/EventSupport.java
(added)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/EventSupport.java
Sun Jul 18 06:05:51 2010
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.lang3.event;
+
+import java.util.EventListener;
+
+/**
+ * <p>
+ * The EventSupport interface identifies as class as being able to register
+ * listeners for events. 
+ * </p>
+ * 
+ * @author <a href="mailto:mwooten.dev@gmail.com">Michael Wooten</a>
+ *
+ * @param <L> the subclass of {@link EventListener} that this event support
+ *        class can register.
+ *        
+ * @since 3.0
+ */
+public interface EventSupport<L extends EventListener> {
+
+    /**
+     * Registers a listener to receive events posted the by the supported class.
+     * 
+     * @param listener the listener to register for posted events. Values of 
+     *        <code>null</code> will be ignored.
+     */
+    public void addListener(L listener);
+    
+    /**
+     * Unregisters a listener from receiving events posted by the supported 
+     * class.
+     * 
+     * @param listener the listener to stop posting events to. Values of 
+     *        <code>null</code> will be ignored.
+     */
+    public void removeListener(L listener);
+}

Propchange: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/EventSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/ReflectiveEventSupport.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/ReflectiveEventSupport.java?rev=965165&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/ReflectiveEventSupport.java
(added)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/ReflectiveEventSupport.java
Sun Jul 18 06:05:51 2010
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.lang3.event;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.EventListener;
+import java.util.EventObject;
+
+import org.apache.commons.lang3.Validate;
+import org.apache.commons.lang3.reflect.MethodUtils;
+
+/**
+ * <p>
+ * The ReflectiveEventSupport class provides a means of posting 
+ * {@link EventObject}s to registered listeners. The class uses reflection to
+ * call specified methods on the listeners, either by {@link Method} or method 
+ * name.
+ * </p>
+ * 
+ * <p>
+ * <em>NOTE: The methods on the listeners must be accessible in order to be
+ * called.</em>
+ * </p>
+ * 
+ * <p>
+ * Example:
+ * <code><pre>
+ * ReflectiveEventSupport<ChangeListener> reflectiveEventSupport = 
+ *    new ReflectiveEventSupport<ChangeListener>(this);
+ * 
+ * ...
+ *    
+ * reflectiveEventSupport.addListener(listener);
+ * 
+ * ...
+ * 
+ * reflectiveEventSupport.fireEvent("stateChanged",
+ *     new ChangeEvent(reflectiveEventSupport.getSource());
+ * </pre></code>
+ * </p>
+ * 
+ * @author <a href="mailto:mwooten.dev@gmail.com">Michael Wooten</a>
+ *
+ * @param <L> the subclass of {@link EventListener} that this event support
+ *        class can register.
+ * 
+ * @since 3.0
+ */
+public class ReflectiveEventSupport<L extends EventListener> 
+    extends AbstractEventSupport<L> {
+
+    /**
+     * The serialization unique version identifier.
+     */
+    private static final long serialVersionUID = 20100310L;
+    
+    /**
+     * Constructs a new ReflectiveEventSupport object and associates it with the
+     * object that can be used as the source of all events sent to the 
+     * listeners.
+     * 
+     * @param source the object that can be used as the source of all events
+     *        posted to the listeners.
+     *        
+     * @throws NullPointerException if <code>source</code> is 
+     *         <code>null</code>.
+     */
+    public ReflectiveEventSupport(Object source) {
+        super(source);
+    }
+
+    /**
+     * Fires the provided event object to the named method specified on each of 
+     * the listeners registered with this event support class.
+     * 
+     * @param <E>
+     *            the {@link EventObject} type that will be posted to the
+     *            listeners.
+     * 
+     * @param methodName
+     *            the name of the method that should be called on each of the
+     *            listeners.
+     * @param eventObject
+     *            the event object that will be passed to the listener's method.
+     * 
+     * @throws NullPointerException 
+     *             if <code>methodName</code> is <code>null</code>.
+     * @throws NoSuchMethodException
+     *             if there is no such accessible method
+     * @throws InvocationTargetException
+     *             wraps an exception thrown by the method invoked
+     * @throws IllegalAccessException
+     *             if the requested method is not accessible via reflection
+     */
+    public <E extends EventObject> void fireEvent(String methodName, E eventObject)

+        throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        Validate.notNull(methodName, "methodName cannot be null");
+        for (L listener : this) {
+            MethodUtils.invokeMethod(listener, methodName, eventObject);
+        }
+    }
+    
+    /**
+     * Fires the provided event object to the method specified on each of the
+     * listeners registered with this event support class.
+     * 
+     * @param <E>
+     *            the {@link EventObject} type that will be posted to the
+     *            listeners.
+     * @param method
+     *            the method that should be called on each of the listeners.
+     * @param eventObject
+     *            the event object that will be passed to the listener's method.
+     * 
+     * @throws NullPointerException 
+     *             if <code>method</code> is <code>null</code>.
+     * @throws NoSuchMethodException 
+     *            if there is no such accessible method
+     * @throws InvocationTargetException 
+     *            wraps an exception thrown by the method invoked
+     * @throws IllegalAccessException 
+     *            if the requested method is not accessible via reflection
+     */
+    public <E extends EventObject> void fireEvent(Method method, E eventObject) 
+        throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        Validate.notNull(method, "method cannot be null");
+        Method accessibleMethod = MethodUtils.getAccessibleMethod(method);
+        for (L listener : this) {
+            accessibleMethod.invoke(listener, eventObject);
+        }
+    }
+}

Propchange: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/event/ReflectiveEventSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/event/AbstractEventSupportTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/event/AbstractEventSupportTest.java?rev=965165&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/event/AbstractEventSupportTest.java
(added)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/event/AbstractEventSupportTest.java
Sun Jul 18 06:05:51 2010
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.lang3.event;
+
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import junit.framework.TestCase;
+
+/**
+ * <p>
+ * The {@link AbstractEventSupportTestCase} class provides test cases for 
+ * testing the {@link AbstractEventSupport} class.
+ * </p>
+ * 
+ * @author <a href="mailto:mwooten.dev@gmail.com">Michael Wooten</a>
+ *
+ * @since 3.0
+ */
+public class AbstractEventSupportTest extends TestCase {
+
+    /**
+     * The event support mock object that will be used for testing.
+     */
+    private AbstractEventSupport<ChangeListener> eventSupport;
+    
+    /**
+     * Creates the implementation of {@link AbstractEventSupport} that will be
+     * used for testing.
+     */
+    public void setUp() throws Exception {
+        eventSupport = new AbstractEventSupportMock(this);
+    }
+    
+    /**
+     * Tests that the 
+     * {@link AbstractEventSupport#addListener(java.util.EventListener)}
+     * properly registers a listener.
+     */
+    public void testAddListener() {
+        ChangeListener changeListener = new ChangeListenerMock();
+        eventSupport.addListener(changeListener);
+        assertTrue(eventSupport.iterator().hasNext());
+        assertEquals(changeListener, eventSupport.iterator().next());
+    }
+    
+    /**
+     * Tests that the 
+     * {@link AbstractEventSupport#addListener(java.util.EventListener)}
+     * method performs no operation when provided the value of 
+     * <code>null</code>.
+     */
+    public void testAddNullListener() {
+        eventSupport.addListener(null);
+        assertFalse(eventSupport.iterator().hasNext());
+    }
+
+    /**
+     * Tests that the 
+     * {@link AbstractEventSupport#removeListener(java.util.EventListener)}
+     * properly removes a previously registered listener.
+     */
+    public void testRemoveListener() {
+        ChangeListener changeListener = new ChangeListenerMock();
+        eventSupport.addListener(changeListener);
+        assertTrue(eventSupport.iterator().hasNext());
+        eventSupport.removeListener(changeListener);
+        assertFalse(eventSupport.iterator().hasNext());
+    }
+    
+    /**
+     * Tests that the 
+     * {@link AbstractEventSupport#removeListener(java.util.EventListener)}
+     * method performs no operation when provided the value of 
+     * <code>null</code>.
+     */
+    public void testRemoveNullListener() {
+        ChangeListener changeListener = new ChangeListenerMock();
+        eventSupport.addListener(changeListener);
+        assertTrue(eventSupport.iterator().hasNext());
+        eventSupport.removeListener(null);
+        assertTrue(eventSupport.iterator().hasNext());
+    }
+
+    /**
+     * Tests that the source registered with the event support is the one 
+     * provided by {@link AbstractEventSupport#getSource()}.
+     */
+    public void testGetSource() {
+        assertEquals(this, eventSupport.getSource());
+    }
+
+    /**
+     * Tests that the event support object returns an iterator of the registered
+     * listeners.
+     */
+    public void testIterator() {
+        ChangeListener changeListener = new ChangeListenerMock();
+        eventSupport.addListener(changeListener);
+        assertNotNull(eventSupport.iterator());
+        assertTrue(eventSupport.iterator().hasNext());
+    }
+    
+    /**
+     * <p>
+     * The AbstractEventSupportMock class provides a mock version of the
+     * {@link AbstractEventSupport} class that can be used for testing since
+     * AbstractEventSupport is an abstract class.
+     * </p>
+     */
+    @SuppressWarnings("serial")
+    private class AbstractEventSupportMock extends AbstractEventSupport<ChangeListener>
{
+
+        /**
+         * Constructs a new AbstractEventSupportMock and associates it with the
+         * source of the events.
+         * 
+         * @param source the source of the events.
+         */
+        public AbstractEventSupportMock(Object source) {
+            super(source);
+        }
+    }
+    
+    /**
+     * <p>
+     * The ChangeListenerMock class provides a mock version of the
+     * {@link ChangeListener} interface that can be used for testing.
+     * </p>
+     */
+    private class ChangeListenerMock implements ChangeListener {
+        public void stateChanged(ChangeEvent changeEvent) {
+        }
+    }
+}

Propchange: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/event/AbstractEventSupportTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/event/ReflectiveEventSupportTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/event/ReflectiveEventSupportTest.java?rev=965165&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/event/ReflectiveEventSupportTest.java
(added)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/event/ReflectiveEventSupportTest.java
Sun Jul 18 06:05:51 2010
@@ -0,0 +1,355 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.lang3.event;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import junit.framework.TestCase;
+
+/**
+ * <p>
+ * The ReflectiveEventSupportTest class provides a set of unit tests for the 
+ * {@link ReflectiveEventSupport} class.
+ * </p>
+ * 
+ * @author <a href="mailto:mwooten.dev@gmail.com">Michael Wooten</a>
+ * 
+ * @since 3.0
+ */
+public class ReflectiveEventSupportTest extends TestCase {
+
+    /**
+     * The event support mock object that will be used for testing.
+     */
+    private ReflectiveEventSupport<ChangeListener> eventSupport;
+    
+    /**
+     * The first listener that will be registered for change events.
+     */
+    private ChangeDetectedChangeListener firstChangeListener;
+    
+    /**
+     * The second listener that will be registered for change events.
+     */
+    private ChangeDetectedChangeListener secondChangeListener;
+    
+    /**
+     * Creates the {@link ReflectiveEventSupport} instance under test and 
+     * registers a couple of {@link ChangeDetectedChangeListener}s with the
+     * event support.
+     */
+    protected void setUp() throws Exception {
+        eventSupport = new ReflectiveEventSupport<ChangeListener>(this);
+        firstChangeListener = new ChangeDetectedChangeListener();
+        secondChangeListener = new ChangeDetectedChangeListener();
+        eventSupport.addListener(firstChangeListener);
+        eventSupport.addListener(secondChangeListener);
+    }
+
+    /**
+     * Tests the {@link ReflectiveEventSupport#ReflectiveEventSupport(Object)}
+     * constructor.
+     */
+    public void testReflectiveEventSupport() {
+        try 
+        {
+            new ReflectiveEventSupport<ChangeListener>(null);
+            fail("ReflectiveEventSupport(null) did not throw an IllegalArgumentException");
+        }
+        catch (NullPointerException iae)
+        {
+            // Success, the exception was properly thrown
+        }
+    }
+
+    /**
+     * Tests the 
+     * {@link ReflectiveEventSupport#fireEvent(String, java.util.EventObject)}
+     * method to ensure that events will be propagated to accessible methods
+     * with the provided name.
+     * 
+     * @throws NoSuchMethodException
+     * @throws IllegalAccessException
+     * @throws InvocationTargetException
+     */
+    public void testFireEventByMethodName() throws NoSuchMethodException, 
+        IllegalAccessException, InvocationTargetException {
+        ChangeEvent changeEvent = new ChangeEvent(eventSupport.getSource());
+        eventSupport.fireEvent("stateChanged", changeEvent);
+        assertTrue("ChangeEvent not propogated to first change lisetener", 
+                firstChangeListener.isChanged());
+        assertTrue("ChangeEvent not propogated to second change lisetener", 
+                secondChangeListener.isChanged());
+    }
+    
+    /**
+     * Tests the 
+     * {@link ReflectiveEventSupport#fireEvent(String, java.util.EventObject)}
+     * method to ensure that a {@link NoSuchMethodException} is thrown if the
+     * method is not accessible.
+     * 
+     * @throws IllegalAccessException
+     * @throws InvocationTargetException
+     */
+    public void testFireEventByMethodNameToInaccessibleMethods() 
+        throws IllegalAccessException, InvocationTargetException {
+        
+        ChangeEvent changeEvent = new ChangeEvent(eventSupport.getSource());
+        
+        try
+        {
+            eventSupport.fireEvent("privateMethod", changeEvent);
+            fail("eventSupport.fireEvent() did not throw an exception " +
+                "for a private method");
+        } 
+        catch (NoSuchMethodException nsme)
+        {
+            // Success
+        }
+        
+        try
+        {
+            eventSupport.fireEvent("protectedMethod", changeEvent);
+            fail("eventSupport.fireEvent() did not throw an exception " +
+                "for a protected method");
+        } 
+        catch (NoSuchMethodException nsme)
+        {
+            // Success
+        }
+        
+        try
+        {
+            eventSupport.fireEvent("defaultMethod", changeEvent);
+            fail("eventSupport.fireEvent() did not throw an exception " +
+                "for a default method");
+        } 
+        catch (NoSuchMethodException nsme)
+        {
+            // Success
+        }
+    }
+    
+    /**
+     * Tests the 
+     * {@link ReflectiveEventSupport#fireEvent(String, java.util.EventObject)}
+     * method to ensure that a {@link NullPointerException} is thrown if a 
+     * <code>null</code> value is provided for the method name.
+     * 
+     * @throws NoSuchMethodException
+     * @throws IllegalAccessException
+     * @throws InvocationTargetException
+     */
+    public void testFireEventNullMethodName() throws NoSuchMethodException, 
+        IllegalAccessException, 
+        InvocationTargetException {
+        try
+        {
+            ChangeEvent changeEvent = new ChangeEvent(eventSupport.getSource());
+            eventSupport.fireEvent((String) null, changeEvent);
+            fail("eventSupport.fireEvent() did not throw an exception for a " +
+                "null method name.");
+        }
+        catch (NullPointerException npe)
+        {
+            // Success
+        }
+    }
+
+    /**
+     * Tests the 
+     * {@link ReflectiveEventSupport#fireEvent(Method, java.util.EventObject)}
+     * method to ensure that events will be propagated to the accessible method
+     * provided.
+     * 
+     * @throws NoSuchMethodException
+     * @throws IllegalAccessException
+     * @throws InvocationTargetException
+     */
+    public void testFireEventByMethod() throws NoSuchMethodException, 
+        IllegalAccessException, InvocationTargetException {
+        ChangeEvent changeEvent = new ChangeEvent(eventSupport.getSource());
+        Method stateChangedMethod = 
+            ChangeListener.class.getMethod("stateChanged", ChangeEvent.class);
+        eventSupport.fireEvent(stateChangedMethod, changeEvent);
+        assertTrue("ChangeEvent not propogated to first change lisetener", 
+                firstChangeListener.isChanged());
+        assertTrue("ChangeEvent not propogated to second change lisetener", 
+                secondChangeListener.isChanged());
+    }
+    
+    /**
+     * Tests the 
+     * {@link ReflectiveEventSupport#fireEvent(Method, java.util.EventObject)}
+     * method to ensure that a {@link NoSuchMethodException} is thrown if the
+     * method is not accessible.
+     * 
+     * @throws IllegalAccessException
+     * @throws InvocationTargetException
+     */
+    public void testFireEventByMethodToInaccessibleMethods() 
+        throws IllegalAccessException, InvocationTargetException {
+        
+        ChangeEvent changeEvent = new ChangeEvent(eventSupport.getSource());
+        
+        try
+        {
+            Method privateMethod = 
+                ChangeListener.class.getMethod("privateMethod", 
+                    ChangeEvent.class);
+            eventSupport.fireEvent(privateMethod, changeEvent);
+            fail("eventSupport.fireEvent() did not throw an exception " +
+                "for a private method");
+        } 
+        catch (NoSuchMethodException nsme)
+        {
+            // Success
+        }
+        
+        try
+        {
+            Method protectedMethod = 
+                ChangeListener.class.getMethod("protectedMethod", 
+                    ChangeEvent.class);
+            eventSupport.fireEvent(protectedMethod, changeEvent);
+            fail("eventSupport.fireEvent() did not throw an exception " +
+                "for a protected method");
+        } 
+        catch (NoSuchMethodException nsme)
+        {
+            // Success
+        }
+        
+        try
+        {
+            Method defaultMethod = 
+                ChangeListener.class.getMethod("defaultMethod", 
+                    ChangeEvent.class);
+            eventSupport.fireEvent(defaultMethod, changeEvent);
+            fail("eventSupport.fireEvent() did not throw an exception " +
+                "for a default method");
+        } 
+        catch (NoSuchMethodException nsme)
+        {
+            // Success
+        }
+    }
+
+    /**
+     * Tests the 
+     * {@link ReflectiveEventSupport#fireEvent(Method, java.util.EventObject)}
+     * method to ensure that a {@link NullPointerException} is thrown if a 
+     * <code>null</code> value is provided for the method.
+     * 
+     * @throws NoSuchMethodException
+     * @throws IllegalAccessException
+     * @throws InvocationTargetException
+     */
+    public void testFireEventNullMethod() throws NoSuchMethodException, 
+        IllegalAccessException, InvocationTargetException {
+        try
+        {
+            ChangeEvent changeEvent = new ChangeEvent(eventSupport.getSource());
+            eventSupport.fireEvent((Method) null, changeEvent);
+            fail("eventSupport.fireEvent() did not throw an exception for a " +
+                "null method.");
+        }
+        catch (NullPointerException npe)
+        {
+            // Success
+        }
+    }
+    
+    /**
+     * Tests the {@link ReflectiveEventSupport#getSource()} method to ensure it
+     * returns the source object it was originally provided.
+     */
+    public void testGetSource() {
+        assertEquals(this, eventSupport.getSource());
+    }
+
+    /**
+     * <p>
+     * The ChangeDetectedChangeListener class provides a version of the
+     * {@link ChangeListener} interface that detects when the listener has 
+     * been called. The class provides an {@link #isChanged()} method that
+     * will indicate whether or not the listener has been called.
+     * </p>
+     */
+    public class ChangeDetectedChangeListener implements ChangeListener {
+        
+        /**
+         * Represents whether or not the listener has detected a change.
+         */
+        private boolean changed = false;
+        
+        /**
+         * Called whenever a change is detected.
+         * 
+         * @param changeEvent the change event indicating a state change.
+         */
+        public void stateChanged(ChangeEvent changeEvent) {
+            this.changed = true;
+        }
+        
+        /**
+         * Returns whether or not the listener has detected a change event.
+         * 
+         * @return <code>true</code> if the listener has detected a change
+         *         event, <code>false</code> otherwise.
+         */
+        public boolean isChanged() {
+            return this.changed;
+        }
+        
+        /**
+         * A default (package private) method used to test 
+         * ReflectiveEventSupport calls to inaccessible methods.
+         * 
+         * @param changeEvent not used.
+         */
+        void defaultMethod(ChangeEvent changeEvent) {
+            this.changed = true;
+        }
+        
+        /**
+         * A protected method used to test ReflectiveEventSupport calls to 
+         * inaccessible methods.
+         * 
+         * @param changeEvent not used.
+         */
+        protected void protectedMethod(ChangeEvent changeEvent) {
+            this.changed = true;
+        }
+        
+        /**
+         * A private method used to test ReflectiveEventSupport calls to 
+         * inaccessible methods.
+         * 
+         * @param changeEvent not used.
+         */
+        @SuppressWarnings("unused")
+        private void privateMethod(ChangeEvent changeEvent) {
+            this.changed = true;
+        }
+    }
+}

Propchange: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/event/ReflectiveEventSupportTest.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message