You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by jk...@apache.org on 2007/04/28 21:50:33 UTC

svn commit: r533422 - in /tapestry/tapestry4/trunk/tapestry-framework/src: java/org/apache/tapestry/internal/event/ java/org/apache/tapestry/internal/event/impl/ java/org/apache/tapestry/services/impl/ test/org/apache/tapestry/internal/event/impl/

Author: jkuhnert
Date: Sat Apr 28 12:50:32 2007
New Revision: 533422

URL: http://svn.apache.org/viewvc?view=rev&rev=533422
Log:
-) Made ComponentEventInvoker thread safe.

-) Added caching of component event properties for minor performance improvements in overall component rendering.

Modified:
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/IComponentEventInvoker.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/impl/ComponentEventInvoker.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/internal/event/impl/ComponentEventInvokerTest.java

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/IComponentEventInvoker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/IComponentEventInvoker.java?view=diff&rev=533422&r1=533421&r2=533422
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/IComponentEventInvoker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/IComponentEventInvoker.java Sat Apr 28 12:50:32 2007
@@ -51,7 +51,17 @@
      * @return The bound listeners, or null if none exist.
      */
     List getEventListeners(String componentId);
-    
+
+    /**
+     * Gets all bound property event listeners for the specified componentIdPath.
+     *
+     * @param componentIdPath
+     *          The unique id path of the component, as returned from {@link org.apache.tapestry.IComponent#getIdPath()}.
+     *
+     * @return The aggregated array of all event properties bound to the specified component, empty if none exist.
+     */
+    ComponentEventProperty[] getEventPropertyListeners(String componentIdPath);
+
     /**
      * Adds a mapping for an event listener that should be triggered when the specified
      * form component with id of <code>formId</code> is submitted. This will later

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/impl/ComponentEventInvoker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/impl/ComponentEventInvoker.java?view=diff&rev=533422&r1=533421&r2=533422
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/impl/ComponentEventInvoker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/internal/event/impl/ComponentEventInvoker.java Sat Apr 28 12:50:32 2007
@@ -13,6 +13,7 @@
 // limitations under the License.
 package org.apache.tapestry.internal.event.impl;
 
+import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
 import org.apache.hivemind.util.Defense;
 import org.apache.tapestry.IActionListener;
 import org.apache.tapestry.IComponent;
@@ -26,6 +27,7 @@
 import org.apache.tapestry.internal.event.IComponentEventInvoker;
 import org.apache.tapestry.listener.ListenerInvoker;
 import org.apache.tapestry.spec.IComponentSpecification;
+import org.apache.tapestry.spec.IEventListener;
 
 import java.util.*;
 
@@ -37,13 +39,18 @@
  */
 public class ComponentEventInvoker implements IComponentEventInvoker, ResetEventListener
 {
+    static final ComponentEventProperty[] EMPTY_PROPERTIES = new ComponentEventProperty[0];
+
     // Mapped component id path -> List of IEventListeners
-    private Map _components = new HashMap();
+    private Map _components = new ConcurrentHashMap();
     // Mapped form id path -> List of IEventListeners
-    private Map _formComponents = new HashMap();
+    private Map _formComponents = new ConcurrentHashMap();
     // Used to invoke actual listener methods
     private ListenerInvoker _invoker;
 
+    // Cached set of ComponentEventProperty[] arrays mapped to specific components
+    private Map _propertyCache = new ConcurrentHashMap();
+
     /**
      * {@inheritDoc}
      */
@@ -236,6 +243,8 @@
         if (!listeners.contains(listener)) {
             listeners.add(listener);
         }
+        
+        _propertyCache.remove(componentId);
     }
     
     /**
@@ -243,9 +252,40 @@
      */
     public List getEventListeners(String componentId)
     {
+        if (componentId == null)
+            return null;
+        
         return (List)_components.get(componentId);
     }
