diff --git a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java index 2bc9672d4..96ea7b1be 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java @@ -1,4 +1,5 @@ /* + * $Id$ * $Id$ * * Licensed to the Apache Software Foundation (ASF) under one @@ -33,6 +34,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.struts2.RequestUtils; import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsConstants; +import org.apache.struts2.dispatcher.ServletDispatcherResult; import org.apache.struts2.util.PrefixTrie; import javax.servlet.http.HttpServletRequest; @@ -168,8 +170,9 @@ public class DefaultActionMapper implements ActionMapper { protected static final String METHOD_PREFIX = "method:"; protected static final String ACTION_PREFIX = "action:"; + private static final String STRUTS2_ACTION_PREFIX_PARSED = "_struts2_action_prefix_parsed"; - protected boolean allowDynamicMethodCalls = true; + protected boolean allowDynamicMethodCalls = false; protected boolean allowSlashesInActionNames = false; protected boolean alwaysSelectFullNamespace = false; protected PrefixTrie prefixTrie = null; @@ -186,7 +189,7 @@ public class DefaultActionMapper implements ActionMapper { prefixTrie = new PrefixTrie() { { put(METHOD_PREFIX, new ParameterAction() { - public void execute(String key, ActionMapping mapping) { + public void execute(String key, ActionMapping mapping, HttpServletRequest request) { if (allowDynamicMethodCalls) { mapping.setMethod(key.substring(METHOD_PREFIX.length())); } @@ -194,17 +197,25 @@ public class DefaultActionMapper implements ActionMapper { }); put(ACTION_PREFIX, new ParameterAction() { - public void execute(String key, ActionMapping mapping) { - String name = key.substring(ACTION_PREFIX.length()); - if (allowDynamicMethodCalls) { - int bang = name.indexOf('!'); - if (bang != -1) { - String method = name.substring(bang + 1); - mapping.setMethod(method); - name = name.substring(0, bang); + public void execute(final String key, ActionMapping mapping, HttpServletRequest request) { + if (request != null && request.getAttribute(STRUTS2_ACTION_PREFIX_PARSED) == null) { + request.setAttribute(STRUTS2_ACTION_PREFIX_PARSED, true); + String name = key.substring(ACTION_PREFIX.length()); + if (allowDynamicMethodCalls) { + int bang = name.indexOf('!'); + if (bang != -1) { + String method = name.substring(bang + 1); + mapping.setMethod(method); + name = name.substring(0, bang); + } } + String actionName = cleanupActionName(name); + mapping.setName(actionName); + if (getDefaultExtension() != null) { + actionName = actionName + "." + getDefaultExtension(); + } + mapping.setResult(new ServletDispatcherResult(actionName)); } - mapping.setName(cleanupActionName(name)); } }); @@ -225,7 +236,7 @@ public class DefaultActionMapper implements ActionMapper { @Inject(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION) public void setAllowDynamicMethodCalls(String allow) { - allowDynamicMethodCalls = "true".equals(allow); + allowDynamicMethodCalls = "true".equalsIgnoreCase(allow); } @Inject(StrutsConstants.STRUTS_ENABLE_SLASHES_IN_ACTION_NAMES) @@ -335,7 +346,7 @@ public class DefaultActionMapper implements ActionMapper { if (!uniqueParameters.contains(key)) { ParameterAction parameterAction = (ParameterAction) prefixTrie.get(key); if (parameterAction != null) { - parameterAction.execute(key, mapping); + parameterAction.execute(key, mapping, request); uniqueParameters.add(key); break; } diff --git a/core/src/main/java/org/apache/struts2/dispatcher/mapper/ParameterAction.java b/core/src/main/java/org/apache/struts2/dispatcher/mapper/ParameterAction.java index f4f3f4fae..a3c7bdf26 100644 --- a/core/src/main/java/org/apache/struts2/dispatcher/mapper/ParameterAction.java +++ b/core/src/main/java/org/apache/struts2/dispatcher/mapper/ParameterAction.java @@ -21,6 +21,8 @@ package org.apache.struts2.dispatcher.mapper; +import javax.servlet.http.HttpServletRequest; + /** * Defines a parameter action prefix. This is executed when the configured prefix key is matched in a parameter * name, allowing the implementation to manipulate the action mapping accordingly. For example, if the "action:foo" @@ -30,5 +32,5 @@ package org.apache.struts2.dispatcher.mapper; * @since 2.1.0 */ public interface ParameterAction { - void execute(String key, ActionMapping mapping); + void execute(String key, ActionMapping mapping, HttpServletRequest request); } diff --git a/core/src/main/resources/org/apache/struts2/default.properties b/core/src/main/resources/org/apache/struts2/default.properties index 6e16db1eb..2d2ad1199 100644 --- a/core/src/main/resources/org/apache/struts2/default.properties +++ b/core/src/main/resources/org/apache/struts2/default.properties @@ -105,7 +105,7 @@ struts.serve.static.browserCache=true ### like method:bar (but not action:foo). ### An alternative to implicit dynamic method invocation is to use wildcard ### mappings, such as -struts.enable.DynamicMethodInvocation = true +struts.enable.DynamicMethodInvocation = false ### Set this to true if you wish to allow slashes in your action names. If false, ### Actions names cannot have slashes, and will be accessible via any directory diff --git a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java index a1270ee24..93b5a9a86 100644 --- a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java +++ b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java @@ -1,4 +1,5 @@ /* + * $Id$ * $Id$ * * Licensed to the Apache Software Foundation (ASF) under one @@ -33,6 +34,7 @@ import org.apache.struts2.StrutsTestCase; import org.apache.struts2.dispatcher.StrutsResultSupport; import org.apache.struts2.views.jsp.StrutsMockHttpServletRequest; +import javax.servlet.http.HttpServletRequest; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -88,6 +90,7 @@ public class DefaultActionMapperTest extends StrutsTestCase { req.addExpectedGetAttributeName("javax.servlet.include.servlet_path"); DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowDynamicMethodCalls("true"); ActionMapping mapping = mapper.getMapping(req, configManager); assertEquals("/my/namespace", mapping.getNamespace()); @@ -212,6 +215,7 @@ public class DefaultActionMapperTest extends StrutsTestCase { public void testGetMappingWithActionName_methodAndName() throws Exception { DefaultActionMapper mapper = new DefaultActionMapper(); + mapper.setAllowDynamicMethodCalls("true"); ActionMapping mapping = mapper.getMappingFromActionName("actionName!add"); assertEquals("actionName", mapping.getName()); assertEquals("add", mapping.getMethod()); @@ -407,7 +411,7 @@ public class DefaultActionMapperTest extends StrutsTestCase { DefaultActionMapper defaultActionMapper = new DefaultActionMapper(); ActionMapping actionMapping = defaultActionMapper.getMapping(request, configManager); - assertEquals(actionMapping.getName(), "myAction"); + assertEquals("myAction", actionMapping.getName()); } public void testActionPrefix_fromImageButton() throws Exception { @@ -423,7 +427,7 @@ public class DefaultActionMapperTest extends StrutsTestCase { DefaultActionMapper defaultActionMapper = new DefaultActionMapper(); ActionMapping actionMapping = defaultActionMapper.getMapping(request, configManager); - assertEquals(actionMapping.getName(), "myAction"); + assertEquals("myAction", actionMapping.getName()); } public void testActionPrefix_fromIEImageButton() throws Exception { @@ -438,7 +442,7 @@ public class DefaultActionMapperTest extends StrutsTestCase { DefaultActionMapper defaultActionMapper = new DefaultActionMapper(); ActionMapping actionMapping = defaultActionMapper.getMapping(request, configManager); - assertEquals(actionMapping.getName(), "myAction"); + assertEquals("myAction", actionMapping.getName()); } public void testRedirectPrefix() throws Exception { @@ -529,13 +533,13 @@ public class DefaultActionMapperTest extends StrutsTestCase { Map parameterMap = new HashMap(); parameterMap.put("foo:myAction", ""); - StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest(); + final StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest(); request.setParameterMap(parameterMap); request.setupGetServletPath("/someServletPath.action"); DefaultActionMapper defaultActionMapper = new DefaultActionMapper(); defaultActionMapper.addParameterAction("foo", new ParameterAction() { - public void execute(String key, ActionMapping mapping) { + public void execute(String key, ActionMapping mapping, HttpServletRequest request) { mapping.setName("myAction"); } }); diff --git a/core/src/test/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapperTest.java b/core/src/test/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapperTest.java index dc203cb61..116ad946e 100644 --- a/core/src/test/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapperTest.java +++ b/core/src/test/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapperTest.java @@ -92,6 +92,7 @@ public class Restful2ActionMapperTest extends StrutsTestCase { public void testGetEdit() throws Exception { mapper.setIdParameterName("id"); + mapper.setAllowDynamicMethodCalls("true"); req.setupGetRequestURI("/my/namespace/foo/3!edit"); req.setupGetServletPath("/my/namespace/foo/3!edit"); req.setupGetAttribute(null); diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ActionTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ActionTagTest.java index 7b7238881..4a1f90d14 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ActionTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ActionTagTest.java @@ -21,24 +21,24 @@ package org.apache.struts2.views.jsp; -import java.util.HashMap; - -import javax.servlet.jsp.JspException; -import javax.servlet.jsp.PageContext; - -import org.apache.struts2.ServletActionContext; -import org.apache.struts2.StrutsException; -import org.apache.struts2.TestAction; -import org.apache.struts2.TestActionTagResult; -import org.apache.struts2.TestConfigurationProvider; -import org.apache.struts2.components.ActionComponent; - import com.mockobjects.dynamic.Mock; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.ActionProxy; import com.opensymphony.xwork2.config.entities.ActionConfig; +import org.apache.struts2.ServletActionContext; +import org.apache.struts2.StrutsException; +import org.apache.struts2.TestAction; +import org.apache.struts2.TestActionTagResult; +import org.apache.struts2.TestConfigurationProvider; +import org.apache.struts2.components.ActionComponent; +import org.apache.struts2.dispatcher.mapper.ActionMapper; +import org.apache.struts2.dispatcher.mapper.DefaultActionMapper; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.PageContext; +import java.util.HashMap; /** @@ -282,6 +282,7 @@ public class ActionTagTest extends AbstractTagTest { tag.setNamespace(""); tag.setName("testActionTagAction!input"); tag.setExecuteResult(true); + ((DefaultActionMapper)container.getInstance(ActionMapper.class)).setAllowDynamicMethodCalls("true"); tag.doStartTag(); diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java index 211cc2904..aadfd1159 100644 --- a/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java +++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java @@ -39,6 +39,8 @@ import org.apache.struts2.TestAction; import org.apache.struts2.TestConfigurationProvider; import org.apache.struts2.components.Form; import org.apache.struts2.dispatcher.Dispatcher; +import org.apache.struts2.dispatcher.mapper.ActionMapper; +import org.apache.struts2.dispatcher.mapper.DefaultActionMapper; import org.apache.struts2.views.jsp.AbstractUITagTest; import org.apache.struts2.views.jsp.ActionTag; import org.easymock.EasyMock; @@ -110,6 +112,9 @@ public class FormTagTest extends AbstractUITagTest { tag.setEnctype("myEncType"); tag.setTitle("mytitle"); tag.setOnsubmit("submitMe()"); + + ((DefaultActionMapper)container.getInstance(ActionMapper.class)).setAllowDynamicMethodCalls("true"); + tag.doStartTag(); tag.doEndTag(); diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionMapper.java b/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionMapper.java index f0e44bd35..d9224c3f5 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionMapper.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionMapper.java @@ -108,7 +108,7 @@ public class RestActionMapper extends DefaultActionMapper { private String optionsMethodName = "options"; private String postContinueMethodName = "createContinue"; private String putContinueMethodName = "updateContinue"; - private boolean allowDynamicMethodCalls = true; + private boolean allowDynamicMethodCalls = false; public RestActionMapper() { } diff --git a/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionMapperTest.java b/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionMapperTest.java index ffaa99ef6..8d39cc19a 100644 --- a/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionMapperTest.java +++ b/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionMapperTest.java @@ -200,6 +200,7 @@ public class RestActionMapperTest extends TestCase { req.setServletPath("/animals/dog/fido!edit"); req.setMethod("GET"); + mapper.setAllowDynamicMethodCalls("true"); ActionMapping mapping = mapper.getMapping(req, configManager); assertEquals("/animals", mapping.getNamespace()); @@ -303,6 +304,8 @@ public class RestActionMapperTest extends TestCase { req.setServletPath("/animals/dog/23!edit"); req.setMethod("GET"); + mapper.setAllowDynamicMethodCalls("true"); + // when ActionMapping actionMapping = mapper.getMapping(req, configManager);