Author: musachy
Date: Tue May 13 15:18:17 2008
New Revision: 656033

URL: http://svn.apache.org/viewvc?rev=656033&view=rev
Log:
[WW-1796] @InterceptorRef and @InterceptorRefs annotations to configure actions 
with custom interceptor-refs

(interceptor params still missing)

thanks to Aadi Deshpande for the patch

Added:
    
struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/annotation/InterceptorRef.java
    
struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/actions/interceptor/
    
struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/actions/interceptor/InterceptorsAction.java
Modified:
    
struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java
    
struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/annotation/Action.java
    
struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java

Modified: 
struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java?rev=656033&r1=656032&r2=656033&view=diff
==============================================================================
--- 
struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java
 (original)
+++ 
struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java
 Tue May 13 15:18:17 2008
@@ -27,6 +27,7 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -34,6 +35,7 @@
 import org.apache.struts2.convention.annotation.Action;
 import org.apache.struts2.convention.annotation.Actions;
 import org.apache.struts2.convention.annotation.AnnotationTools;
+import org.apache.struts2.convention.annotation.InterceptorRef;
 import org.apache.struts2.convention.annotation.Namespace;
 import org.apache.struts2.convention.annotation.ParentPackage;
 
@@ -41,8 +43,10 @@
 import com.opensymphony.xwork2.config.Configuration;
 import com.opensymphony.xwork2.config.ConfigurationException;
 import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.config.entities.InterceptorMapping;
 import com.opensymphony.xwork2.config.entities.PackageConfig;
 import com.opensymphony.xwork2.config.entities.ResultConfig;
+import com.opensymphony.xwork2.config.providers.InterceptorBuilder;
 import com.opensymphony.xwork2.inject.Inject;
 import com.opensymphony.xwork2.util.logging.Logger;
 import com.opensymphony.xwork2.util.logging.LoggerFactory;
@@ -421,12 +425,40 @@
                     actionClass.toString(), actionName, pkgCfg.getName(), 
pkgCfg.getNamespace());
         }
 
+        //build interceptors
+        List<InterceptorMapping> interceptors = buildInterceptors(pkgCfg, 
actionName, annotation);
+        actionConfig.addInterceptors(interceptors);
+
+        //build results
         Map<String, ResultConfig> results = 
resultMapBuilder.build(actionClass, annotation, actionName, pkgCfg.build());
         actionConfig.addResultConfigs(results);
 
         pkgCfg.addActionConfig(actionName, actionConfig.build());
     }
 
+    private List<InterceptorMapping> buildInterceptors(PackageConfig.Builder 
builder, String actionName, Action annotation) {
+        List<InterceptorMapping> interceptorList = new 
ArrayList<InterceptorMapping>(10);
+
+        if (annotation != null) {
+            InterceptorRef[] interceptors = annotation.interceptorRefs();
+            if (interceptors != null) {
+                for (InterceptorRef interceptor : interceptors) {
+                    if (LOG.isTraceEnabled())
+                        LOG.trace("Adding interceptor [#0] to [#1]", 
interceptor.value(), actionName);
+                    interceptorList.addAll(buildInterceptorList(builder, 
interceptor));
+                }
+            }
+        }
+
+        return interceptorList;
+    }
+
+    private List<InterceptorMapping> 
buildInterceptorList(PackageConfig.Builder builder, InterceptorRef ref) {
+        return InterceptorBuilder.constructInterceptorReference(builder, 
ref.value(), new LinkedHashMap(),
+                builder.build().getLocation(), (ObjectFactory) 
configuration.getContainer().getInstance(
+                        ObjectFactory.class));
+    }
+
     private PackageConfig.Builder getPackageConfig(final Map<String, 
PackageConfig.Builder> packageConfigs,
             String actionNamespace, final String actionPackage, final Class<?> 
actionClass,
             Action action) {

Modified: 
struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/annotation/Action.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/annotation/Action.java?rev=656033&r1=656032&r2=656033&view=diff
==============================================================================
--- 
struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/annotation/Action.java
 (original)
+++ 
struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/annotation/Action.java
 Tue May 13 15:18:17 2008
@@ -74,4 +74,10 @@
      * @return  The results for the action.
      */
     Result[] results() default {};
+
+    /**
+     * Allows action methods to specify what interceptors must be applied to 
it.
+     * @return Interceptors to be applied to the action
+     */
+    InterceptorRef[] interceptorRefs() default {};
 }
\ No newline at end of file

Added: 
struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/annotation/InterceptorRef.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/annotation/InterceptorRef.java?rev=656033&view=auto
==============================================================================
--- 
struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/annotation/InterceptorRef.java
 (added)
