diff --git a/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxy.java b/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxy.java index 4d73813eeb..6bc28ed252 100644 --- a/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxy.java +++ b/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxy.java @@ -168,8 +168,8 @@ private void resolveMethod() { this.method = config.getMethodName(); if (StringUtils.isEmpty(this.method)) { this.method = ActionConfig.DEFAULT_METHOD; + methodSpecified = false; } - methodSpecified = false; } } diff --git a/core/src/main/java/org/apache/struts2/ActionProxy.java b/core/src/main/java/org/apache/struts2/ActionProxy.java index d5e19e44da..ad800d4063 100644 --- a/core/src/main/java/org/apache/struts2/ActionProxy.java +++ b/core/src/main/java/org/apache/struts2/ActionProxy.java @@ -93,9 +93,11 @@ public interface ActionProxy { String getMethod(); /** - * Gets status of the method value's initialization. + * Gets status of the method value's initialization. Returns {@code true} when the method was explicitly provided + * (e.g. via URL parameter, wildcard substitution, or action configuration), and {@code false} only when the + * framework defaults to {@code "execute"} because no method was specified anywhere. * - * @return true if the method returned by getMethod() is not a default initializer value. + * @return true if the method returned by getMethod() is not the default "execute" fallback. */ boolean isMethodSpecified(); diff --git a/core/src/test/java/com/opensymphony/xwork2/DefaultActionProxyTest.java b/core/src/test/java/com/opensymphony/xwork2/DefaultActionProxyTest.java index 125c5b4bd6..5db2f68cf8 100644 --- a/core/src/test/java/com/opensymphony/xwork2/DefaultActionProxyTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/DefaultActionProxyTest.java @@ -18,15 +18,14 @@ */ package com.opensymphony.xwork2; +import com.opensymphony.xwork2.config.ConfigurationException; import com.opensymphony.xwork2.mock.MockActionInvocation; import org.apache.struts2.StrutsInternalTestCase; import org.apache.struts2.config.StrutsXmlConfigurationProvider; -import org.junit.Test; public class DefaultActionProxyTest extends StrutsInternalTestCase { - @Test - public void testThorwExceptionOnNotAllowedMethod() throws Exception { + public void testThrowExceptionOnNotAllowedMethod() { final String filename = "com/opensymphony/xwork2/config/providers/xwork-test-allowed-methods.xml"; loadConfigurationProviders(new StrutsXmlConfigurationProvider(filename)); DefaultActionProxy dap = new DefaultActionProxy(new MockActionInvocation(), "strict", "Default", "notAllowed", true, true); @@ -35,8 +34,52 @@ public void testThorwExceptionOnNotAllowedMethod() throws Exception { try { dap.prepare(); fail("Must throw exception!"); - } catch (Exception e) { - assertEquals(e.getMessage(), "Method notAllowed for action Default is not allowed!"); + } catch (ConfigurationException e) { + assertEquals("Method notAllowed for action Default is not allowed!", e.getMessage()); } } + + public void testMethodSpecifiedWhenPassedExplicitly() { + final String filename = "com/opensymphony/xwork2/config/providers/xwork-test-allowed-methods.xml"; + loadConfigurationProviders(new StrutsXmlConfigurationProvider(filename)); + DefaultActionProxy dap = new DefaultActionProxy(new MockActionInvocation(), "", "NoMethod", "onPostOnly", true, true); + container.inject(dap); + dap.prepare(); + + assertTrue("Method passed explicitly should be marked as specified", dap.isMethodSpecified()); + assertEquals("onPostOnly", dap.getMethod()); + } + + public void testMethodSpecifiedWhenResolvedFromConfig() { + final String filename = "com/opensymphony/xwork2/config/providers/xwork-test-allowed-methods.xml"; + loadConfigurationProviders(new StrutsXmlConfigurationProvider(filename)); + DefaultActionProxy dap = new DefaultActionProxy(new MockActionInvocation(), "", "ConfigMethod", null, true, true); + container.inject(dap); + dap.prepare(); + + assertTrue("Method resolved from action config should be marked as specified", dap.isMethodSpecified()); + assertEquals("onPostOnly", dap.getMethod()); + } + + public void testMethodNotSpecifiedWhenDefaultingToExecute() { + final String filename = "com/opensymphony/xwork2/config/providers/xwork-test-allowed-methods.xml"; + loadConfigurationProviders(new StrutsXmlConfigurationProvider(filename)); + DefaultActionProxy dap = new DefaultActionProxy(new MockActionInvocation(), "", "NoMethod", null, true, true); + container.inject(dap); + dap.prepare(); + + assertFalse("Method defaulting to execute should not be marked as specified", dap.isMethodSpecified()); + assertEquals("execute", dap.getMethod()); + } + + public void testMethodSpecifiedWithWildcardAction() { + final String filename = "com/opensymphony/xwork2/config/providers/xwork-test-allowed-methods.xml"; + loadConfigurationProviders(new StrutsXmlConfigurationProvider(filename)); + DefaultActionProxy dap = new DefaultActionProxy(new MockActionInvocation(), "", "Wild-onPostOnly", null, true, true); + container.inject(dap); + dap.prepare(); + + assertTrue("Method resolved from wildcard should be marked as specified", dap.isMethodSpecified()); + assertEquals("onPostOnly", dap.getMethod()); + } } \ No newline at end of file diff --git a/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderAllowedMethodsTest.java b/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderAllowedMethodsTest.java index 1ac2315bc4..00604757d5 100644 --- a/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderAllowedMethodsTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderAllowedMethodsTest.java @@ -42,7 +42,7 @@ public void testDefaultAllowedMethods() throws ConfigurationException { Map actionConfigs = pkg.getActionConfigs(); // assertions - assertEquals(5, actionConfigs.size()); + assertEquals(8, actionConfigs.size()); ActionConfig action = (ActionConfig) actionConfigs.get("Default"); assertEquals(1, action.getAllowedMethods().size()); diff --git a/core/src/test/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptorTest.java index 98e78c3fa5..f68b01df3f 100644 --- a/core/src/test/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptorTest.java +++ b/core/src/test/java/org/apache/struts2/interceptor/httpmethod/HttpMethodInterceptorTest.java @@ -217,6 +217,43 @@ public void testPostOnPutOrPostMethod() throws Exception { assertEquals(HttpMethod.POST, action.getHttpMethod()); } + public void testWildcardResolvedMethodWithPostAnnotationRejectsGet() throws Exception { + // given + HttpMethodsTestAction action = new HttpMethodsTestAction(); + prepareActionInvocation(action); + actionProxy.setMethod("onPostOnly"); + actionProxy.setMethodSpecified(true); + + invocation.setResultCode("onPostOnly"); + + prepareRequest("GET"); + + // when + String resultName = interceptor.intercept(invocation); + + // then + assertEquals("bad-request", resultName); + } + + public void testWildcardResolvedMethodWithPostAnnotationAllowsPost() throws Exception { + // given + HttpMethodsTestAction action = new HttpMethodsTestAction(); + prepareActionInvocation(action); + actionProxy.setMethod("onPostOnly"); + actionProxy.setMethodSpecified(true); + + invocation.setResultCode("onPostOnly"); + + prepareRequest("POST"); + + // when + String resultName = interceptor.intercept(invocation); + + // then + assertEquals("onPostOnly", resultName); + assertEquals(HttpMethod.POST, action.getHttpMethod()); + } + private void prepareActionInvocation(Object action) { interceptor = new HttpMethodInterceptor(); invocation = new MockActionInvocation(); diff --git a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowed-methods.xml b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowed-methods.xml index 247b4ef271..0c78ff5cf9 100644 --- a/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowed-methods.xml +++ b/core/src/test/resources/com/opensymphony/xwork2/config/providers/xwork-test-allowed-methods.xml @@ -29,7 +29,7 @@ - + @@ -43,6 +43,18 @@ foo,bar + + + regex:.* + + + + regex:.* + + + + regex:.* +