Author: tv
Date: Tue Aug 12 12:40:41 2014
New Revision: 1617460

URL: http://svn.apache.org/r1617460
Log:
Add Annotation @TurbineActionEvent to annotate action methods with arbitrary 
event names.

Added:
    
turbine/core/trunk/src/java/org/apache/turbine/annotation/TurbineActionEvent.java
   (with props)
Modified:
    turbine/core/trunk/src/changes/changes.xml
    turbine/core/trunk/src/java/org/apache/turbine/modules/ActionEvent.java
    turbine/core/trunk/src/test/org/apache/turbine/modules/ActionLoaderTest.java
    
turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionDoesNothing.java
    
turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionThrowsException.java
    
turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionWithServiceInjection.java

Modified: turbine/core/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/turbine/core/trunk/src/changes/changes.xml?rev=1617460&r1=1617459&r2=1617460&view=diff
==============================================================================
--- turbine/core/trunk/src/changes/changes.xml (original)
+++ turbine/core/trunk/src/changes/changes.xml Tue Aug 12 12:40:41 2014
@@ -25,6 +25,10 @@
 
   <body>
     <release version="4.0-M2" date="in Subversion">
+      <action type="add" dev="tv">
+        Add Annotation @TurbineActionEvent to annotate action methods 
+        with arbitrary event names.
+      </action>
       <action type="update" dev="tv">
         Update dependencies
         - servlet-api to 2.5 (Tomcat 6.0)

Added: 
turbine/core/trunk/src/java/org/apache/turbine/annotation/TurbineActionEvent.java
URL: 
http://svn.apache.org/viewvc/turbine/core/trunk/src/java/org/apache/turbine/annotation/TurbineActionEvent.java?rev=1617460&view=auto
==============================================================================
--- 
turbine/core/trunk/src/java/org/apache/turbine/annotation/TurbineActionEvent.java
 (added)
+++ 
turbine/core/trunk/src/java/org/apache/turbine/annotation/TurbineActionEvent.java
 Tue Aug 12 12:40:41 2014
@@ -0,0 +1,40 @@
+package org.apache.turbine.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/*
+ * 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.
+ */
+
+/**
+ * Annotation to associate methods in modules to action events
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( ElementType.METHOD )
+public @interface TurbineActionEvent
+{
+    /**
+     * Event name, no default
+     *
+     * @return the event name
+     */
+    String value();
+}

Propchange: 
turbine/core/trunk/src/java/org/apache/turbine/annotation/TurbineActionEvent.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: 
turbine/core/trunk/src/java/org/apache/turbine/modules/ActionEvent.java
URL: 
http://svn.apache.org/viewvc/turbine/core/trunk/src/java/org/apache/turbine/modules/ActionEvent.java?rev=1617460&r1=1617459&r2=1617460&view=diff
==============================================================================
--- turbine/core/trunk/src/java/org/apache/turbine/modules/ActionEvent.java 
(original)
+++ turbine/core/trunk/src/java/org/apache/turbine/modules/ActionEvent.java Tue 
Aug 12 12:40:41 2014
@@ -21,16 +21,17 @@ package org.apache.turbine.modules;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.util.Iterator;
+import java.util.Arrays;
 
 import org.apache.commons.collections.map.MultiKeyMap;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.fulcrum.parser.ParameterParser;
-import org.apache.fulcrum.parser.ParserService;
+import org.apache.fulcrum.parser.ValueParser.URLCaseFolding;
 import org.apache.turbine.Turbine;
 import org.apache.turbine.TurbineConstants;
+import org.apache.turbine.annotation.TurbineActionEvent;
 import org.apache.turbine.pipeline.PipelineData;
 import org.apache.turbine.util.RunData;
 
@@ -43,7 +44,7 @@ import org.apache.turbine.util.RunData;
  * For example, "eventSubmit_doDelete". Then any class that subclasses
  * this class will get its "doDelete(RunData data)" method executed.
  * If for any reason, it was not able to execute the method, it will
- * fall back to executing the doPeform() method which is required to
+ * fall back to executing the doPerform() method which is required to
  * be implemented.
  *
  * <p>
@@ -145,17 +146,40 @@ public abstract class ActionEvent extend
         *
         * @param name the name of the method
         * @param signature an array of classes forming the signature of the 
method
+        * @param pp ParameterParser for correct folding
         *
         * @return the method object
         * @throws NoSuchMethodException if the method does not exist
         */