+++ 
struts/sandbox/trunk/struts2-convention-plugin/src/main/java/org/apache/struts2/convention/annotation/InterceptorRef.java
 Tue May 13 15:18:17 2008
@@ -0,0 +1,39 @@
+/*
+ * $Id$
+ *
+ * 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.struts2.convention.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * <!-- START SNIPPET: javadoc -->
+ * <p>
+ * This annotation allows interceptor to be applied to acctions
+ * </p>
+ * <!-- END SNIPPET: javadoc -->
+ */
[EMAIL PROTECTED](RetentionPolicy.RUNTIME)
[EMAIL PROTECTED](ElementType.TYPE)
+public @interface InterceptorRef {
+    String value();
+}

Modified: 
struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java?rev=656033&r1=656032&r2=656033&view=diff
==============================================================================
--- 
struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
 (original)
+++ 
struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
 Tue May 13 15:18:17 2008
@@ -20,8 +20,11 @@
  */
 package org.apache.struts2.convention;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import junit.framework.TestCase;
 
@@ -33,6 +36,7 @@
 import org.apache.struts2.convention.actions.action.ActionNamesAction;
 import org.apache.struts2.convention.actions.action.SingleActionNameAction;
 import org.apache.struts2.convention.actions.action.TestAction;
+import org.apache.struts2.convention.actions.interceptor.InterceptorsAction;
 import 
org.apache.struts2.convention.actions.namespace.ActionLevelNamespaceAction;
 import 
org.apache.struts2.convention.actions.namespace.ClassLevelNamespaceAction;
 import 
org.apache.struts2.convention.actions.namespace.PackageLevelNamespaceAction;
@@ -52,13 +56,24 @@
 import org.easymock.EasyMock;
 import static org.easymock.EasyMock.*;
 
+import com.opensymphony.xwork2.ActionInvocation;
 import com.opensymphony.xwork2.ObjectFactory;
 import com.opensymphony.xwork2.config.Configuration;
 import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.config.entities.InterceptorConfig;
+import com.opensymphony.xwork2.config.entities.InterceptorMapping;
+import com.opensymphony.xwork2.config.entities.InterceptorStackConfig;
 import com.opensymphony.xwork2.config.entities.PackageConfig;
 import com.opensymphony.xwork2.config.entities.ResultConfig;
 import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
 import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.Scope.Strategy;
+import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+import com.opensymphony.xwork2.ognl.OgnlReflectionProvider;
+import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
+import com.opensymphony.xwork2.validator.ValidationInterceptor;
 
 /**
  * <p>
@@ -75,9 +90,24 @@
     }
 
     private void run(String actionPackages, String packageLocators, String 
excludePackages) {
+        //setup interceptors
+        List<InterceptorConfig> defaultInterceptors = new 
ArrayList<InterceptorConfig>();
+        defaultInterceptors.add(makeInterceptorConfig("interceptor-1"));
+        defaultInterceptors.add(makeInterceptorConfig("interceptor-2"));
+        defaultInterceptors.add(makeInterceptorConfig("interceptor-3"));
+
+        //setup interceptor stacks
+        List<InterceptorStackConfig> defaultInterceptorStacks = new 
ArrayList<InterceptorStackConfig>();
+        defaultInterceptorStacks.add(makeInterceptorStackConfig("stack-1", 
"interceptor-1", "interceptor-2"));
+        defaultInterceptorStacks.add(makeInterceptorStackConfig("stack-2", 
"interceptor-3", "stack-1"));
+
+        //setup results
+        ResultTypeConfig[] defaultResults = new ResultTypeConfig[] { new 
ResultTypeConfig.Builder("dispatcher",
+                
ServletDispatcherResult.class.getName()).defaultResultParam("location").build() 
};
+
         PackageConfig strutsDefault = makePackageConfig("struts-default", 
null, null, "dispatcher",
-            new ResultTypeConfig.Builder("dispatcher", 
ServletDispatcherResult.class.getName()).
-                defaultResultParam("location").build());
+                defaultResults, defaultInterceptors, defaultInterceptorStacks);
+
         PackageConfig packageLevelParentPkg = 
makePackageConfig("package-level", null, null, null);
         PackageConfig classLevelParentPkg = makePackageConfig("class-level", 
null, null, null);
 
@@ -89,6 +119,8 @@
             "/idx", strutsDefault, null);
         PackageConfig idx2Pkg = 
makePackageConfig("org.apache.struts2.convention.actions.idx.idx2#struts-default#/idx/idx2",
             "/idx/idx2", strutsDefault, null);
+        PackageConfig interceptorRefsPkg = 
makePackageConfig("org.apache.struts2.convention.actions.interceptor#struts-default#/interceptor",
+                "/interceptor", strutsDefault, null);
         PackageConfig packageLevelPkg = 
makePackageConfig("org.apache.struts2.convention.actions.parentpackage#package-level#/parentpackage",
             "/parentpackage", packageLevelParentPkg, null);
         PackageConfig differentPkg = 
makePackageConfig("org.apache.struts2.convention.actions.parentpackage#class-level#/parentpackage",
@@ -125,6 +157,11 @@
         
expect(resultMapBuilder.build(org.apache.struts2.convention.actions.idx.Index.class,
 null, "index", idxPkg)).andReturn(results);
         
expect(resultMapBuilder.build(org.apache.struts2.convention.actions.idx.idx2.Index.class,
 null, "index", idx2Pkg)).andReturn(results);
 
+        /* org.apache.struts2.convention.actions.interceptor */
+        expect(resultMapBuilder.build(InterceptorsAction.class, 
getAnnotation(InterceptorsAction.class, "run1", Action.class), "action100", 
interceptorRefsPkg)).andReturn(results);
+        expect(resultMapBuilder.build(InterceptorsAction.class, 
getAnnotation(InterceptorsAction.class, "run2", Action.class), "action200", 
interceptorRefsPkg)).andReturn(results);
+        expect(resultMapBuilder.build(InterceptorsAction.class, 
getAnnotation(InterceptorsAction.class, "run3", Action.class), "action300", 
interceptorRefsPkg)).andReturn(results);
+
         /* org.apache.struts2.convention.actions.namespace */
         expect(resultMapBuilder.build(ActionLevelNamespaceAction.class, 
getAnnotation(ActionLevelNamespaceAction.class, "execute", Action.class), 
"action", actionLevelNamespacePkg)).andReturn(results);
         expect(resultMapBuilder.build(ClassLevelNamespaceAction.class, null, 
"class-level-namespace", classLevelNamespacePkg)).andReturn(results);
@@ -157,7 +194,15 @@
 
         EasyMock.replay(resultMapBuilder);
 
