Updating Struts to support the new immutable object scheme and the

new xwork capability to limit methods that are called.  Still more to do
here.

WW-2363 XW-595 XW-594


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@602665 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Donald J. Brown
2007-12-09 12:11:25 +00:00
parent d4be10c786
commit 7cd9c9165a
38 changed files with 252 additions and 748 deletions
@@ -277,8 +277,7 @@ public class ActionComponent extends ContextBean {
// execute at this point, after params have been set
try {
proxy = actionProxyFactory.createActionProxy(namespace, actionName, createExtraContext(), executeResult, true);
proxy.setMethod(methodName);
proxy = actionProxyFactory.createActionProxy(namespace, actionName, methodName, createExtraContext(), executeResult, true);
// set the new stack into the request for the taglib to use
req.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
proxy.execute();
@@ -1,246 +0,0 @@
/*
* $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.config;
import com.opensymphony.xwork2.config.ConfigurationProvider;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.RuntimeConfiguration;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.inject.ContainerBuilder;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.location.LocatableProperties;
import com.opensymphony.xwork2.ObjectFactory;
import java.util.*;
import java.lang.reflect.Method;
/**
* MethodConfigurationProvider creates ActionConfigs for potential action
* methods that lack a corresponding action mapping,
* so that these methods can be invoked without extra or redundant configuration.
* <p/>
* As a dynamic method, the behavior of this class could be represented as:
* <p/>
* <code>
* int bang = name.indexOf('!');
* if (bang != -1) {
* String method = name.substring(bang + 1);
* mapping.setMethod(method);
* name = name.substring(0, bang);
* }
* </code>
* <p/>
* If the action URL is "foo!bar", then the "foo" action is invoked,
* calling "bar" instead of "execute".
* <p/>
* Instead of scanning each request at runtime, the provider creates action mappings
* for each method that could be matched using a dynamic approach.
* Advantages over a dynamic approach are that:
* <p/>
* <ul>
* <ol>The "dynamic" methods are not a special case, but just another action mapping,
* with all the features of a hardcoded mapping.
* <ol>When needed, a manual action can be provided for a method and invoked with the same
* syntax as an automatic action.
* <ol>The ConfigBrowser can display all potential actions.
* </ul>
*/
public class MethodConfigurationProvider implements ConfigurationProvider {
/**
* Stores configuration property.
*/
private Configuration configuration;
/**
* Updates configuration property.
* @param configuration New configuration
*/
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
}
// See superclass for Javadoc
public void destroy() {
// Override to provide functionality
}
// See superclass for Javadoc
public void init(Configuration configuration) throws ConfigurationException {
setConfiguration(configuration);
configuration.rebuildRuntimeConfiguration();
}
// See superclass for Javadoc
public void register(ContainerBuilder containerBuilder, LocatableProperties locatableProperties) throws ConfigurationException {
// Override to provide functionality
}
// See superclass for Javadoc
public void loadPackages() throws ConfigurationException {
Set namespaces = Collections.EMPTY_SET;
RuntimeConfiguration rc = configuration.getRuntimeConfiguration();
Map allActionConfigs = rc.getActionConfigs();
if (allActionConfigs != null) {
namespaces = allActionConfigs.keySet();
}
if (namespaces.size() == 0) {
throw new ConfigurationException("MethodConfigurationProvider.loadPackages: namespaces.size == 0");
}
boolean added = false;
for (Object namespace : namespaces) {
Map<Object, Object> actions = (Map) allActionConfigs.get(namespace);
for (Map.Entry<Object, Object> actionEntry : actions.entrySet()) {
String actionName = (String) actionEntry.getKey();
ActionConfig actionConfig = (ActionConfig) actionEntry.getValue();
added = added | addDynamicMethods(actions, actionName, actionConfig);
}
}
reload = added;
}
/**
* Store needsReload property.
*/
boolean reload;
// See superclass for Javadoc
public boolean needsReload() {
return reload;
}
/**
* Stores ObjectFactory property.
*/
ObjectFactory factory;
/**
* Updates ObjectFactory property.
* @param factory
*/
@Inject
public void setObjectFactory(ObjectFactory factory) {
this.factory = factory;
}
/**
* Verifies that character at a String position is upper case.
* @param pos Position to test
* @param string Text containing position
* @return True if character at a String position is upper case
*/
private boolean upperAt(int pos, String string) {
int len = string.length();
if (len < pos) return false;
String ch = string.substring(pos, pos+1);
return ch.equals(ch.toUpperCase());
}
/**
* Scans class for potential Action mehods,
* automatically generating and registering ActionConfigs as needed.
* <p/>
* The system iterates over the set of namespaces and the set of actionNames
* in a Configuration and retrieves each ActionConfig.
* For each ActionConfig that invokes the default "execute" method,
* the provider inspects the className class for other non-void,
* no-argument methods that do not begin with "getX" or "isX".
* For each qualifying method, the provider looks for another actionName in
* the same namespace that equals action.name + "!" + method.name.
* If that actionName is not found, System copies the ActionConfig,
* changes the method property, and adds it to the package configuration
* under the new actionName (action!method).
* <p/>
* The system ignores ActionConfigs with a method property set so as to
* avoid creating alias methods for alias methods.
* The system ignores "getX" and "isX" methods since these would appear to be
* JavaBeans property and would not be intended as action methods.
* (The X represents any upper character or non-letter.)
* @param actions All ActionConfigs in namespace
* @param actionName Name of ActionConfig to analyze
* @param actionConfig ActionConfig corresponding to actionName
*/
protected boolean addDynamicMethods(Map actions, String actionName, ActionConfig actionConfig) throws ConfigurationException {
String configMethod = actionConfig.getMethodName();
boolean hasMethod = (configMethod != null) && (configMethod.length() > 0);
if (hasMethod) return false;
String className = actionConfig.getClassName();
Set actionMethods = new HashSet();
Class actionClass;
try {
actionClass = factory.getClassInstance(className);
} catch (ClassNotFoundException e) {
throw new ConfigurationException(e);
}
Method[] methods = actionClass.getMethods();
for (Method method : methods) {
String returnString = method.getReturnType().getName();
boolean isString = "java.lang.String".equals(returnString);
if (isString) {
Class[] parameterTypes = method.getParameterTypes();
boolean noParameters = (parameterTypes.length == 0);
String methodString = method.getName();
boolean notGetMethod = !((methodString.startsWith("get")) && upperAt(3, methodString));
boolean notIsMethod = !((methodString.startsWith("is")) && upperAt(2, methodString));
boolean notToString = !("toString".equals(methodString));
boolean notExecute = !("execute".equals(methodString));
boolean qualifies = noParameters && notGetMethod && notIsMethod && notToString && notExecute;
if (qualifies) {
actionMethods.add(methodString);
}
}
}
for (Object actionMethod : actionMethods) {
String methodName = (String) actionMethod;
StringBuilder sb = new StringBuilder();
sb.append(actionName);
sb.append("!"); // TODO: Make "!" a configurable character
sb.append(methodName);
String newActionName = sb.toString();
boolean haveAction = actions.containsKey(newActionName);
if (haveAction) continue;
ActionConfig newActionConfig = new ActionConfig(
newActionName,
actionConfig.getClassName(),
actionConfig.getParams(),
actionConfig.getResults(),
actionConfig.getInterceptors(),
actionConfig.getExceptionMappings());
newActionConfig.setMethodName(methodName);
String packageName = actionConfig.getPackageName();
newActionConfig.setPackageName(packageName);
PackageConfig packageConfig = configuration.getPackageConfig(packageName);
packageConfig.addActionConfig(newActionName, actionConfig);
}
return (actionMethods.size() > 0);
}
}
@@ -59,7 +59,6 @@ import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
*
*
* @see FilterDispatcher
* @see AbstractFilter
* @see Dispatcher
*
* @version $Date$ $Id$
@@ -464,8 +464,8 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
Configuration config = configurationManager.getConfiguration();
ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
namespace, name, extraContext, true, false);
proxy.setMethod(method);
namespace, name, method, extraContext, true, false);
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
// if the ActionMapping says to go straight to a result, do it!
@@ -484,7 +484,7 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
LOG.error("Could not find action or result", e);
sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
} catch (Exception e) {
throw new ServletException(e);
sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
} finally {
UtilTimerStack.pop(timerKey);
}
@@ -32,9 +32,9 @@ public class StrutsActionProxy extends DefaultActionProxy {
private static final long serialVersionUID = -2434901249671934080L;
public StrutsActionProxy(ActionInvocation inv, String namespace, String actionName, Map extraContext,
boolean executeResult, boolean cleanupContext) throws Exception {
super(inv, namespace, actionName, extraContext, executeResult, cleanupContext);
public StrutsActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName,
boolean executeResult, boolean cleanupContext) {
super(inv, namespace, actionName, methodName, executeResult, cleanupContext);
}
public String execute() throws Exception {
@@ -54,4 +54,10 @@ public class StrutsActionProxy extends DefaultActionProxy {
ActionContext.setContext(previous);
}
}
@Override
protected void prepare() {
super.prepare();
}
}
@@ -30,9 +30,10 @@ import com.opensymphony.xwork2.DefaultActionProxyFactory;
public class StrutsActionProxyFactory extends DefaultActionProxyFactory {
public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, Map extraContext, boolean executeResult, boolean cleanupContext) throws Exception {
@Override
public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) {
ActionProxy proxy = new StrutsActionProxy(inv, namespace, actionName, extraContext, executeResult, cleanupContext);
StrutsActionProxy proxy = new StrutsActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
container.inject(proxy);
proxy.prepare();
return proxy;
@@ -242,8 +242,9 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor {
"provide an action-specific or global result named '" + WAIT +
"'! This requires FreeMarker support and won't work if you don't have it installed");
// no wait result? hmm -- let's try to do dynamically put it in for you!
ResultConfig rc = new ResultConfig(WAIT, "org.apache.struts2.views.freemarker.FreemarkerResult",
Collections.singletonMap("location", "/org/apache/struts2/interceptor/wait.ftl"));
ResultConfig rc = new ResultConfig.Builder(WAIT, "org.apache.struts2.views.freemarker.FreemarkerResult")
.addParams(Collections.singletonMap("location", "/org/apache/struts2/interceptor/wait.ftl"))
.build();
results.put(WAIT, rc);
}
@@ -100,7 +100,7 @@ public class DWRValidator {
try {
Configuration cfg = du.getConfigurationManager().getConfiguration();
ActionInvocation inv = new ValidatorActionInvocation(ctx, true);
ActionProxy proxy = actionProxyFactory.createActionProxy(inv, namespace, action, ctx, true, true);
ActionProxy proxy = actionProxyFactory.createActionProxy(inv, namespace, action, null, true, true);
proxy.execute();
Object a = proxy.getAction();
@@ -36,12 +36,7 @@
<#if parameters.id?exists>
id="${parameters.id?html}"<#rt/>
</#if>
<#if parameters.cssClass?exists>
class="${parameters.cssClass?html}"<#rt/>
</#if>
<#if parameters.cssStyle?exists>
style="${parameters.cssStyle?html}"<#rt/>
</#if>
<#include "/${parameters.templateDir}/simple/css.ftl" />
<#if parameters.title?exists>
title="${parameters.title?html}"<#rt/>
</#if>
@@ -40,12 +40,7 @@
<#if parameters.id?exists>
id="${parameters.id?html}"<#rt/>
</#if>
<#if parameters.cssClass?exists>
class="${parameters.cssClass?html}"<#rt/>
</#if>
<#if parameters.cssStyle?exists>
style="${parameters.cssStyle?html}"<#rt/>
</#if>
<#include "/${parameters.templateDir}/simple/css.ftl" />
<#if parameters.title?exists>
title="${parameters.title?html}"<#rt/>
</#if>
@@ -43,12 +43,7 @@
<#if parameters.id?exists>
id="${parameters.id?html}"<#rt/>
</#if>
<#if parameters.cssClass?exists>
class="${parameters.cssClass?html}"<#rt/>
</#if>
<#if parameters.cssStyle?exists>
style="${parameters.cssStyle?html}"<#rt/>
</#if>
<#include "/${parameters.templateDir}/simple/css.ftl" />
<#if parameters.title?exists>
title="${parameters.title?html}"<#rt/>
</#if>
@@ -35,12 +35,7 @@
<#if parameters.id?exists>
id="${parameters.id?html}"<#rt/>
</#if>
<#if parameters.cssClass?exists>
class="${parameters.cssClass?html}"<#rt/>
</#if>
<#if parameters.cssStyle?exists>
style="${parameters.cssStyle?html}"<#rt/>
</#if>
<#include "/${parameters.templateDir}/simple/css.ftl" />
<#if parameters.title?exists>
title="${parameters.title?html}"<#rt/>
</#if>
@@ -43,12 +43,7 @@
<#if parameters.id?exists>
id="${parameters.id?html}"<#rt/>
</#if>
<#if parameters.cssClass?exists>
class="${parameters.cssClass?html}"<#rt/>
</#if>
<#if parameters.cssStyle?exists>
style="${parameters.cssStyle?html}"<#rt/>
</#if>
<#include "/${parameters.templateDir}/simple/css.ftl" />
<#if parameters.title?exists>
title="${parameters.title?html}"<#rt/>
</#if>
@@ -39,12 +39,7 @@
<#if parameters.id?exists>
id="${parameters.id?html}"<#rt/>
</#if>
<#if parameters.cssClass?exists>
class="${parameters.cssClass?html}"<#rt/>
</#if>
<#if parameters.cssStyle?exists>
style="${parameters.cssStyle?html}"<#rt/>
</#if>
<#include "/${parameters.templateDir}/simple/css.ftl" />
<#if parameters.title?exists>
title="${parameters.title?html}"<#rt/>
</#if>
@@ -77,80 +77,58 @@ public class TestConfigurationProvider implements ConfigurationProvider {
* Initializes the configuration object.
*/
public void loadPackages() {
PackageConfig defaultPackageConfig = new PackageConfig("");
HashMap results = new HashMap();
HashMap successParams = new HashMap();
successParams.put("propertyName", "executionCount");
successParams.put("expectedValue", "1");
ResultConfig successConfig = new ResultConfig(Action.SUCCESS, TestResult.class.getName(), successParams);
ActionConfig executionCountActionConfig = new ActionConfig.Builder("", "", ExecutionCountTestAction.class.getName())
.addResultConfig(new ResultConfig.Builder(Action.SUCCESS, TestResult.class.getName())
.addParams(successParams)
.build())
.build();
results.put(Action.SUCCESS, successConfig);
List interceptors = new ArrayList();
ActionConfig testActionConfig = new ActionConfig.Builder("", "", TestAction.class.getName())
.addResultConfig(new ResultConfig.Builder(Action.SUCCESS, ServletDispatcherResult.class.getName())
.addParam("location", "success.jsp")
.build())
.addInterceptor(new InterceptorMapping("params", new ParametersInterceptor()))
.build();
ActionConfig executionCountActionConfig = new ActionConfig(null, ExecutionCountTestAction.class, null, results, interceptors);
defaultPackageConfig.addActionConfig(EXECUTION_COUNT_ACTION_NAME, executionCountActionConfig);
results = new HashMap();
ActionConfig tokenActionConfig = new ActionConfig.Builder("", "", TestAction.class.getName())
.addInterceptor(new InterceptorMapping("token", new TokenInterceptor()))
.addResultConfig(new ResultConfig.Builder("invalid.token", MockResult.class.getName()).build())
.addResultConfig(new ResultConfig.Builder("success", MockResult.class.getName()).build())
.build();
successParams = new HashMap();
successParams.put("location", "success.jsp");
successConfig = new ResultConfig(Action.SUCCESS, ServletDispatcherResult.class.getName(), successParams);
results.put(Action.SUCCESS, successConfig);
interceptors.add(new InterceptorMapping("params", new ParametersInterceptor()));
ActionConfig testActionConfig = new ActionConfig(null, TestAction.class, null, results, interceptors);
defaultPackageConfig.addActionConfig(TEST_ACTION_NAME, testActionConfig);
interceptors = new ArrayList();
interceptors.add(new InterceptorMapping("token", new TokenInterceptor()));
results = new HashMap();
ActionConfig tokenActionConfig = new ActionConfig(null, TestAction.class, null, results, interceptors);
tokenActionConfig.addResultConfig(new ResultConfig("invalid.token", MockResult.class.getName()));
tokenActionConfig.addResultConfig(new ResultConfig("success", MockResult.class.getName()));
defaultPackageConfig.addActionConfig(TOKEN_ACTION_NAME, tokenActionConfig);
interceptors = new ArrayList();
interceptors.add(new InterceptorMapping("token-session", new TokenSessionStoreInterceptor()));
results = new HashMap();
successParams = new HashMap();
successParams.put("actionName", EXECUTION_COUNT_ACTION_NAME);
successConfig = new ResultConfig(Action.SUCCESS, ActionChainResult.class.getName(), successParams);
results.put(Action.SUCCESS, successConfig);
// empty results for token session unit test
results = new HashMap();
ActionConfig tokenSessionActionConfig = new ActionConfig(null, TestAction.class, null, results, interceptors);
tokenSessionActionConfig.addResultConfig(new ResultConfig("invalid.token", MockResult.class.getName()));
tokenSessionActionConfig.addResultConfig(new ResultConfig("success", MockResult.class.getName()));
defaultPackageConfig.addActionConfig(TOKEN_SESSION_ACTION_NAME, tokenSessionActionConfig);
ActionConfig tokenSessionActionConfig = new ActionConfig.Builder("", "", TestAction.class.getName())
.addResultConfig(new ResultConfig.Builder("invalid.token", MockResult.class.getName()).build())
.addResultConfig(new ResultConfig.Builder("success", MockResult.class.getName()).build())
.addInterceptor(new InterceptorMapping("token-session", new TokenSessionStoreInterceptor()))
.build();
PackageConfig defaultPackageConfig = new PackageConfig.Builder("")
.addActionConfig(EXECUTION_COUNT_ACTION_NAME, executionCountActionConfig)
.addActionConfig(TEST_ACTION_NAME, testActionConfig)
.addActionConfig(TOKEN_ACTION_NAME, tokenActionConfig)
.addActionConfig(TOKEN_SESSION_ACTION_NAME, tokenSessionActionConfig)
.addActionConfig("testActionTagAction", new ActionConfig.Builder("", "", TestAction.class.getName())
.addResultConfig(new ResultConfig.Builder(Action.SUCCESS, TestActionTagResult.class.getName()).build())
.addResultConfig(new ResultConfig.Builder(Action.INPUT, TestActionTagResult.class.getName()).build())
.build())
.build();
configuration.addPackageConfig("", defaultPackageConfig);
Map testActionTagResults = new HashMap();
testActionTagResults.put(Action.SUCCESS, new ResultConfig(Action.SUCCESS, TestActionTagResult.class.getName(), new HashMap()));
testActionTagResults.put(Action.INPUT, new ResultConfig(Action.INPUT, TestActionTagResult.class.getName(), new HashMap()));
ActionConfig testActionTagActionConfig = new ActionConfig((String) null, TestAction.class, (Map) null, testActionTagResults, new ArrayList());
defaultPackageConfig.addActionConfig("testActionTagAction", testActionTagActionConfig);
PackageConfig namespacePackageConfig = new PackageConfig("namespacePackage");
namespacePackageConfig.setNamespace(TEST_NAMESPACE);
namespacePackageConfig.addParent(defaultPackageConfig);
ActionConfig namespaceAction = new ActionConfig(null, TestAction.class, null, null, null);
namespacePackageConfig.addActionConfig(TEST_NAMESPACE_ACTION, namespaceAction);
PackageConfig namespacePackageConfig = new PackageConfig.Builder("namespacePackage")
.namespace(TEST_NAMESPACE)
.addParent(defaultPackageConfig)
.addActionConfig(TEST_NAMESPACE_ACTION, new ActionConfig.Builder("", "", TestAction.class.getName()).build())
.build();
configuration.addPackageConfig("namespacePackage", namespacePackageConfig);
}
@@ -1,250 +0,0 @@
/*
* $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.config;
import org.apache.struts2.dispatcher.ServletDispatcherResult;
import org.apache.struts2.dispatcher.Dispatcher;
import org.springframework.mock.web.MockServletContext;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.config.entities.*;
import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ObjectFactory;
import junit.framework.TestCase;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
/**
* MethodConfigurationProviderTest exercises the MethodConfigurationProvider
* to confirm that only the expected methods are generated.
*/
public class MethodConfigurationProviderTest extends TestCase {
/**
* Object under test.
*/
MethodConfigurationProvider provider;
/**
* Set of packages and ActionConfigs to exercise.
*/
Configuration configuration;
/**
* Mock dispatcher.
*/
Dispatcher dispatcher;
/**
* Creates a mock Dispatcher and seeds Configuration.
*/
public void setUp() {
/*
InternalConfigurationManager configurationManager = new InternalConfigurationManager();
dispatcher = new Dispatcher(new MockServletContext(), new HashMap<String, String>());
dispatcher.setConfigurationManager(configurationManager);
dispatcher.init();
Dispatcher.setInstance(dispatcher);
configuration = new DefaultConfiguration();
// empty package for the "default" namespace of empty String
PackageConfig strutsDefault = new PackageConfig("struts-default");
strutsDefault.addResultTypeConfig(new ResultTypeConfig("dispatcher", ServletDispatcherResult.class.getName(), "location"));
strutsDefault.setDefaultResultType("dispatcher");
configuration.addPackageConfig("struts-default", strutsDefault);
// custom package with various actions
PackageConfig customPackage = new PackageConfig("trick-package");
customPackage.setNamespace("/trick");
// action that specifies ActionSupport (not empty) but with no methods
ActionConfig action = new ActionConfig(null, ActionSupport.class, null, null, null);
customPackage.addActionConfig("action",action);
// action that species a custom Action with a manual method
ActionConfig custom = new ActionConfig(null, Custom.class, null, null, null);
customPackage.addActionConfig("custom",custom);
// action for manual method, with params, to prove it is not overwritten
Map params = new HashMap();
params.put("name","value");
ActionConfig manual = new ActionConfig("manual", Custom.class, params, null, null);
customPackage.addActionConfig("custom!manual",manual);
configuration.addPackageConfig("trick-package", customPackage);
provider = new MethodConfigurationProvider();
provider.init(configuration);
provider.setObjectFactory(new ObjectFactory());
provider.loadPackages();
*/
}
public void testNothing() {
// now stop complaining!
}
/**
* Provides the "custom-package" configuration.
* @return the "custom-package" configuration.
*/
private PackageConfig getCustom() {
return configuration.getPackageConfig("trick-package");
}
/**
* Confirms baseline setup works as expected.
*/
/*
public void testSetup() {
assertEquals(2, configuration.getPackageConfigs().size());
PackageConfig struts = configuration.getPackageConfig("struts-default");
assertNotNull(struts);
assertTrue("testSetup: Expected struts-default to be empty!", struts.getActionConfigs().size() == 0);
PackageConfig custom = getCustom();
assertNotNull(custom);
assertTrue("testSetup: Expected ActionConfigs to be added!", custom.getActionConfigs().size() > 0);
}*/
/**
* Confirms that system detects no-argument methods that return Strings
* and generates the appropriate ActionConfigs.
*/
/*
public void testQualifyingMethods() {
PackageConfig config = getCustom();
boolean action = config.getActionConfigs().containsKey("action");
assertTrue("The root action is missing!",action);
boolean custom = config.getActionConfigs().containsKey("custom");
assertTrue("The custom action is missing!",custom);
boolean action_input = getCustom().getActionConfigs().containsKey("action!input");
assertTrue("The Action.input method should have an action mapping!",action_input);
boolean custom_input = getCustom().getActionConfigs().containsKey("custom!input");
assertTrue("The Custom.input method should have an action mapping!",custom_input);
boolean custom_auto = getCustom().getActionConfigs().containsKey("custom!auto");
assertTrue("The Custom.auto method should have an action mapping!",custom_auto);
boolean custom_gettysburg = getCustom().getActionConfigs().containsKey("custom!gettysburg");
assertTrue("The Custom.gettysburg method should have an action mapping!",custom_gettysburg);
}*/
/**
* Confirms system excludes methods that do not return Strings
* and no-argument or begin with "getx" or "isX".
*/
/*public void testExcludedMethods() {
PackageConfig custom = getCustom();
boolean action_toString = custom.getActionConfigs().containsKey("action!toString");
assertFalse("The toString has an ActionConfig!",action_toString);
boolean action_execute = custom.getActionConfigs().containsKey("action!execute");
assertFalse("The execute has an ActionConfig!",action_execute);
boolean action_get_method = custom.getActionConfigs().containsKey("action!getLocale");
assertFalse("A 'getX' method has an ActionConfig!",action_get_method);
boolean action_is_method = custom.getActionConfigs().containsKey("custom!isIt");
assertFalse("A 'isX' method has an ActionConfig!",action_is_method);
boolean void_method = custom.getActionConfigs().containsKey("action!validate");
assertFalse("A void method has an ActionConfig!",void_method);
boolean void_with_parameters = custom.getActionConfigs().containsKey("action!addActionMessage");
assertFalse("A void method with parameters has an ActionConfig!",void_with_parameters);
boolean return_method = custom.getActionConfigs().containsKey("action!hasActionErrors");
assertFalse("A method with a return type other than String has an ActionConfig!",return_method);
ActionConfig manual = getCustom().getActionConfigs().get("custom!manual");
Object val = manual.getParams().get("name");
assertTrue("The custom.Manual method was generated!","value".equals(val.toString()));
}*/
// /**
// * Custom is a test Action class.
// */
// public class Custom extends ActionSupport {
//
// /**
// * Tests ordinary methods.
// * @return SUCCESS
// */
// public String custom() {
// return SUCCESS;
// }
//
// /**
// * Tests JavaBean property.
// * @return SUCCESS
// */
// public boolean isIt() {
// return true;
// }
//
// /**
// * Tests manual override.
// * @return SUCCESS
// */
// public String manual() {
// return SUCCESS;
// }
//
// /**
// * Tests dynamic configuration.
// * @return SUCCESS
// */
// public String auto() {
// return SUCCESS;
// }
//
// /**
// * Tests method that looks like a JavaBean property.
// * @return SUCCESS
// */
// public String gettysburg() {
// return SUCCESS;
// }
// }
//
// /**
// * InternalConfigurationManager is a mock ConfigurationManager.
// */
// class InternalConfigurationManager extends ConfigurationManager {
// public boolean destroyConfiguration = false;
//
// @Override
// public synchronized void destroyConfiguration() {
// super.destroyConfiguration();
// destroyConfiguration = true;
// }
// }
}
@@ -46,17 +46,18 @@ public class ServletActionRedirectResultTest extends StrutsTestCase {
public void testIncludeParameterInResultWithConditionParseOn() throws Exception {
ResultConfig resultConfig = new ResultConfig();
resultConfig.addParam("actionName", "someActionName");
resultConfig.addParam("namespace", "someNamespace");
resultConfig.addParam("encode", "true");
resultConfig.addParam("parse", "true");
resultConfig.addParam("location", "someLocation");
resultConfig.addParam("prependServletContext", "true");
resultConfig.addParam("method", "someMethod");
resultConfig.addParam("param1", "${#value1}");
resultConfig.addParam("param2", "${#value2}");
resultConfig.addParam("param3", "${#value3}");
ResultConfig resultConfig = new ResultConfig.Builder("", "")
.addParam("actionName", "someActionName")
.addParam("namespace", "someNamespace")
.addParam("encode", "true")
.addParam("parse", "true")
.addParam("location", "someLocation")
.addParam("prependServletContext", "true")
.addParam("method", "someMethod")
.addParam("param1", "${#value1}")
.addParam("param2", "${#value2}")
.addParam("param3", "${#value3}")
.build();
@@ -74,8 +75,8 @@ public class ServletActionRedirectResultTest extends StrutsTestCase {
Map<String, ResultConfig> results= new HashMap<String, ResultConfig>();
results.put("myResult", resultConfig);
ActionConfig actionConfig = new ActionConfig();
actionConfig.setResults(results);
ActionConfig actionConfig = new ActionConfig.Builder("", "", "")
.addResultConfigs(results).build();
ServletActionRedirectResult result = new ServletActionRedirectResult();
result.setActionName("myAction");
@@ -109,17 +110,18 @@ public class ServletActionRedirectResultTest extends StrutsTestCase {
public void testIncludeParameterInResult() throws Exception {
ResultConfig resultConfig = new ResultConfig();
resultConfig.addParam("actionName", "someActionName");
resultConfig.addParam("namespace", "someNamespace");
resultConfig.addParam("encode", "true");
resultConfig.addParam("parse", "true");
resultConfig.addParam("location", "someLocation");
resultConfig.addParam("prependServletContext", "true");
resultConfig.addParam("method", "someMethod");
resultConfig.addParam("param1", "value 1");
resultConfig.addParam("param2", "value 2");
resultConfig.addParam("param3", "value 3");
ResultConfig resultConfig = new ResultConfig.Builder("", "")
.addParam("actionName", "someActionName")
.addParam("namespace", "someNamespace")
.addParam("encode", "true")
.addParam("parse", "true")
.addParam("location", "someLocation")
.addParam("prependServletContext", "true")
.addParam("method", "someMethod")
.addParam("param1", "value 1")
.addParam("param2", "value 2")
.addParam("param3", "value 3")
.build();
ActionContext context = ActionContext.getContext();
MockHttpServletRequest req = new MockHttpServletRequest();
@@ -131,8 +133,8 @@ public class ServletActionRedirectResultTest extends StrutsTestCase {
Map<String, ResultConfig> results= new HashMap<String, ResultConfig>();
results.put("myResult", resultConfig);
ActionConfig actionConfig = new ActionConfig();
actionConfig.setResults(results);
ActionConfig actionConfig = new ActionConfig.Builder("", "", "")
.addResultConfigs(results).build();
ServletActionRedirectResult result = new ServletActionRedirectResult();
result.setActionName("myAction");
@@ -140,8 +140,7 @@ public class ServletRedirectResultTest extends StrutsTestCase implements StrutsS
protected void setUp() throws Exception {
super.setUp();
configurationManager.getConfiguration().
addPackageConfig("foo", new PackageConfig("foo", "/namespace", false, null));
addPackageConfig("foo", new PackageConfig.Builder("foo").namespace("/namespace").build());
view = new ServletRedirectResult();
container.inject(view);
@@ -62,8 +62,9 @@ public class DefaultActionMapperTest extends StrutsTestCase {
req.setupGetContextPath("/my/namespace");
config = new DefaultConfiguration();
PackageConfig pkg = new PackageConfig("myns", "/my/namespace", false, null);
PackageConfig pkg2 = new PackageConfig("my", "/my", false, null);
PackageConfig pkg = new PackageConfig.Builder("myns")
.namespace("/my/namespace").build();
PackageConfig pkg2 = new PackageConfig.Builder("my").namespace("/my").build();
config.addPackageConfig("mvns", pkg);
config.addPackageConfig("my", pkg2);
configManager = new ConfigurationManager() {
@@ -47,8 +47,10 @@ public class Restful2ActionMapperTest extends StrutsTestCase {
req.setupGetContextPath("/my/namespace");
config = new DefaultConfiguration();
PackageConfig pkg = new PackageConfig("myns", "/my/namespace", false, null);
PackageConfig pkg2 = new PackageConfig("my", "/my", false, null);
PackageConfig pkg = new PackageConfig.Builder("myns")
.namespace("/my/namespace").build();
PackageConfig pkg2 = new PackageConfig.Builder("my")
.namespace("/my").build();
config.addPackageConfig("mvns", pkg);
config.addPackageConfig("my", pkg2);
configManager = new ConfigurationManager() {
@@ -170,7 +170,7 @@ public class ExecuteAndWaitInterceptorTest extends StrutsTestCase {
}
protected ActionProxy buildProxy(String actionName) throws Exception {
return actionProxyFactory.createActionProxy("", actionName, context);
return actionProxyFactory.createActionProxy("", actionName, null, context);
}
protected void setUp() throws Exception {
@@ -211,21 +211,19 @@ public class ExecuteAndWaitInterceptorTest extends StrutsTestCase {
}
public void loadPackages() throws ConfigurationException {
PackageConfig wait = new PackageConfig("");
Map results = new HashMap();
results.put(Action.SUCCESS, new ResultConfig(Action.SUCCESS, MockResult.class.getName(), null));
results.put(ExecuteAndWaitInterceptor.WAIT, new ResultConfig(ExecuteAndWaitInterceptor.WAIT, MockResult.class.getName(), null));
// interceptors
waitInterceptor = new ExecuteAndWaitInterceptor();
List interceptors = new ArrayList();
interceptors.add(new InterceptorMapping("params", new ParametersInterceptor()));
interceptors.add(new InterceptorMapping("execAndWait", waitInterceptor));
ActionConfig ac = new ActionConfig(null, ExecuteAndWaitDelayAction.class, null, results, interceptors);
wait.addActionConfig("action1", ac);
PackageConfig wait = new PackageConfig.Builder("")
.addActionConfig("action1", new ActionConfig.Builder("", "action1", ExecuteAndWaitDelayAction.class.getName())
.addResultConfig(new ResultConfig.Builder(Action.SUCCESS, MockResult.class.getName()).build())
.addResultConfig(new ResultConfig.Builder(ExecuteAndWaitInterceptor.WAIT, MockResult.class.getName()).build())
.addInterceptor(new InterceptorMapping("params", new ParametersInterceptor()))
.addInterceptor(new InterceptorMapping("execAndWait", waitInterceptor))
.build())
.build();
configuration.addPackageConfig("", wait);
}
@@ -156,16 +156,14 @@ public class FormTagTest extends AbstractUITagTest {
public RuntimeConfiguration getRuntimeConfiguration() {
return new RuntimeConfiguration() {
public ActionConfig getActionConfig(String namespace, String name) {
ActionConfig actionConfig = new ActionConfig() {
ActionConfig actionConfig = new ActionConfig("", name, "") {
public List getInterceptors() {
List interceptors = new ArrayList();
ValidationInterceptor validationInterceptor = new ValidationInterceptor();
validationInterceptor.setIncludeMethods("*");
InterceptorMapping interceptorMapping = new InterceptorMapping();
interceptorMapping.setName("validation");
interceptorMapping.setInterceptor(validationInterceptor);
InterceptorMapping interceptorMapping = new InterceptorMapping("validation", validationInterceptor);
interceptors.add(interceptorMapping);
return interceptors;
@@ -249,16 +247,14 @@ public class FormTagTest extends AbstractUITagTest {
public RuntimeConfiguration getRuntimeConfiguration() {
return new RuntimeConfiguration() {
public ActionConfig getActionConfig(String namespace, String name) {
ActionConfig actionConfig = new ActionConfig() {
ActionConfig actionConfig = new ActionConfig("", name, "") {
public List getInterceptors() {
List interceptors = new ArrayList();
ValidationInterceptor validationInterceptor = new ValidationInterceptor();
validationInterceptor.setExcludeMethods("*");
InterceptorMapping interceptorMapping = new InterceptorMapping();
interceptorMapping.setName("validation");
interceptorMapping.setInterceptor(validationInterceptor);
InterceptorMapping interceptorMapping = new InterceptorMapping("validation", validationInterceptor);
interceptors.add(interceptorMapping);
return interceptors;
@@ -120,19 +120,15 @@ public class CodebehindUnknownHandler implements UnknownHandler {
}
protected ActionConfig buildActionConfig(String path, String namespace, String actionName, ResultTypeConfig resultTypeConfig) {
Map<String,ResultConfig> results = new HashMap<String,ResultConfig>();
HashMap params = new HashMap();
if (resultTypeConfig.getParams() != null) {
params.putAll(resultTypeConfig.getParams());
}
params.put(resultTypeConfig.getDefaultResultParam(), path);
PackageConfig pkg = configuration.getPackageConfig(defaultPackageName);
List interceptors = InterceptorBuilder.constructInterceptorReference(pkg, pkg.getFullDefaultInterceptorRef(),
Collections.EMPTY_MAP, null, objectFactory);
ResultConfig config = new ResultConfig(Action.SUCCESS, resultTypeConfig.getClazz(), params);
results.put(Action.SUCCESS, config);
return new ActionConfig("execute", ActionSupport.class.getName(), defaultPackageName, new HashMap(), results, interceptors);
return new ActionConfig.Builder(defaultPackageName, "execute", ActionSupport.class.getName())
.addInterceptors(InterceptorBuilder.constructInterceptorReference(pkg, pkg.getFullDefaultInterceptorRef(),
Collections.EMPTY_MAP, null, objectFactory))
.addResultConfig(new ResultConfig.Builder(Action.SUCCESS, resultTypeConfig.getClassName())
.addParams(resultTypeConfig.getParams())
.addParam(resultTypeConfig.getDefaultResultParam(), path)
.build())
.build();
}
public Result handleUnknownResult(ActionContext actionContext, String actionName,
@@ -172,15 +168,10 @@ public class CodebehindUnknownHandler implements UnknownHandler {
}
protected Result buildResult(String path, String resultCode, ResultTypeConfig config, ActionContext invocationContext) {
String resultClass = config.getClazz();
Map<String,String> params = new LinkedHashMap<String,String>();
if (config.getParams() != null) {
params.putAll(config.getParams());
}
params.put(config.getDefaultResultParam(), path);
ResultConfig resultConfig = new ResultConfig(resultCode, resultClass, params);
ResultConfig resultConfig = new ResultConfig.Builder(resultCode, config.getClassName())
.addParams(config.getParams())
.addParam(config.getDefaultResultParam(), path)
.build();
try {
return objectFactory.buildResult(resultConfig, invocationContext.getContextMap());
} catch (Exception e) {
@@ -24,9 +24,7 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.*;
import javax.servlet.ServletContext;
@@ -123,12 +121,7 @@ public class ClasspathPackageProvider implements PackageProvider {
*/
private boolean initialized = false;
/**
* The package configurations for scanned Actions.
*
* @see #loadPackageConfig
*/
private Map<String,PackageConfig> loadedPackageConfigs = new HashMap<String,PackageConfig>();
private PackageLoader packageLoader;
/**
* Logging instance for this class.
@@ -235,6 +228,7 @@ public class ClasspathPackageProvider implements PackageProvider {
*/
protected void loadPackages(String[] pkgs) {
packageLoader = new PackageLoader();
ResolverUtil<Class> resolver = new ResolverUtil<Class>();
resolver.find(createActionClassTest(), pkgs);
@@ -246,8 +240,8 @@ public class ClasspathPackageProvider implements PackageProvider {
}
}
for (String key : loadedPackageConfigs.keySet()) {
configuration.addPackageConfig(key, loadedPackageConfigs.get(key));
for (PackageConfig config : packageLoader.createPackageConfigs()) {
configuration.addPackageConfig(config.getName(), config);
}
}
@@ -279,7 +273,6 @@ public class ClasspathPackageProvider implements PackageProvider {
* @param pkgs List of packages that were scanned for Actions
*/
protected void processActionClass(Class<?> cls, String[] pkgs) {
ActionConfig actionConfig = new ActionConfig();
String name = cls.getName();
String actionPackage = cls.getPackage().getName();
String actionNamespace = null;
@@ -328,7 +321,7 @@ public class ClasspathPackageProvider implements PackageProvider {
}
}
PackageConfig pkgConfig = loadPackageConfig(actionNamespace, actionPackage, cls);
PackageConfig.Builder pkgConfig = loadPackageConfig(actionNamespace, actionPackage, cls);
// In case the package changed due to namespace annotation processing
if (!actionPackage.equals(pkgConfig.getName())) {
@@ -345,14 +338,14 @@ public class ClasspathPackageProvider implements PackageProvider {
pkgConfig.addParent(parentPkg);
if (!TextUtils.stringSet(pkgConfig.getNamespace()) && TextUtils.stringSet(parentPkg.getNamespace())) {
pkgConfig.setNamespace(parentPkg.getNamespace());
pkgConfig.namespace(parentPkg.getNamespace());
}
}
actionConfig.setClassName(cls.getName());
actionConfig.setPackageName(actionPackage);
actionConfig.setResults(new ResultMap<String,ResultConfig>(cls, actionName, pkgConfig));
ResultTypeConfig defaultResultType = packageLoader.getDefaultResultType(pkgConfig);
ActionConfig actionConfig = new ActionConfig.Builder(actionPackage, actionName, cls.getName())
.addResultConfigs(new ResultMap<String,ResultConfig>(cls, actionName, defaultResultType))
.build();
pkgConfig.addActionConfig(actionName, actionConfig);
}
@@ -367,8 +360,8 @@ public class ClasspathPackageProvider implements PackageProvider {
* @param actionClass The Action class instance
* @return PackageConfig object for the Action class
*/
protected PackageConfig loadPackageConfig(String actionNamespace, String actionPackage, Class actionClass) {
PackageConfig parent = null;
protected PackageConfig.Builder loadPackageConfig(String actionNamespace, String actionPackage, Class actionClass) {
PackageConfig.Builder parent = null;
// Check for the @Namespace annotation
if (actionClass != null) {
@@ -391,29 +384,34 @@ public class ClasspathPackageProvider implements PackageProvider {
}
PackageConfig pkgConfig = loadedPackageConfigs.get(actionPackage);
PackageConfig.Builder pkgConfig = packageLoader.getPackage(actionPackage);
if (pkgConfig == null) {
pkgConfig = new PackageConfig();
pkgConfig.setName(actionPackage);
pkgConfig = new PackageConfig.Builder(actionPackage);
pkgConfig.namespace(actionNamespace);
if (parent == null) {
parent = configuration.getPackageConfig(defaultParentPackage);
}
if (parent == null) {
throw new ConfigurationException("ClasspathPackageProvider: Unable to locate default parent package: " +
PackageConfig cfg = configuration.getPackageConfig(defaultParentPackage);
if (cfg != null) {
pkgConfig.addParent(cfg);
} else {
throw new ConfigurationException("ClasspathPackageProvider: Unable to locate default parent package: " +
defaultParentPackage);
}
}
pkgConfig.addParent(parent);
pkgConfig.setNamespace(actionNamespace);
packageLoader.registerPackage(pkgConfig);
loadedPackageConfigs.put(actionPackage, pkgConfig);
// if the parent package was first created by a child, ensure the namespace is correct
} else if (pkgConfig.getNamespace() == null) {
pkgConfig.setNamespace(actionNamespace);
pkgConfig.namespace(actionNamespace);
}
if (parent != null) {
packageLoader.registerChildToParent(pkgConfig, parent);
}
System.out.println("class:"+actionClass+" parent:"+parent+" current:"+(pkgConfig != null ? pkgConfig.getName() : ""));
return pkgConfig;
}
@@ -439,7 +437,6 @@ public class ClasspathPackageProvider implements PackageProvider {
* @throws ConfigurationException
*/
public void loadPackages() throws ConfigurationException {
loadedPackageConfigs.clear();
if (actionPackages != null) {
String[] names = actionPackages.split("\\s*[,]\\s*");
// Initialize the classloader scanner with the configured packages
@@ -467,12 +464,12 @@ public class ClasspathPackageProvider implements PackageProvider {
class ResultMap<K,V> extends HashMap<K,V> {
private Class actionClass;
private String actionName;
private PackageConfig pkgConfig;
private ResultTypeConfig defaultResultType;
public ResultMap(Class actionClass, String actionName, PackageConfig pkgConfig) {
public ResultMap(Class actionClass, String actionName, ResultTypeConfig defaultResultType) {
this.actionClass = actionClass;
this.actionName = actionName;
this.pkgConfig = pkgConfig;
this.defaultResultType = defaultResultType;
// check if any annotations are around
while (!actionClass.getName().equals(Object.class.getName())) {
@@ -543,10 +540,8 @@ public class ClasspathPackageProvider implements PackageProvider {
String location,
Map<? extends Object,? extends Object > configParams) {
if (resultClass == null) {
String defaultResultType = pkgConfig.getFullDefaultResultType();
ResultTypeConfig resultType = pkgConfig.getAllResultTypeConfigs().get(defaultResultType);
configParams = resultType.getParams();
String className = resultType.getClazz();
configParams = defaultResultType.getParams();
String className = defaultResultType.getClassName();
try {
resultClass = ClassLoaderUtil.loadClass(className, getClass());
} catch (ClassNotFoundException ex) {
@@ -568,7 +563,7 @@ public class ClasspathPackageProvider implements PackageProvider {
}
params.put(defaultParam, location);
return new ResultConfig((String) key, resultClass.getName(), params);
return new ResultConfig.Builder((String) key, resultClass.getName()).addParams(params).build();
}
}
@@ -598,4 +593,68 @@ public class ClasspathPackageProvider implements PackageProvider {
return url;
}
}
private static class PackageLoader {
/**
* The package configurations for scanned Actions.
*/
private Map<String,PackageConfig.Builder> packageConfigBuilders = new HashMap<String,PackageConfig.Builder>();
private Map<PackageConfig.Builder,PackageConfig.Builder> childToParent = new HashMap<PackageConfig.Builder,PackageConfig.Builder>();
public PackageConfig.Builder getPackage(String name) {
return packageConfigBuilders.get(name);
}
public void registerChildToParent(PackageConfig.Builder child, PackageConfig.Builder parent) {
childToParent.put(child, parent);
}
public void registerPackage(PackageConfig.Builder builder) {
packageConfigBuilders.put(builder.getName(), builder);
}
public Collection<PackageConfig> createPackageConfigs() {
Map<String, PackageConfig> configs = new HashMap<String, PackageConfig>();
Set<PackageConfig.Builder> builders;
while ((builders = findPackagesWithNoParents()).size() > 0) {
for (PackageConfig.Builder parent : builders) {
PackageConfig config = parent.build();
configs.put(config.getName(), config);
packageConfigBuilders.remove(config.getName());
for (Iterator<Map.Entry<PackageConfig.Builder,PackageConfig.Builder>> i = childToParent.entrySet().iterator(); i.hasNext(); ) {
Map.Entry<PackageConfig.Builder,PackageConfig.Builder> entry = i.next();
if (entry.getValue() == parent) {
entry.getKey().addParent(config);
i.remove();
}
}
}
}
return configs.values();
}
Set<PackageConfig.Builder> findPackagesWithNoParents() {
Set<PackageConfig.Builder> builders = new HashSet<PackageConfig.Builder>();
for (PackageConfig.Builder child : packageConfigBuilders.values()) {
if (!childToParent.containsKey(child)) {
builders.add(child);
}
}
return builders;
}
public ResultTypeConfig getDefaultResultType(PackageConfig.Builder pkgConfig) {
PackageConfig.Builder parent;
PackageConfig.Builder current = pkgConfig;
while ((parent = childToParent.get(current)) != null) {
current = parent;
}
return current.getResultType(current.getFullDefaultResultType());
}
}
}
@@ -61,7 +61,7 @@ public class CodebehindUnknownHandlerTest extends StrutsTestCase {
public void testBuildResult() {
ActionContext ctx = new ActionContext(new HashMap());
ResultTypeConfig config = new ResultTypeConfig("null", SomeResult.class.getName(), "location");
ResultTypeConfig config = new ResultTypeConfig.Builder("null", SomeResult.class.getName()).defaultResultParam("location").build();
Result result = handler.buildResult("/foo.jsp", "success", config, ctx);
assertNotNull(result);
@@ -44,12 +44,16 @@ public class ClasspathPackageProviderTest extends TestCase {
provider = new ClasspathPackageProvider();
provider.setActionPackages("org.apache.struts2.config");
config = new DefaultConfiguration();
PackageConfig strutsDefault = new PackageConfig("struts-default");
strutsDefault.addResultTypeConfig(new ResultTypeConfig("dispatcher", ServletDispatcherResult.class.getName(), "location"));
strutsDefault.setDefaultResultType("dispatcher");
PackageConfig strutsDefault = new PackageConfig.Builder("struts-default")
.addResultTypeConfig(new ResultTypeConfig.Builder("dispatcher", ServletDispatcherResult.class.getName())
.defaultResultParam("location")
.build())
.defaultResultType("dispatcher")
.build();
config.addPackageConfig("struts-default", strutsDefault);
PackageConfig customPackage = new PackageConfig("custom-package");
customPackage.setNamespace("/custom");
PackageConfig customPackage = new PackageConfig.Builder("custom-package")
.namespace("/custom")
.build();
config.addPackageConfig("custom-package", customPackage);
provider.init(config);
provider.loadPackages();
@@ -59,7 +63,7 @@ public class ClasspathPackageProviderTest extends TestCase {
provider = null;
config = null;
}
public void testFoundRootPackages() {
assertEquals(6, config.getPackageConfigs().size());
PackageConfig pkg = config.getPackageConfig("org.apache.struts2.config");
+1 -1
View File
@@ -55,7 +55,7 @@
<module>tiles</module>
<module>dojo</module>
<module>rest</module>
<module>portlet</module>
<module>portlet</module>
</modules>
<dependencies>
@@ -439,8 +439,7 @@ public class Jsr168Dispatcher extends GenericPortlet implements StrutsStatics,
LOG.debug("Creating action proxy for name = " + actionName
+ ", namespace = " + namespace);
ActionProxy proxy = factory.createActionProxy(namespace,
actionName, extraContext);
proxy.setMethod(mapping.getMethod());
actionName, mapping.getMethod(), extraContext);
request.setAttribute("struts.valueStack", proxy.getInvocation()
.getStack());
proxy.execute();
@@ -115,11 +115,10 @@ public class Jsr168DispatcherTest extends MockObjectTestCase implements PortletA
mockActionProxy = mock(ActionProxy.class);
mockInvocation = mock(ActionInvocation.class);
mockActionFactory.expects(once()).method("createActionProxy").with(new Constraint[]{eq(namespace), eq(actionName), isA(Map.class)}).will(returnValue(mockActionProxy.proxy()));
mockActionFactory.expects(once()).method("createActionProxy").with(new Constraint[]{eq(namespace), eq(actionName), NULL, isA(Map.class)}).will(returnValue(mockActionProxy.proxy()));
mockActionProxy.stubs().method("getAction").will(returnValue(mockAction.proxy()));
mockActionProxy.expects(once()).method("execute").will(returnValue(result));
mockActionProxy.expects(once()).method("getInvocation").will(returnValue(mockInvocation.proxy()));
mockActionProxy.expects(once()).method("setMethod");
mockInvocation.stubs().method("getStack").will(returnValue(stack));
}
@@ -243,11 +242,6 @@ public class Jsr168DispatcherTest extends MockObjectTestCase implements PortletA
mockRequest.stubs().method("getWindowState").will(returnValue(state));
}
/**
* @param requestParams
* @param mockRequest2
* @param string
*/
private void setupParamStub(Map requestParams, Mock mockRequest, String method) {
Map newMap = new HashMap();
Iterator it = requestParams.keySet().iterator();
@@ -78,7 +78,7 @@ public class RestActionInvocation extends DefaultActionInvocation {
private ContentTypeHandlerManager handlerSelector;
protected RestActionInvocation(Map extraContext, boolean pushAction) throws Exception {
protected RestActionInvocation(Map extraContext, boolean pushAction) {
super(extraContext, pushAction);
}
@@ -35,10 +35,11 @@ import com.opensymphony.xwork2.inject.Inject;
*/
public class RestActionProxyFactory extends DefaultActionProxyFactory {
public ActionProxy createActionProxy(String namespace, String actionName, Map extraContext, boolean executeResult, boolean cleanupContext) throws Exception {
@Override
public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map extraContext, boolean executeResult, boolean cleanupContext) {
ActionInvocation inv = new RestActionInvocation(extraContext, true);
container.inject(inv);
return createActionProxy(inv, namespace, actionName, extraContext, executeResult, cleanupContext);
return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
}
}
@@ -43,7 +43,7 @@ import static javax.servlet.http.HttpServletResponse.*;
* An interceptor that makes sure there are not validation errors before allowing the interceptor chain to continue.
* <b>This interceptor does not perform any validation</b>.
*
* <p>Copied from the {@link DefaultWorkflowInterceptor}, this interceptor adds support for error handling of Restful
* <p>Copied from the {@link com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor}, this interceptor adds support for error handling of Restful
* operations. For example, if an validation error is discovered, a map of errors is created and processed to be
* returned, using the appropriate content handler for rendering the body.</p>
*
@@ -79,7 +79,7 @@ public class ContentTypeHandlerManagerTest extends TestCase {
};
mgr.handlers.put("xml", handler);
mgr.defaultExtension = "xml";
mgr.handleResult(new ActionConfig(), new DefaultHttpHeaders().withStatus(SC_OK), obj);
mgr.handleResult(new ActionConfig.Builder("", "", "").build(), new DefaultHttpHeaders().withStatus(SC_OK), obj);
assertEquals(obj.getBytes().length, mockResponse.getContentLength());
}
@@ -24,8 +24,8 @@ public class RestActionMapperTest extends TestCase {
mapper = new RestActionMapper();
config = new DefaultConfiguration();
PackageConfig pkg = new PackageConfig("myns", "/animals", false, null);
PackageConfig pkg2 = new PackageConfig("my", "/my", false, null);
PackageConfig pkg = new PackageConfig.Builder("myns").namespace("/animals").build();
PackageConfig pkg2 = new PackageConfig.Builder("my").namespace("/my").build();
config.addPackageConfig("mvns", pkg);
config.addPackageConfig("my", pkg2);
configManager = new ConfigurationManager() {
@@ -12,9 +12,9 @@ digraph mygraph {
fontcolor=grey;
label="sitegraph";
tutorial_sitegraph_guess [label="guess",color="coral1"];
tutorial_sitegraph_guess_error_ftl [label="guess-error.ftl",color="darkseagreen2"];
tutorial_sitegraph_guess_input_ftl [label="guess-input.ftl",color="darkseagreen2"];
tutorial_sitegraph_guess_success_jsp [label="guess-success.jsp",color="darkseagreen2"];
tutorial_sitegraph_guess_input_ftl [label="guess-input.ftl",color="darkseagreen2"];
tutorial_sitegraph_guess_error_ftl [label="guess-error.ftl",color="darkseagreen2"];
}
tutorial_test [label="test",color="coral1"];
tutorial_guess_input_ftl [label="guess-input.ftl",color="darkseagreen2"];
@@ -185,7 +185,7 @@ public abstract class TemplatePageFilter extends PageFilter {
public void setActionEventListener(ActionEventListener listener) {
}
public void init(ActionProxy proxy) throws Exception {
public void init(ActionProxy proxy) {
}
}
}
@@ -208,7 +208,7 @@ public class ActionFormValidationInterceptor extends AbstractInterceptor {
}
/**
* @param pathnames the pathnames to set
* @param pathNames the pathnames to set
*/
public void setPathnames(String pathNames) {
this.pathnames = pathNames;
@@ -138,7 +138,7 @@ public class Struts1FactoryTest extends StrutsTestCase {
ExceptionConfig[] exceptionConfigs = mapping.findExceptionConfigs();
assertNotNull(exceptionConfigs);
assertEquals(3, exceptionConfigs.length);
assertEquals(2, exceptionConfigs.length);
ModuleConfig moduleConfig = mapping.getModuleConfig();
assertNotNull(moduleConfig);