-    
+
+    public ComponentEventProperty[] getEventPropertyListeners(String componentIdPath)
+    {
+        if (componentIdPath == null)
+            return EMPTY_PROPERTIES;
+        
+        ComponentEventProperty[] ret = (ComponentEventProperty[])_propertyCache.get(componentIdPath);
+        if (ret != null)
+            return ret;
+
+        List listeners = getEventListeners(componentIdPath);
+        if (listeners == null || listeners.size() < 1)
+            return EMPTY_PROPERTIES;
+
+        List props = new ArrayList();
+        for (int i=0; i < listeners.size(); i++) {
+
+            IEventListener listener = (IEventListener)listeners.get(i);
+
+            props.add(listener.getComponentEvents(componentIdPath));
+        }
+
+        ret = (ComponentEventProperty[])props.toArray(new ComponentEventProperty[props.size()]);
+
+        _propertyCache.put(componentIdPath, ret);
+
+        return ret;
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -268,6 +308,9 @@
      */
     public List getFormEventListeners(String formId)
     {
+        if (formId == null)
+            return null;
+        
         return (List)_formComponents.get(formId);
     }
     
@@ -278,6 +321,7 @@
     {
         _components.clear();
         _formComponents.clear();
+        _propertyCache.clear();
     }
     
     /** Injected. */

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java?view=diff&rev=533422&r1=533421&r2=533422
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/ComponentEventConnectionWorker.java Sat Apr 28 12:50:32 2007
@@ -26,7 +26,6 @@
 import org.apache.tapestry.internal.event.EventBoundListener;
 import org.apache.tapestry.internal.event.IComponentEventInvoker;
 import org.apache.tapestry.services.ComponentRenderWorker;
-import org.apache.tapestry.spec.IEventListener;
 import org.apache.tapestry.util.ScriptUtils;
 
 import java.util.*;
@@ -96,7 +95,7 @@
     
     void linkComponentEvents(IRequestCycle cycle, IComponent component)
     {
-        ComponentEventProperty[] props = getComponentEvents(component);
+        ComponentEventProperty[] props = _invoker.getEventPropertyListeners(component.getIdPath());
         if (props == null)
             return;
         
@@ -128,24 +127,6 @@
         }
     }
     
-    ComponentEventProperty[] getComponentEvents(IComponent comp)
-    {
-        List listeners = _invoker.getEventListeners(comp.getIdPath());
-        if (listeners == null || listeners.size() < 1)
-            return null;
-
-        List ret = new ArrayList();
-        
-        for (int i=0; i < listeners.size(); i++) {
-            
-            IEventListener listener = (IEventListener)listeners.get(i);
-            
-            ret.add(listener.getComponentEvents(comp.getIdPath()));
-        }
-        
-        return (ComponentEventProperty[])ret.toArray(new ComponentEventProperty[ret.size()]);
-    }
-    
     void linkElementEvents(IRequestCycle cycle, IComponent component)
     {
         if (!component.getSpecification().hasElementEvents())
@@ -227,7 +208,7 @@
             
             linkElementEvents(cycle, component);
             
-            ComponentEventProperty[] props = getComponentEvents(component);
+            ComponentEventProperty[] props = _invoker.getEventPropertyListeners(component.getIdPath());
             if (props == null)
                 continue;
             

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/internal/event/impl/ComponentEventInvokerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/internal/event/impl/ComponentEventInvokerTest.java?view=diff&rev=533422&r1=533421&r2=533422
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/internal/event/impl/ComponentEventInvokerTest.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/internal/event/impl/ComponentEventInvokerTest.java Sat Apr 28 12:50:32 2007
@@ -73,6 +73,32 @@
         assertEquals(p.getFormEvents().size(), 1);
     }
 
+    public void test_Get_Event_Property_Listeners()
+    {
+        IComponentSpecification spec = new ComponentSpecification();
+        spec.setComponentClassName("first.test");
+        spec.addEventListener("comp1", new String[] {"onClick"}, "testFoo", null, false, true, false, false);
+        spec.addEventListener("comp1", new String[] {"onClick"}, "testBar", null, false, true, false, false);
+
+        IComponentSpecification spec2 = new ComponentSpecification();
+        spec.setComponentClassName("second.test"); // to make .equals unique
+        spec2.addEventListener("comp1", new String[] {"onClick"}, "testFoo", null, false, true, false, false);
+        spec2.addEventListener("comp1", new String[] {"onClick"}, "testBar", null, false, true, false, false);
+
+        ComponentEventInvoker invoker = new ComponentEventInvoker();
+        invoker.addEventListener("comp1", spec);
+        invoker.addEventListener("comp1", spec2);
+
+        ComponentEventProperty[] empty = invoker.getEventPropertyListeners("bogus");
+        assert empty != null;
+        assertEquals(empty.length, 0);
+
+        ComponentEventProperty[] props = invoker.getEventPropertyListeners("comp1");
+        assertEquals(props.length, 2);
+
+        assert invoker.getEventPropertyListeners("comp1") == props;
+    }
+
     public void test_Invoke_Component_Listener()
     {
         IRequestCycle cycle = newCycle();