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/05/21 00:18:43 UTC

svn commit: r539966 - in /tapestry/tapestry4/trunk: tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/ tapestry-framework/src/java/org/apache/tapestry/form/ tapestry-framework/src/java/org/apache/tapestry/listener/ tapestry-fr...

Author: jkuhnert
Date: Sun May 20 15:18:41 2007
New Revision: 539966

URL: http://svn.apache.org/viewvc?view=rev&rev=539966
Log:
Fixes TAPESTRY-1240. Listener methods would be reported as not found just because the arguments were null.

Modified:
    tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/form/AbstractSubmit.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapImpl.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapSourceImpl.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMethodInvokerImpl.java
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/ListenerMethodHolder.java
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/ListenerMethodInvokerTest.java
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/TestListenerMapSource.java

Modified: tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java?view=diff&rev=539966&r1=539965&r2=539966
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java (original)
+++ tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/page/TaskEntryPage.java Sun May 20 15:18:41 2007
@@ -132,7 +132,7 @@
         
         getTaskDao().addTask(task);
     }
-    
+
     @EventListener(events = "onSave", targets="projName")
     public void onNameUpdate()
     {

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/form/AbstractSubmit.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/form/AbstractSubmit.java?view=diff&rev=539966&r1=539965&r2=539966
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/form/AbstractSubmit.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/form/AbstractSubmit.java Sun May 20 15:18:41 2007
@@ -76,8 +76,7 @@
             }
             else
             {
-                cycle.setListenerParameters(new Object[]
-                { parameters });
+                cycle.setListenerParameters(new Object[] { parameters });
             }
         }
         

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapImpl.java?view=diff&rev=539966&r1=539965&r2=539966
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapImpl.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapImpl.java Sun May 20 15:18:41 2007
@@ -14,15 +14,15 @@
 
 package org.apache.tapestry.listener;
 
+import org.apache.hivemind.ApplicationRuntimeException;
+import org.apache.hivemind.util.Defense;
+import org.apache.tapestry.IActionListener;
+
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.hivemind.ApplicationRuntimeException;
-import org.apache.hivemind.util.Defense;
-import org.apache.tapestry.IActionListener;
-
 /**
  * @author Howard M. Lewis Ship
  * @since 4.0
@@ -70,12 +70,11 @@
 
     private IActionListener createListener(String name)
     {
-        ListenerMethodInvoker invoker = (ListenerMethodInvoker) _invokers
-                .get(name);
+        ListenerMethodInvoker invoker = (ListenerMethodInvoker) _invokers.get(name);
 
         if (invoker == null)
-            throw new ApplicationRuntimeException(ListenerMessages
-                    .objectMissingMethod(_target, name), _target, null, null);
+            throw new ApplicationRuntimeException(ListenerMessages.objectMissingMethod(_target, name),
+                                                  _target, null, null);
 
         return new SyntheticListener(_target, invoker);
     }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapSourceImpl.java?view=diff&rev=539966&r1=539965&r2=539966
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapSourceImpl.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMapSourceImpl.java Sun May 20 15:18:41 2007
@@ -14,27 +14,20 @@
 
 package org.apache.tapestry.listener;
 
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.hivemind.util.Defense;
 import org.apache.tapestry.IPage;
 import org.apache.tapestry.engine.ILink;
 import org.apache.tapestry.event.ResetEventListener;
 
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
 /**
  * @author Howard M. Lewis Ship
  * @since 4.0
  */
