]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fixed #588 (partially, other places still need fixes)
authorJani Laakso <jani.laakso@itmill.com>
Thu, 31 Jan 2008 11:06:01 +0000 (11:06 +0000)
committerJani Laakso <jani.laakso@itmill.com>
Thu, 31 Jan 2008 11:06:01 +0000 (11:06 +0000)
EventRouter
 * is now thread safe
 * listenerList contains unique listeners, duplicates are not allowed

ListenerMethod
 * implemented proper equals and hashCode methods

AbstractComponent
 * @deprecated Use {@link #addListener(Class, Object, Method)} or
             {@link #addListener(com.itmill.toolkit.ui.Component.Listener)}
             instead. Using this method is discouraged because it cannot
              be checked during compilation.

svn changeset:3681/svn branch:trunk

src/com/itmill/toolkit/event/EventRouter.java
src/com/itmill/toolkit/event/ListenerMethod.java
src/com/itmill/toolkit/ui/AbstractComponent.java

index c6f04c51ad37aca4933fa306a174e144aa7e99e5..78f8a77df18695e7efcf8f06e97d54462322652b 100644 (file)
@@ -5,9 +5,11 @@
 package com.itmill.toolkit.event;
 
 import java.lang.reflect.Method;
+import java.util.Collections;
 import java.util.EventObject;
 import java.util.Iterator;
-import java.util.LinkedList;
+import java.util.LinkedHashSet;
+import java.util.Set;
 
 /**
  * <code>EventRouter</code> class implementing the inheritable event listening
@@ -24,7 +26,7 @@ public class EventRouter implements MethodEventSource {
     /**
      * List of registered listeners.
      */
-    private LinkedList listenerList = null;
+    private Set listenerList = null;
 
     /*
      * Registers a new listener with the specified activation method to listen
@@ -34,10 +36,12 @@ public class EventRouter implements MethodEventSource {
     public void addListener(Class eventType, Object object, Method method) {
 
         if (listenerList == null) {
-            listenerList = new LinkedList();
+            listenerList = Collections.synchronizedSet(new LinkedHashSet());
         }
 
-        listenerList.add(new ListenerMethod(eventType, object, method));
+        synchronized (listenerList) {
+            listenerList.add(new ListenerMethod(eventType, object, method));
+        }
     }
 
     /*
@@ -48,10 +52,12 @@ public class EventRouter implements MethodEventSource {
     public void addListener(Class eventType, Object object, String methodName) {
 
         if (listenerList == null) {
-            listenerList = new LinkedList();
+            listenerList = Collections.synchronizedSet(new LinkedHashSet());
         }
 
-        listenerList.add(new ListenerMethod(eventType, object, methodName));
+        synchronized (listenerList) {
+            listenerList.add(new ListenerMethod(eventType, object, methodName));
+        }
     }
 
     /*
@@ -60,17 +66,19 @@ public class EventRouter implements MethodEventSource {
      * interface.
      */
     public void removeListener(Class eventType, Object target) {
-
         if (listenerList != null) {
-            final Iterator i = listenerList.iterator();
-            while (i.hasNext()) {
-                try {
-                    final ListenerMethod lm = (ListenerMethod) i.next();
-                    if (lm.matches(eventType, target)) {
-                        i.remove();
+            synchronized (listenerList) {
+                final Iterator i = listenerList.iterator();
+                while (i.hasNext()) {
+                    try {
+                        final ListenerMethod lm = (ListenerMethod) i.next();
+                        if (lm.matches(eventType, target)) {
+                            i.remove();
+                            return;
+                        }
+                    } catch (final java.lang.ClassCastException e) {
+                        // Class cast exceptions are ignored
                     }
-                } catch (final java.lang.ClassCastException e) {
-                    // Class cast exceptions are ignored
                 }
             }
         }
@@ -84,22 +92,25 @@ public class EventRouter implements MethodEventSource {
     public void removeListener(Class eventType, Object target, Method method) {
 
         if (listenerList != null) {
-            final Iterator i = listenerList.iterator();
-            while (i.hasNext()) {
-                try {
-                    final ListenerMethod lm = (ListenerMethod) i.next();
-                    if (lm.matches(eventType, target, method)) {
-                        i.remove();
+            synchronized (listenerList) {
+                final Iterator i = listenerList.iterator();
+                while (i.hasNext()) {
+                    try {
+                        final ListenerMethod lm = (ListenerMethod) i.next();
+                        if (lm.matches(eventType, target, method)) {
+                            i.remove();
+                            return;
+                        }
+                    } catch (final java.lang.ClassCastException e) {
+                        // Class cast exceptions are ignored
                     }
-                } catch (final java.lang.ClassCastException e) {
-                    // Class cast exceptions are ignored
                 }
             }
         }
     }
 
     /*
-     * Removes the event listener method matching the given given paramaters.
+     * Removes the event listener method matching the given given parameters.
      * Don't add a JavaDoc comment here, we use the default documentation from
      * implemented interface.
      */
@@ -119,15 +130,18 @@ public class EventRouter implements MethodEventSource {
 
         // Remove the listeners
         if (listenerList != null) {
-            final Iterator i = listenerList.iterator();
-            while (i.hasNext()) {
-                try {
-                    final ListenerMethod lm = (ListenerMethod) i.next();
-                    if (lm.matches(eventType, target, method)) {
-                        i.remove();
+            synchronized (listenerList) {
+                final Iterator i = listenerList.iterator();
+                while (i.hasNext()) {
+                    try {
+                        final ListenerMethod lm = (ListenerMethod) i.next();
+                        if (lm.matches(eventType, target, method)) {
+                            i.remove();
+                            return;
+                        }
+                    } catch (final java.lang.ClassCastException e) {
+                        // Class cast exceptions are ignored
                     }
-                } catch (final java.lang.ClassCastException e) {
-                    // Class cast exceptions are ignored
                 }
             }
         }
@@ -137,7 +151,9 @@ public class EventRouter implements MethodEventSource {
      * Removes all listeners from event router.
      */
     public void removeAllListeners() {
-        listenerList = null;
+        synchronized (listenerList) {
+            listenerList = null;
+        }
     }
 
     /**
@@ -148,15 +164,15 @@ public class EventRouter implements MethodEventSource {
      *                the Event to be sent to all listeners.
      */
     public void fireEvent(EventObject event) {
-
         // It is not necessary to send any events if there are no listeners
         if (listenerList != null) {
-
             // Send the event to all listeners. The listeners themselves
             // will filter out unwanted events.
-            final Iterator i = new LinkedList(listenerList).iterator();
-            while (i.hasNext()) {
-                ((ListenerMethod) i.next()).receiveEvent(event);
+            synchronized (listenerList) {
+                final Iterator i = listenerList.iterator();
+                while (i.hasNext()) {
+                    ((ListenerMethod) i.next()).receiveEvent(event);
+                }
             }
         }
     }
index eaaf2a4e0fc011a60132e561f57eb44243f14eb3..8cf1d17c3e0af4c83659468f89ad7f131f7eb6d4 100644 (file)
@@ -5,6 +5,7 @@
 package com.itmill.toolkit.event;
 
 import java.lang.reflect.Method;
+import java.util.Arrays;
 import java.util.EventListener;
 import java.util.EventObject;
 
@@ -456,7 +457,7 @@ public class ListenerMethod implements EventListener {
      *                by this listener.
      * @return <code>true</code> if <code>target</code> is the same object
      *         as the one stored in this object and <code>eventType</code>
-     *         equals the event type stored in this object.
+     *         equals the event type stored in this object. *
      */
     public boolean matches(Class eventType, Object target) {
         return (target == object) && (eventType.equals(this.eventType));
@@ -486,6 +487,41 @@ public class ListenerMethod implements EventListener {
                         .equals(this.method));
     }
 
+    public int hashCode() {
+        int hash = 7;
+
+        hash = 31 * hash + eventArgumentIndex;
+        hash = 31 * hash + (eventType == null ? 0 : eventType.hashCode());
+        hash = 31 * hash + (object == null ? 0 : object.hashCode());
+        hash = 31 * hash + (method == null ? 0 : method.hashCode());
+        hash = 31 * hash + (arguments == null ? 0 : Arrays.hashCode(arguments));
+
+        return hash;
+    }
+
+    public boolean equals(Object obj) {
+
+        if (this == obj)
+            return true;
+
+        // return false if obj is a subclass (do not use instanceof check)
+        if ((obj == null) || (obj.getClass() != this.getClass()))
+            return false;
+
+        // obj is of same class, test it further
+        ListenerMethod t = (ListenerMethod) obj;
+
+        return eventArgumentIndex == t.eventArgumentIndex
+                && (eventType == t.eventType || (eventType != null && eventType
+                        .equals(t.eventType)))
+                && (object == t.object || (object != null && object
+                        .equals(t.object)))
+                && (method == t.method || (method != null && method
+                        .equals(t.method)))
+                && (arguments == t.arguments || (Arrays.deepEquals(arguments,
+                        t.arguments)));
+    }
+
     /**
      * Exception that wraps an exception thrown by an invoked method. When
      * <code>ListenerMethod</code> invokes the target method, it may throw
index dc305af320ed4d2868e9bafaa0e506546a6c9421..23b7aa49347bd2e14ecbadc01d57680d76efc8cc 100644 (file)
@@ -822,6 +822,10 @@ public abstract class AbstractComponent implements Component, MethodEventSource
      *                the object instance who owns the activation method.
      * @param methodName
      *                the name of the activation method.
+     * @deprecated Use {@link #addListener(Class, Object, Method)} or
+     *             {@link #addListener(com.itmill.toolkit.ui.Component.Listener)}
+     *             instead. Using this method is discouraged because it cannot
+     *             be checked during compilation.
      */
     public void addListener(Class eventType, Object object, String methodName) {
         if (eventRouter == null) {