Author: musachy
Date: Sun Apr 26 22:58:17 2009
New Revision: 768826
URL: http://svn.apache.org/viewvc?rev=768826&view=rev
Log:
WW-3101 @Action and @Actions should be able to be applied to classes, the
method will be determined at runtime by Dynamic Action invocation mechanism
Added:
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationAction.java
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationDefaultMethodAction.java
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationsAction.java
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationsDefaultMethodAction.java
Modified:
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Action.java
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Actions.java
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
Modified:
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java?rev=768826&r1=768825&r2=768826&view=diff
==============================================================================
---
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java
(original)
+++
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java
Sun Apr 26 22:58:17 2009
@@ -40,6 +40,7 @@
import com.opensymphony.xwork2.util.finder.ClassLoaderInterfaceDelegate;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
+import com.opensymphony.xwork2.util.logging.LoggerUtils;
import org.apache.commons.lang.xwork.StringUtils;
import org.apache.commons.lang.xwork.ObjectUtils;
import org.apache.struts2.StrutsConstants;
@@ -99,6 +100,8 @@
private boolean reload;
private Set<String> fileProtocols;
+ private static final String DEFAULT_METHOD = "execute";
+
/**
* Constructs actions based on a list of packages.
*
@@ -459,6 +462,9 @@
Map<String, PackageConfig.Builder> packageConfigs = new
HashMap<String, PackageConfig.Builder>();
for (Class<?> actionClass : classes) {
+ Actions actionsAnnotation =
actionClass.getAnnotation(Actions.class);
+ Action actionAnnotation = actionClass.getAnnotation(Action.class);
+
// Skip classes that can't be instantiated
if (cannotInstantiate(actionClass)) {
if (LOG.isTraceEnabled())
@@ -485,7 +491,6 @@
List<String> namespaces = determineActionNamespace(actionClass);
for (String namespace : namespaces) {
String defaultActionName = determineActionName(actionClass);
- String defaultActionMethod = "execute";
PackageConfig.Builder defaultPackageConfig =
getPackageConfig(packageConfigs, namespace,
actionPackage, actionClass, null);
@@ -493,7 +498,10 @@
// configuration should still be built or not.
Map<String, List<Action>> map =
getActionAnnotations(actionClass);
Set<String> actionNames = new HashSet<String>();
- if (!map.containsKey(defaultActionMethod) &&
ReflectionTools.containsMethod(actionClass, defaultActionMethod)) {
+ boolean hasDefaultMethod =
ReflectionTools.containsMethod(actionClass, DEFAULT_METHOD);
+ if (!map.containsKey(DEFAULT_METHOD)
+ && hasDefaultMethod
+ && actionAnnotation == null && actionsAnnotation ==
null) {
boolean found = false;
for (String method : map.keySet()) {
List<Action> actions = map.get(method);
@@ -518,7 +526,7 @@
// Build the default
if (!found) {
- createActionConfig(defaultPackageConfig, actionClass,
defaultActionName, defaultActionMethod, null);
+ createActionConfig(defaultPackageConfig, actionClass,
defaultActionName, DEFAULT_METHOD, null);
}
}
@@ -538,10 +546,18 @@
// some actions will not have any @Action or a default method,
like the rest actions
// where the action mapper is the one that finds the right
method at runtime
- if (map.isEmpty() && mapAllMatches) {
- Action actionAnnotation =
actionClass.getAnnotation(Action.class);
+ if (map.isEmpty() && mapAllMatches && actionAnnotation == null
&& actionsAnnotation == null) {
createActionConfig(defaultPackageConfig, actionClass,
defaultActionName, null, actionAnnotation);
}
+
+ //if there are @Actions or @Action at the class level, create
the mappings for them
+ String methodName = hasDefaultMethod ? DEFAULT_METHOD : null;
+ if (actionsAnnotation != null) {
+ List<Action> actionAnnotations =
checkActionsAnnotation(actionsAnnotation);
+ for (Action actionAnnotation2 : actionAnnotations)
+ createActionConfig(defaultPackageConfig, actionClass,
defaultActionName, methodName, actionAnnotation2);
+ } else if (actionAnnotation != null)
+ createActionConfig(defaultPackageConfig, actionClass,
defaultActionName, methodName, actionAnnotation);
}
}
@@ -671,20 +687,7 @@
for (Method method : methods) {
Actions actionsAnnotation = method.getAnnotation(Actions.class);
if (actionsAnnotation != null) {
- Action[] actionArray = actionsAnnotation.value();
- boolean valuelessSeen = false;
- List<Action> actions = new ArrayList<Action>();
- for (Action ann : actionArray) {
- if (ann.value().equals(Action.DEFAULT_VALUE) &&
!valuelessSeen) {
- valuelessSeen = true;
- } else if (ann.value().equals(Action.DEFAULT_VALUE)) {
- throw new ConfigurationException("You may only add a
single Action " +
- "annotation that has no value parameter.");
- }
-
- actions.add(ann);
- }
-
+ List<Action> actions =
checkActionsAnnotation(actionsAnnotation);
map.put(method.getName(), actions);
} else {
Action ann = method.getAnnotation(Action.class);
@@ -698,6 +701,28 @@
}
/**
+ * Builds a list of actions from an @Actions annotation, and check that
they are not all empty
+ * @param actionsAnnotation Actions annotation
+ * @return a list of Actions
+ */
+ protected List<Action> checkActionsAnnotation(Actions actionsAnnotation) {
+ Action[] actionArray = actionsAnnotation.value();
+ boolean valuelessSeen = false;
+ List<Action> actions = new ArrayList<Action>();
+ for (Action ann : actionArray) {
+ if (ann.value().equals(Action.DEFAULT_VALUE) && !valuelessSeen) {
+ valuelessSeen = true;
+ } else if (ann.value().equals(Action.DEFAULT_VALUE)) {
+ throw new ConfigurationException("You may only add a single
Action " +
+ "annotation that has no value parameter.");
+ }
+
+ actions.add(ann);
+ }
+ return actions;
+ }
+
+ /**
* Creates a single ActionConfig object.
*
* @param pkgCfg The package the action configuration instance will
belong to.
Modified:
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Action.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Action.java?rev=768826&r1=768825&r2=768826&view=diff
==============================================================================
---
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Action.java
(original)
+++
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Action.java
Sun Apr 26 22:58:17 2009
@@ -52,7 +52,7 @@
* </pre>
* <!-- END SNIPPET: javadoc -->
*/
-...@target({ElementType.METHOD})
+...@target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Action {
String DEFAULT_VALUE = "DEFAULT_VALUE";
Modified:
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Actions.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Actions.java?rev=768826&r1=768825&r2=768826&view=diff
==============================================================================
---
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Actions.java
(original)
+++
struts/struts2/trunk/plugins/convention/src/main/java/org/apache/struts2/convention/annotation/Actions.java
Sun Apr 26 22:58:17 2009
@@ -33,7 +33,7 @@
* </p>
* <!-- END SNIPPET: javadoc -->
*/
-...@target(ElementType.METHOD)
+...@target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Actions {
Action[] value() default {};
Modified:
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java?rev=768826&r1=768825&r2=768826&view=diff
==============================================================================
---
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
(original)
+++
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
Sun Apr 26 22:58:17 2009
@@ -35,11 +35,7 @@
import org.apache.struts2.convention.actions.NoAnnotationAction;
import org.apache.struts2.convention.actions.Skip;
import org.apache.struts2.convention.actions.chain.ChainedAction;
-import org.apache.struts2.convention.actions.action.ActionNameAction;
-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.action.TestExtends;
+import org.apache.struts2.convention.actions.action.*;
import
org.apache.struts2.convention.actions.defaultinterceptor.SingleActionNameAction2;
import
org.apache.struts2.convention.actions.exception.ExceptionsActionLevelAction;
import
org.apache.struts2.convention.actions.exception.ExceptionsMethodLevelAction;
@@ -194,6 +190,17 @@
expect(resultMapBuilder.build(TestAction.class, null, "test",
actionPkg)).andReturn(results);
expect(resultMapBuilder.build(TestExtends.class, null, "test-extends",
actionPkg)).andReturn(results);
+ Actions classLevelActions =
ClassLevelAnnotationsAction.class.getAnnotation(Actions.class);
+ expect(resultMapBuilder.build(ClassLevelAnnotationsAction.class,
classLevelActions.value()[0], "class1", actionPkg)).andReturn(results);
+ expect(resultMapBuilder.build(ClassLevelAnnotationsAction.class,
classLevelActions.value()[1], "class2", actionPkg)).andReturn(results);
+
+ Actions classLevelActionsDefaultMethod =
ClassLevelAnnotationsDefaultMethodAction.class.getAnnotation(Actions.class);
+
expect(resultMapBuilder.build(ClassLevelAnnotationsDefaultMethodAction.class,
classLevelActionsDefaultMethod.value()[0], "class3",
actionPkg)).andReturn(results);
+
expect(resultMapBuilder.build(ClassLevelAnnotationsDefaultMethodAction.class,
classLevelActionsDefaultMethod.value()[1], "class4",
actionPkg)).andReturn(results);
+
+ expect(resultMapBuilder.build(ClassLevelAnnotationAction.class,
ClassLevelAnnotationAction.class.getAnnotation(Action.class), "class5",
actionPkg)).andReturn(results);
+
expect(resultMapBuilder.build(ClassLevelAnnotationDefaultMethodAction.class,
ClassLevelAnnotationDefaultMethodAction.class.getAnnotation(Action.class),
"class6", actionPkg)).andReturn(results);
+
/* org.apache.struts2.convention.actions.idx */
/* org.apache.struts2.convention.actions.idx.idx2 */
expect(resultMapBuilder.build(org.apache.struts2.convention.actions.idx.Index.class,
null, "index", idxPkg)).andReturn(results);
@@ -314,7 +321,7 @@
/* org.apache.struts2.convention.actions.action */
PackageConfig pkgConfig =
configuration.getPackageConfig("org.apache.struts2.convention.actions.action#struts-default#/action");
assertNotNull(pkgConfig);
- assertEquals(7, pkgConfig.getActionConfigs().size());
+ assertEquals(13, pkgConfig.getActionConfigs().size());
verifyActionConfig(pkgConfig, "action1", ActionNameAction.class,
"run1", pkgConfig.getName());
verifyActionConfig(pkgConfig, "action2", ActionNameAction.class,
"run2", pkgConfig.getName());
verifyActionConfig(pkgConfig, "actions1", ActionNamesAction.class,
"run", pkgConfig.getName());
@@ -323,6 +330,13 @@
verifyActionConfig(pkgConfig, "test", TestAction.class, "execute",
pkgConfig.getName());
verifyActionConfig(pkgConfig, "test-extends", TestExtends.class,
"execute", pkgConfig.getName());
+ verifyActionConfig(pkgConfig, "class1",
ClassLevelAnnotationsAction.class, null, pkgConfig.getName());
+ verifyActionConfig(pkgConfig, "class2",
ClassLevelAnnotationsAction.class, null, pkgConfig.getName());
+ verifyActionConfig(pkgConfig, "class3",
ClassLevelAnnotationsDefaultMethodAction.class, "execute", pkgConfig.getName());
+ verifyActionConfig(pkgConfig, "class4",
ClassLevelAnnotationsDefaultMethodAction.class, "execute", pkgConfig.getName());
+ verifyActionConfig(pkgConfig, "class5",
ClassLevelAnnotationAction.class, null, pkgConfig.getName());
+ verifyActionConfig(pkgConfig, "class6",
ClassLevelAnnotationDefaultMethodAction.class, "execute", pkgConfig.getName());
+
/* org.apache.struts2.convention.actions.namespace3 */
//action on namespace1 (action level)
pkgConfig =
configuration.getPackageConfig("org.apache.struts2.convention.actions.namespace3#struts-default#/namespaces1");
Added:
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationAction.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationAction.java?rev=768826&view=auto
==============================================================================
---
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationAction.java
(added)
+++
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationAction.java
Sun Apr 26 22:58:17 2009
@@ -0,0 +1,27 @@
+/*
+ * $Id: ActionNamesAction.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.action;
+
+import org.apache.struts2.convention.annotation.Action;
+
+...@action("class5")
+public class ClassLevelAnnotationAction {
+}
Added:
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationDefaultMethodAction.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationDefaultMethodAction.java?rev=768826&view=auto
==============================================================================
---
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationDefaultMethodAction.java
(added)
+++
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationDefaultMethodAction.java
Sun Apr 26 22:58:17 2009
@@ -0,0 +1,30 @@
+/*
+ * $Id: ActionNamesAction.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.action;
+
+import org.apache.struts2.convention.annotation.Action;
+
+...@action("class6")
+public class ClassLevelAnnotationDefaultMethodAction {
+ public String execute() {
+ return "boo";
+ }
+}
Added:
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationsAction.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationsAction.java?rev=768826&view=auto
==============================================================================
---
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationsAction.java
(added)
+++
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationsAction.java
Sun Apr 26 22:58:17 2009
@@ -0,0 +1,32 @@
+/*
+ * $Id: ActionNamesAction.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.action;
+
+import org.apache.struts2.convention.annotation.Actions;
+import org.apache.struts2.convention.annotation.Action;
+
+...@actions({
+ @Action("class1"),
+ @Action("class2")
+})
+public class ClassLevelAnnotationsAction {
+
+}
Added:
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationsDefaultMethodAction.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationsDefaultMethodAction.java?rev=768826&view=auto
==============================================================================
---
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationsDefaultMethodAction.java
(added)
+++
struts/struts2/trunk/plugins/convention/src/test/java/org/apache/struts2/convention/actions/action/ClassLevelAnnotationsDefaultMethodAction.java
Sun Apr 26 22:58:17 2009
@@ -0,0 +1,34 @@
+/*
+ * $Id: ActionNamesAction.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.action;
+
+import org.apache.struts2.convention.annotation.Actions;
+import org.apache.struts2.convention.annotation.Action;
+
+...@actions({
+ @Action("class3"),
+ @Action("class4")
+})
+public class ClassLevelAnnotationsDefaultMethodAction {
+ public String execute() {
+ return "boo";
+ }
+}