-public class ListenerMapSourceImpl implements ListenerMapSource,
-        ResetEventListener
+public class ListenerMapSourceImpl implements ListenerMapSource, ResetEventListener
 {
 
     /**

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMethodInvokerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMethodInvokerImpl.java?view=diff&rev=539966&r1=539965&r2=539966
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMethodInvokerImpl.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/listener/ListenerMethodInvokerImpl.java Sun May 20 15:18:41 2007
@@ -39,6 +39,16 @@
 {
 
     /**
+     * Used as default byte value in null method parameters for native types
+     */
+    private static final byte DEFAULT_BYTE = -1;
+
+    /**
+     * Used as default short value in null method parameters for native types
+     */
+    private static final short DEFAULT_SHORT = -1;
+    
+    /**
      * Methods with a name appropriate for this class, sorted into descending
      * order by number of parameters.
      */
@@ -70,8 +80,7 @@
         if (searchAndInvoke(target, cycle, listenerParameters))
             return;
         
-        throw new ApplicationRuntimeException(ListenerMessages
-                .noListenerMethodFound(_name, listenerParameters, target),
+        throw new ApplicationRuntimeException(ListenerMessages.noListenerMethodFound(_name, listenerParameters, target),
                 target, null, null);
     }
     
@@ -83,7 +92,9 @@
             event = (BrowserEvent)listenerParameters[listenerParameters.length - 1];
         
         List invokeParms = new ArrayList();
-        
+
+        Method possibleMethod = null;
+
         methods:
             for (int i = 0; i < _methods.length; i++, invokeParms.clear()) {
                 
@@ -93,8 +104,16 @@
                 Class[] parms = _methods[i].getParameterTypes();
                 
                 // impossible to call this
-                if (parms.length > (listenerParameters.length + 1) )
+                
+                if (parms.length > (listenerParameters.length + 1) ) {
+                    
+                    if (possibleMethod == null)
+                        possibleMethod = _methods[i];
+                    else if (parms.length < possibleMethod.getParameterTypes().length)
+                        possibleMethod = _methods[i];
+                    
                     continue;
+                }
                 
                 int listenerIndex = 0;
                 for (int p = 0; p < parms.length && listenerIndex < (listenerParameters.length + 1); p++) {
@@ -123,18 +142,74 @@
                     }
                 }
                 
-                if (invokeParms.size() != parms.length)
+                if (invokeParms.size() != parms.length) {
+
+                    // set possible method just in case
+                    
+                    if (possibleMethod == null)
+                        possibleMethod = _methods[i];
+                    else if (parms.length < possibleMethod.getParameterTypes().length)
+                        possibleMethod = _methods[i];
+
                     continue;
+                }
                 
-                invokeListenerMethod(_methods[i], target, cycle,
-                        invokeParms.toArray(new Object[invokeParms.size()]));
+                invokeListenerMethod(_methods[i], target, cycle, invokeParms.toArray(new Object[invokeParms.size()]));
                 
                 return true;
             }
-        
+
+        // if we didn't have enough parameters but still found a matching method name go ahead
+        // and do your best to fill in the parameters and invoke it
+
+        if (possibleMethod != null) {
+
+            Class[] parms = possibleMethod.getParameterTypes();
+            Object[] args = new Object[parms.length];
+            
+            for (int p=0; p < parms.length; p++) {
+
+                // setup primitive defaults
+                
+                if (parms[p].isPrimitive()) {
+
+                    if (parms[p] == Boolean.TYPE) {
+
+                        args[p] = Boolean.FALSE;
+                    } else if (parms[p] == Byte.TYPE) {
+
+                        args[p] = new Byte(DEFAULT_BYTE);
+                    } else if (parms[p] == Short.TYPE) {
+
+                        args[p] = new Short(DEFAULT_SHORT);
+                    } else if (parms[p] == Integer.TYPE) {
+
+                        args[p] = new Integer(-1);
+                    } else if (parms[p] == Long.TYPE) {
+
+                        args[p] = new Long(-1);
+                    } else if (parms[p] == Float.TYPE) {
+
+                        args[p] = new Float(-1);
+                    } else if (parms[p] == Double.TYPE) {
+
+                        args[p] = new Double(-1);
+                    }
+                }
+
+                if (IRequestCycle.class.isAssignableFrom(parms[p])) {
+                    args[p] = cycle;
+                }
+            }
+            
+            invokeListenerMethod(possibleMethod, target, cycle, args);
+            
+            return true;
+        }
+
         return false;
     }