-        Configuration configuration = new DefaultConfiguration();
+        Configuration configuration = new DefaultConfiguration() {
+
+            @Override
+            public Container getContainer() {
+                return new DummyContainer();
+            }
+
+        };
+
         configuration.addPackageConfig("struts-default", strutsDefault);
         configuration.addPackageConfig("package-level", packageLevelParentPkg);
         configuration.addPackageConfig("class-level", classLevelParentPkg);
@@ -257,6 +302,15 @@
         verifyActionConfig(pkgConfig, "class-level-result-path", 
ClassLevelResultPathAction.class, "execute", pkgConfig.getName());
         verifyActionConfig(pkgConfig, "package-level-result-path", 
PackageLevelResultPathAction.class, "execute", pkgConfig.getName());
 
+        /* org.apache.struts2.convention.actions.interceptorRefs */
+        pkgConfig = 
configuration.getPackageConfig("org.apache.struts2.convention.actions.interceptor#struts-default#/interceptor");
+        assertNotNull(pkgConfig);
+        assertEquals(3, pkgConfig.getActionConfigs().size());
+        verifyActionConfigInterceptors(pkgConfig, "action100", 
"interceptor-1");
+        verifyActionConfigInterceptors(pkgConfig, "action200", 
"interceptor-1", "interceptor-2");
+        verifyActionConfigInterceptors(pkgConfig, "action300", 
"interceptor-3", "stack-1");
+
+
         /* org.apache.struts2.convention.actions */
         pkgConfig = 
configuration.getPackageConfig("org.apache.struts2.convention.actions#struts-default#");
         assertNotNull(pkgConfig);
@@ -267,6 +321,7 @@
         verifyActionConfig(pkgConfig, "skip", Skip.class, "execute", 
pkgConfig.getName());
         verifyActionConfig(pkgConfig, "idx", 
org.apache.struts2.convention.actions.idx.Index.class, "execute",
             "org.apache.struts2.convention.actions.idx#struts-default#/idx");
+
     }
 
     private void verifyActionConfig(PackageConfig pkgConfig, String 
actionName, Class<?> actionClass,
@@ -278,8 +333,24 @@
         assertEquals(packageName, ac.getPackageName());
     }
 