-       protected Method getMethod(String name, Class<?>[] signature) throws 
NoSuchMethodException
+       protected Method getMethod(String name, Class<?>[] signature, 
ParameterParser pp) throws NoSuchMethodException
        {
            Method method = (Method) this.methodCache.get(name, signature);
 
            if (method == null)
            {
-               method = getClass().getMethod(name, signature);
+               // Try annotations of public methods
+               Method[] methods = getClass().getMethods();
+               for (Method m : methods)
+               {
+                   if (m.isAnnotationPresent(TurbineActionEvent.class))
+                   {
+                       TurbineActionEvent tae = 
m.getAnnotation(TurbineActionEvent.class);
+                       if (name.equals(pp.convert(tae.value()))
+                        && Arrays.equals(signature, m.getParameterTypes()))
+                       {
+                           method = m;
+                           break;
+                       }
+                   }
+               }
+
+               // Try legacy mode
+               if (method == null)
+               {
+                String tmp = name.toLowerCase().substring(METHOD_NAME_LENGTH);
+                   method = getClass().getMethod(METHOD_NAME_PREFIX + 
StringUtils.capitalize(tmp), signature);
+               }
+
                this.methodCache.put(name, signature, method);
            }
 
@@ -214,14 +238,14 @@ public abstract class ActionEvent extend
                String key = null;
 
                // Loop through and find the button.
-               for (Iterator<String> it = pp.keySet().iterator(); 
it.hasNext();)
+               for (String k : pp)
                {
-                       key = it.next();
+                       key = k;
                        if (key.startsWith(button))
                        {
                                if (considerKey(key, pp))
                                {
-                                       theButton = formatString(key, pp);
+                                       theButton = key;
                                        break;
                                }
                        }
@@ -229,19 +253,20 @@ public abstract class ActionEvent extend
 
                if (theButton == null)
                {
-                   theButton = DEFAULT_METHOD;
+                   theButton = BUTTON + DEFAULT_METHOD;
                    key = null;
                }
 
+               theButton = formatString(theButton, pp);
                Method method = null;
 
         try
         {
-            method = getMethod(theButton, signature);
+            method = getMethod(theButton, signature, pp);
         }
         catch (NoSuchMethodException e)
         {
-            method = getMethod(DEFAULT_METHOD, signature);
+            method = getMethod(DEFAULT_METHOD, signature, pp);
         }
         finally
         {
@@ -289,7 +314,7 @@ public abstract class ActionEvent extend
         * @param pp The parameter parser (for correct folding)
         * @return A string with the method name in the proper case.
         */
-       protected final String formatString(String input, ParameterParser pp)
+       protected String formatString(String input, ParameterParser pp)
        {
                String tmp = input;
 
@@ -298,18 +323,17 @@ public abstract class ActionEvent extend
                        tmp = input.toLowerCase();
 
                        // Chop off suffixes (for image type)
-                       input = (tmp.endsWith(".x") || tmp.endsWith(".y"))
+                       String methodName = (tmp.endsWith(".x") || 
tmp.endsWith(".y"))
                                        ? input.substring(0, input.length() - 2)
                                        : input;
 
-                       if (pp.getUrlFolding() != 
ParserService.URL_CASE_FOLDING_NONE)
+                       if (pp.getUrlFolding() == URLCaseFolding.NONE)
                        {
-                               tmp = 
input.toLowerCase().substring(BUTTON_LENGTH + METHOD_NAME_LENGTH);
-                               tmp = METHOD_NAME_PREFIX + 
StringUtils.capitalize(tmp);
+                tmp = methodName.substring(BUTTON_LENGTH);
                        }
                        else
                        {
-                               tmp = input.substring(BUTTON_LENGTH);
+                tmp = methodName.toLowerCase().substring(BUTTON_LENGTH);
                        }
                }
 

Modified: 
turbine/core/trunk/src/test/org/apache/turbine/modules/ActionLoaderTest.java
URL: 
http://svn.apache.org/viewvc/turbine/core/trunk/src/test/org/apache/turbine/modules/ActionLoaderTest.java?rev=1617460&r1=1617459&r2=1617460&view=diff
==============================================================================
--- 
turbine/core/trunk/src/test/org/apache/turbine/modules/ActionLoaderTest.java 
(original)
+++ 
turbine/core/trunk/src/test/org/apache/turbine/modules/ActionLoaderTest.java 
Tue Aug 12 12:40:41 2014
@@ -50,7 +50,7 @@ import static org.junit.Assert.*;
  * properly bubbled up when action.event.bubbleexception=true. Or, if
  * action.event.bubbleexception=false, then the exceptions should be logged and
  * sunk.
- * 
+ *
  * Changes 2014/Jun/26 (gk): removed Constructor with String parameter as no 
Test VelocityErrorScreenTest is found and JUnit does not allow it.
  *
  * @author <a href="mailto:[email protected]";>Eric Pugh</a>
@@ -67,13 +67,13 @@ public class ActionLoaderTest extends Ba
     /*
      * @see TestCase#setUp()
      */
-    
+
     @BeforeClass
     public static void init() {
         tc = new TurbineConfig(".", 
"/conf/test/CompleteTurbineResources.properties");
-        tc.initialize();     
+        tc.initialize();
     }
-    
+
     @Before
     public void setUpBefore() throws Exception
     {
@@ -245,6 +245,41 @@ public class ActionLoaderTest extends Ba
         }
     }
 
+    /**
+     * This unit test verifies that if an Action Event doEventSubmit_ is 
called,
+     * a properly annotated method is being called
+     *
+     * @throws Exception
+     *             If something goes wrong with the unit test
+     */
+    @Test
+    public void testActionEventAnnotation() throws Exception
+    {
+        // can't seem to figure out how to setup the Mock Request with the 
right
+        // parameters...
+        request.setupAddParameter("eventSubmit_annotatedEvent", "foo");
+        RunData data = getRunData(request, response, config);
+        PipelineData pipelineData = data;
+        data.setAction("VelocityActionDoesNothing");
+        data.getParameters().add("eventSubmit_annotatedEvent", "foo");
+
+        int numberOfCalls = VelocityActionDoesNothing.numberOfCalls;
+        int pipelineDataCalls = VelocityActionDoesNothing.pipelineDataCalls;
+        int actionEventCalls = VelocityActionDoesNothing.actionEventCalls;
+        try
+        {
+            ActionLoader.getInstance().exec(pipelineData, data.getAction());
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            fail("Should not have thrown an exception.");
+        }
+        assertEquals(numberOfCalls + 1, 
VelocityActionDoesNothing.numberOfCalls);
+        assertEquals(pipelineDataCalls, 
VelocityActionDoesNothing.pipelineDataCalls);
+        assertEquals(actionEventCalls + 1, 
VelocityActionDoesNothing.actionEventCalls);
+    }
+
     @Test
     public void testNonexistentActionCausesError() throws Exception
     {

Modified: 
turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionDoesNothing.java
URL: 
http://svn.apache.org/viewvc/turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionDoesNothing.java?rev=1617460&r1=1617459&r2=1617460&view=diff
==============================================================================
--- 
turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionDoesNothing.java
 (original)
+++ 
turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionDoesNothing.java
 Tue Aug 12 12:40:41 2014
@@ -22,6 +22,7 @@ package org.apache.turbine.modules.actio
 
 import static org.junit.Assert.*;
 
+import org.apache.turbine.annotation.TurbineActionEvent;
 import org.apache.turbine.pipeline.PipelineData;
 import org.apache.turbine.util.RunData;
 import org.apache.velocity.context.Context;
@@ -39,13 +40,16 @@ public class VelocityActionDoesNothing e
     public static int numberOfCalls;
     public static int runDataCalls;
     public static int pipelineDataCalls;
+    public static int actionEventCalls;
     /**
      *  Default action is throw an exception.
      *
      * @param  data           Current RunData information
      * @param  context        Context to populate
      * @exception  Exception  Thrown on error
+     * @deprecated
      */
+    @Deprecated
     @Override
     public void doPerform(RunData data, Context context) throws Exception
     {
@@ -71,4 +75,20 @@ public class VelocityActionDoesNothing e
                VelocityActionDoesNothing.pipelineDataCalls++;
     }
 
+    /**
+     *  Annotated action method.
+     *
+     * @param  data           Current RunData information
+     * @param  context        Context to populate
+     * @exception  Exception  Thrown on error
+     */
+    @TurbineActionEvent("annotatedEvent") // subject to URL folding
+    public void arbitraryMethodName(PipelineData pipelineData, Context 
context) throws Exception
+    {
+        log.debug("Calling arbitraryMethodName(PipelineData)");
+        VelocityActionDoesNothing.numberOfCalls++;
+        RunData rd = (RunData)pipelineData;
+        assertNotNull("RunData object was Null.", rd);
+        VelocityActionDoesNothing.actionEventCalls++;
+    }
 }

Modified: 
turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionThrowsException.java
URL: 
http://svn.apache.org/viewvc/turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionThrowsException.java?rev=1617460&r1=1617459&r2=1617460&view=diff
==============================================================================
--- 
turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionThrowsException.java
 (original)
+++ 
turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionThrowsException.java
 Tue Aug 12 12:40:41 2014
@@ -42,7 +42,10 @@ public class VelocityActionThrowsExcepti
      * @param  data           Current RunData information
      * @param  context        Context to populate
      * @exception  Exception  Thrown on error
+     * @deprecated
      */
+    @Override
+    @Deprecated
     public void doPerform(RunData data, Context context) throws Exception
     {
         log.debug("Calling doPerform(RunData)");
@@ -56,6 +59,7 @@ public class VelocityActionThrowsExcepti
      * @param  context        Context to populate
      * @exception  Exception  Thrown on error
      */
+    @Override
     public void doPerform(PipelineData data, Context context) throws Exception
     {
         log.debug("Calling doPerform(PipelineData)");

Modified: 
turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionWithServiceInjection.java
URL: 
http://svn.apache.org/viewvc/turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionWithServiceInjection.java?rev=1617460&r1=1617459&r2=1617460&view=diff
==============================================================================
--- 
turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionWithServiceInjection.java
 (original)
+++ 
turbine/core/trunk/src/test/org/apache/turbine/modules/actions/VelocityActionWithServiceInjection.java
 Tue Aug 12 12:40:41 2014
@@ -53,7 +53,9 @@ public class VelocityActionWithServiceIn
      * @param  data           Current RunData information
      * @param  context        Context to populate
      * @exception  Exception  Thrown on error
+     * @deprecated
      */
+    @Deprecated
     @Override
     public void doPerform(RunData data, Context context) throws Exception
     {


Reply via email to