-    
+
     private void invokeListenerMethod(Method listenerMethod, Object target,
             IRequestCycle cycle, Object[] parameters)
     {
@@ -152,14 +227,12 @@
             if (targetException instanceof ApplicationRuntimeException)
                 throw (ApplicationRuntimeException) targetException;
 
-            throw new ApplicationRuntimeException(ListenerMessages
-                    .listenerMethodFailure(listenerMethod, target,
+            throw new ApplicationRuntimeException(ListenerMessages.listenerMethodFailure(listenerMethod, target,
                             targetException), target, null, targetException);
         }
         catch (Exception ex)
         {
-            throw new ApplicationRuntimeException(ListenerMessages
-                    .listenerMethodFailure(listenerMethod, target, ex), target,
+            throw new ApplicationRuntimeException(ListenerMessages.listenerMethodFailure(listenerMethod, target, ex), target,
                     null, ex);
 
         }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/ListenerMethodHolder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/ListenerMethodHolder.java?view=diff&rev=539966&r1=539965&r2=539966
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/ListenerMethodHolder.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/ListenerMethodHolder.java Sun May 20 15:18:41 2007
@@ -14,14 +14,14 @@
 
 package org.apache.tapestry.listener;
 
-import java.util.Map;
-
 import org.apache.tapestry.IPage;
 import org.apache.tapestry.IRequestCycle;
 import org.apache.tapestry.engine.ILink;
 import org.apache.tapestry.event.BrowserEvent;
 import org.apache.tapestry.html.BasePage;
 
+import java.util.Map;
+
 /**
  * Used by {@link org.apache.tapestry.listener.TestListenerMapSource}.
  * 
@@ -37,7 +37,9 @@
     private IPage _page;
 
     private ILink _link;
-    
+
+    int _stringArgCount;
+
     public ListenerMethodHolder()
     {
     }
@@ -55,6 +57,11 @@
     public ListenerMethodHolder(IPage page)
     {
         _page = page;
+    }
+
+    public void stringArg(String value)
+    {
+        _stringArgCount++;
     }
 
     public void wrongTypes(Map map)

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/ListenerMethodInvokerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/ListenerMethodInvokerTest.java?view=diff&rev=539966&r1=539965&r2=539966
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/ListenerMethodInvokerTest.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/ListenerMethodInvokerTest.java Sun May 20 15:18:41 2007
@@ -22,8 +22,6 @@
 
 /**
  * Tests functionality of {@link ListenerMethodInvokerImpl}.
- * 
- * @author jkuhnert
  */
 @Test(sequential=true)
 public class ListenerMethodInvokerTest extends BaseComponentTestCase
@@ -58,7 +56,7 @@
         
         ListenerMethodInvoker invoker = 
             new ListenerMethodInvokerImpl("bangbangClicked", target.getClass().getDeclaredMethods());
-        
+
         BrowserEvent event = new BrowserEvent("onClick", null);
         Object[] parms = { new Integer(12), event };
         
@@ -69,6 +67,50 @@
         invoker.invokeListenerMethod(target, cycle);
         
         verify();
+    }
+
+    public void test_Null_Parameter()
+    {
+        IRequestCycle cycle = newCycle();
+
+        ListenerMethodHolder target = new ListenerMethodHolder();
+
+        ListenerMethodInvoker invoker =
+            new ListenerMethodInvokerImpl("stringArg", target.getClass().getDeclaredMethods());
+
+        Object[] parms = { null };
+
+        expect(cycle.getListenerParameters()).andReturn(parms);
+
+        replay();
+
+        invoker.invokeListenerMethod(target, cycle);
+
+        verify();
+
+        assertEquals(target._stringArgCount, 1);
+    }
+
+    public void test_No_Parameters_With_Method_Parameters()
+    {
+        IRequestCycle cycle = newCycle();
+
+        ListenerMethodHolder target = new ListenerMethodHolder();
+
+        ListenerMethodInvoker invoker =
+            new ListenerMethodInvokerImpl("stringArg", target.getClass().getDeclaredMethods());
+
+        Object[] parms = new Object[0];
+
+        expect(cycle.getListenerParameters()).andReturn(parms);
+
+        replay();
+
+        invoker.invokeListenerMethod(target, cycle);
+
+        verify();
+
+        assertEquals(target._stringArgCount, 1);
     }
 
     public void test_To_String()

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/TestListenerMapSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/TestListenerMapSource.java?view=diff&rev=539966&r1=539965&r2=539966
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/TestListenerMapSource.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/listener/TestListenerMapSource.java Sun May 20 15:18:41 2007
@@ -14,18 +14,17 @@
 
 package org.apache.tapestry.listener;
 
-import static org.easymock.EasyMock.expect;
-
-import java.lang.reflect.Method;
-
 import org.apache.hivemind.ApplicationRuntimeException;
 import org.apache.tapestry.BaseComponentTestCase;
 import org.apache.tapestry.IPage;
 import org.apache.tapestry.IRequestCycle;
 import org.apache.tapestry.engine.ILink;
 import org.apache.tapestry.event.BrowserEvent;
+import static org.easymock.EasyMock.expect;
 import org.testng.annotations.Test;
 
+import java.lang.reflect.Method;
+
 /**
  * Tests for {@link org.apache.tapestry.listener.ListenerMapSourceImpl}&nbsp;and
  * {@link org.apache.tapestry.listener.ListenerMethodInvokerImpl}.
@@ -243,7 +242,8 @@
         verify();
     }
 
-    public void testNoMatch()
+    @Test(expectedExceptions = ApplicationRuntimeException.class)
+    public void test_No_Match()
     {
         IRequestCycle cycle = newLCycle(new Object[] { "Hello", new Integer(7) });
 
@@ -254,19 +254,8 @@
         ListenerMapSource source = new ListenerMapSourceImpl();
 
         ListenerMap map = source.getListenerMapForObject(holder);
-        
-        try
-        {
-            map.getListener("noMatch").actionTriggered(null, cycle);
-            unreachable();
-        }
-        catch (ApplicationRuntimeException ex)
-        {
-            assertEquals(
-                    "No listener method named 'noMatch' suitable for 2 listener parameters found in ListenerMethodHolder.",
-                    ex.getMessage());
-            assertSame(holder, ex.getComponent());
-        }
+
+        map.getListener("noMatchFound").actionTriggered(null, cycle);
 
         verify();
     }
@@ -295,6 +284,7 @@
                     "Failure invoking listener method 'public void "
                             + "org.apache.tapestry.listener.ListenerMethodHolder."
                             + "wrongTypes(java.util.Map)' on ListenerMethodHolder:"));
+            
             // TODO: IBM jre doesn't format these messages the same as sun's
             // jre,
             // IBM's message has no message string source for the