+    private void verifyActionConfigInterceptors(PackageConfig pkgConfig, 
String actionName, String... refs) {
+        ActionConfig ac = pkgConfig.getAllActionConfigs().get(actionName);
+        assertNotNull(ac);
+        List<InterceptorMapping> interceptorMappings = ac.getInterceptors();
+        for (int i = 0; i < interceptorMappings.size(); i++) {
+            InterceptorMapping interceptorMapping = interceptorMappings.get(i);
+            assertEquals(refs[i], interceptorMapping.getName());
+        }
+    }
+
     private PackageConfig makePackageConfig(String name, String namespace, 
PackageConfig parent,
             String defaultResultType, ResultTypeConfig... results) {
+        return makePackageConfig(name, namespace, parent, defaultResultType, 
results, null, null);
+    }
+
+    private PackageConfig makePackageConfig(String name, String namespace, 
PackageConfig parent,
+            String defaultResultType, ResultTypeConfig[] results, 
List<InterceptorConfig> interceptors,
+            List<InterceptorStackConfig> interceptorStacks) {
         PackageConfig.Builder builder = new PackageConfig.Builder(name);
         if (namespace != null) {
             builder.namespace(namespace);
@@ -290,13 +361,37 @@
         if (defaultResultType != null) {
             builder.defaultResultType(defaultResultType);
         }
-        for (ResultTypeConfig result : results) {
-            builder.addResultTypeConfig(result);
+        if (results != null) {
+            for (ResultTypeConfig result : results) {
+                builder.addResultTypeConfig(result);
+            }
+        }
+        if (interceptors != null) {
+            for (InterceptorConfig ref : interceptors) {
+                builder.addInterceptorConfig(ref);
+            }
+        }
+        if (interceptorStacks != null) {
+            for (InterceptorStackConfig ref : interceptorStacks) {
+                builder.addInterceptorStackConfig(ref);
+            }
         }
 
         return new MyPackageConfig(builder.build());
     }
 
+    private InterceptorConfig makeInterceptorConfig(String name) {
+        InterceptorConfig.Builder builder = new 
InterceptorConfig.Builder(name, 
"com.opensymphony.xwork2.validator.ValidationInterceptor");
+        return builder.build();
+    }
+
+    private InterceptorStackConfig makeInterceptorStackConfig(String name, 
String... interceptors) {
+        InterceptorStackConfig.Builder builder = new 
InterceptorStackConfig.Builder(name);
+        for (String interceptor : interceptors)
+            builder.addInterceptor(new InterceptorMapping(interceptor, new 
ValidationInterceptor()));
+        return builder.build();
+    }
+
     public class MyPackageConfig extends PackageConfig {
         protected MyPackageConfig(PackageConfig packageConfig) {
             super(packageConfig);
@@ -308,4 +403,48 @@
                 getParents().get(0) == other.getParents().get(0) && 
getParents().size() == other.getParents().size();
         }
     }
+
+    public class DummyContainer implements Container {
+
+        public <T> T getInstance(Class<T> type) {
+            try {
+                T obj = type.newInstance();
+                if (obj instanceof ObjectFactory) {
+                    ((ObjectFactory)obj).setReflectionProvider(new 
OgnlReflectionProvider() {
+
+                        @Override
+                        public void setProperties(Map properties, Object o) {
+                        }
+                    });
+                }
+                return obj;
+            } catch (Exception e) {
+               throw new RuntimeException(e);
+            }
+        }
+
+        public <T> T getInstance(Class<T> type, String name) {
+            return null;
+        }
+
+        public Set<String> getInstanceNames(Class<?> type) {
+            return null;
+        }
+
+        public void inject(Object o) {
+
+        }
+
+        public <T> T inject(Class<T> implementation) {
+            return null;
+        }
+
+        public void removeScopeStrategy() {
+
+        }
+
+        public void setScopeStrategy(Strategy scopeStrategy) {
+        }
+
+    }
 }
\ No newline at end of file

Added: 
struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/actions/interceptor/InterceptorsAction.java
URL: 
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/actions/interceptor/InterceptorsAction.java?rev=656033&view=auto
==============================================================================
--- 
struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/actions/interceptor/InterceptorsAction.java
 (added)
+++ 
struts/sandbox/trunk/struts2-convention-plugin/src/test/java/org/apache/struts2/convention/actions/interceptor/InterceptorsAction.java
 Tue May 13 15:18:17 2008
@@ -0,0 +1,46 @@
+/*
+ * $Id: ActionLevelResultAction.java 655902 2008-05-13 15:15:12Z bpontarelli $
+ *
+ * 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.struts2.convention.actions.interceptor;
+
+import org.apache.struts2.convention.annotation.Action;
+import org.apache.struts2.convention.annotation.InterceptorRef;
+
+/**
+ * <p>
+ * This is a test action with multiple interceptors.
+ * </p>
+ */
+public class InterceptorsAction {
+    @Action(value = "action100", interceptorRefs = 
@InterceptorRef("interceptor-1"))
+    public String run1() {
+        return null;
+    }
+
+    @Action(value = "action200", interceptorRefs = @InterceptorRef("stack-1"))
+    public String run2() {
+        return null;
+    }
+
+    @Action(value = "action300", interceptorRefs = @InterceptorRef("stack-2"))
+    public String run3() {
+        return null;
+    }
+}
\ No newline at end of file


Reply via email to