Author: musachy
Date: Tue May 13 15:18:17 2008
New Revision: 656033
URL:
http://svn.apache.org/viewvc?rev=656033&view=revLog:
[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 -->
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(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