You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2015/06/23 17:14:39 UTC

[1/4] struts git commit: WW-4518 Moves results to dedicated package

Repository: struts
Updated Branches:
  refs/heads/master 8de090fda -> 6bc99ab93


http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/result/ServletDispatcherResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/result/ServletDispatcherResultTest.java b/core/src/test/java/org/apache/struts2/result/ServletDispatcherResultTest.java
new file mode 100644
index 0000000..d9d878d
--- /dev/null
+++ b/core/src/test/java/org/apache/struts2/result/ServletDispatcherResultTest.java
@@ -0,0 +1,110 @@
+/*
+ * $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.result;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import ognl.Ognl;
+
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsInternalTestCase;
+import org.apache.struts2.StrutsStatics;
+
+import com.mockobjects.dynamic.C;
+import com.mockobjects.dynamic.Mock;
+import com.opensymphony.xwork2.ActionContext;
+import org.apache.struts2.result.ServletDispatcherResult;
+
+
+/**
+ *
+ */
+public class ServletDispatcherResultTest extends StrutsInternalTestCase implements StrutsStatics {
+
+    public void testInclude() {
+        ServletDispatcherResult view = new ServletDispatcherResult();
+        view.setLocation("foo.jsp");
+
+        Mock dispatcherMock = new Mock(RequestDispatcher.class);
+        dispatcherMock.expect("include", C.ANY_ARGS);
+
+        Mock requestMock = new Mock(HttpServletRequest.class);
+        requestMock.expectAndReturn("getAttribute", "struts.actiontag.invocation", null);
+        requestMock.expectAndReturn("getRequestDispatcher", C.args(C.eq("foo.jsp")), dispatcherMock.proxy());
+
+        Mock responseMock = new Mock(HttpServletResponse.class);
+        responseMock.expectAndReturn("isCommitted", Boolean.TRUE);
+
+        ActionContext ac = new ActionContext(Ognl.createDefaultContext(null));
+        ActionContext.setContext(ac);
+        ServletActionContext.setRequest((HttpServletRequest) requestMock.proxy());
+        ServletActionContext.setResponse((HttpServletResponse) responseMock.proxy());
+
+        try {
+            view.execute(null);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail();
+        }
+
+        dispatcherMock.verify();
+        requestMock.verify();
+        dispatcherMock.verify();
+    }
+
+    public void testSimple() {
+        ServletDispatcherResult view = new ServletDispatcherResult();
+        view.setLocation("foo.jsp");
+
+        Mock dispatcherMock = new Mock(RequestDispatcher.class);
+        dispatcherMock.expect("forward", C.ANY_ARGS);
+
+        Mock requestMock = new Mock(HttpServletRequest.class);
+        requestMock.expectAndReturn("getAttribute", "struts.actiontag.invocation", null);
+        requestMock.expectAndReturn("getAttribute", "javax.servlet.include.servlet_path", null);
+        requestMock.expectAndReturn("getRequestDispatcher", C.args(C.eq("foo.jsp")), dispatcherMock.proxy());
+        requestMock.expect("setAttribute", C.ANY_ARGS); // this is a bad mock, but it works
+        requestMock.expect("setAttribute", C.ANY_ARGS); // this is a bad mock, but it works
+        requestMock.matchAndReturn("getRequestURI", "foo.jsp");
+
+        Mock responseMock = new Mock(HttpServletResponse.class);
+        responseMock.expectAndReturn("isCommitted", Boolean.FALSE);
+
+        ActionContext ac = new ActionContext(Ognl.createDefaultContext(null));
+        ActionContext.setContext(ac);
+        ServletActionContext.setRequest((HttpServletRequest) requestMock.proxy());
+        ServletActionContext.setResponse((HttpServletResponse) responseMock.proxy());
+
+        try {
+            view.execute(null);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail();
+        }
+
+        dispatcherMock.verify();
+        requestMock.verify();
+        dispatcherMock.verify();
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/result/ServletRedirectResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/result/ServletRedirectResultTest.java b/core/src/test/java/org/apache/struts2/result/ServletRedirectResultTest.java
new file mode 100644
index 0000000..cdf4104
--- /dev/null
+++ b/core/src/test/java/org/apache/struts2/result/ServletRedirectResultTest.java
@@ -0,0 +1,361 @@
+/*
+ * $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.result;
+
+import static javax.servlet.http.HttpServletResponse.SC_SEE_OTHER;
+import static org.easymock.EasyMock.createControl;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import ognl.Ognl;
+
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsInternalTestCase;
+import org.apache.struts2.StrutsStatics;
+import org.apache.struts2.dispatcher.mapper.ActionMapper;
+import org.apache.struts2.result.ServletRedirectResult;
+import org.apache.struts2.views.util.DefaultUrlHelper;
+import org.easymock.IMocksControl;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+import com.mockobjects.dynamic.C;
+import com.mockobjects.dynamic.Mock;
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.ActionProxy;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.config.entities.PackageConfig;
+import com.opensymphony.xwork2.config.entities.ResultConfig;
+import com.opensymphony.xwork2.mock.MockActionInvocation;
+import com.opensymphony.xwork2.util.ValueStack;
+
+
+/**
+ */
+public class ServletRedirectResultTest extends StrutsInternalTestCase implements StrutsStatics {
+
+    protected ServletRedirectResult view;
+    private Mock requestMock;
+    private Mock responseMock;
+    protected ActionInvocation ai;
+
+
+    public void testAbsoluteRedirect() {
+        view.setLocation("/bar/foo.jsp");
+        responseMock.expectAndReturn("encodeRedirectURL", "/context/bar/foo.jsp", "/context/bar/foo.jsp");
+        responseMock.expect("sendRedirect", C.args(C.eq("/context/bar/foo.jsp")));
+
+        try {
+            view.execute(ai);
+            requestMock.verify();
+            responseMock.verify();
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+
+    public void testFullUrlRedirect() {
+        view.setLocation("http://localhost/bar/foo.jsp");
+        responseMock.expectAndReturn("encodeRedirectURL", C.args(C.eq("http://localhost/bar/foo.jsp")), "http://localhost/bar/foo.jsp");
+        responseMock.expect("sendRedirect", C.args(C.eq("http://localhost/bar/foo.jsp")));
+
+        try {
+            view.execute(ai);
+            requestMock.verify();
+            responseMock.verify();
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+
+    public void testFullUrlRedirectWithSpaces() {
+        view.setLocation("http://localhost/bar/foo some.pdf");
+        responseMock.expectAndReturn("encodeRedirectURL", C.args(C.eq("http://localhost/bar/foo some.pdf")), "http://localhost/bar/foo some.pdf");
+        responseMock.expect("sendRedirect", C.args(C.eq("http://localhost/bar/foo some.pdf")));
+
+        try {
+            view.execute(ai);
+            requestMock.verify();
+            responseMock.verify();
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+
+    public void testFullUrlRedirectWithParams() {
+        view.setLocation("http://localhost/bar/foo.action?param=1&param 2=3");
+        responseMock.expectAndReturn("encodeRedirectURL", C.args(C.eq("http://localhost/bar/foo.action?param=1&param 2=3")), "http://localhost/bar/foo.action?param=1&param 2=3");
+        responseMock.expect("sendRedirect", C.args(C.eq("http://localhost/bar/foo.action?param=1&param 2=3")));
+
+        try {
+            view.execute(ai);
+            requestMock.verify();
+            responseMock.verify();
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+
+    public void testAbsoluteRedirect303() {
+        view.setLocation("/bar/foo.jsp");
+        view.setStatusCode(303);
+        responseMock.expectAndReturn("encodeRedirectURL", "/context/bar/foo.jsp", "/context/bar/foo.jsp");
+        responseMock.expect("setStatus", C.args(C.eq(SC_SEE_OTHER)));
+        responseMock.expect("setHeader", C.args(C.eq("Location"), C.eq("/context/bar/foo.jsp")));
+        StringWriter writer = new StringWriter();
+        responseMock.matchAndReturn("getWriter", new PrintWriter(writer));
+
+        try {
+            view.execute(ai);
+            requestMock.verify();
+            responseMock.verify();
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail();
+        }
+        assertEquals("/context/bar/foo.jsp", writer.toString());
+    }
+
+    public void testAbsoluteRedirectAnchor() {
+        view.setLocation("/bar/foo.jsp");
+        view.setAnchor("fragment");
+        responseMock.expectAndReturn("encodeRedirectURL", "/context/bar/foo.jsp#fragment", "/context/bar/foo.jsp#fragment");
+        responseMock.expect("sendRedirect", C.args(C.eq("/context/bar/foo.jsp#fragment")));
+
+        try {
+            view.execute(ai);
+            requestMock.verify();
+            responseMock.verify();
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+    public void testPrependServletContextFalse() {
+        view.setLocation("/bar/foo.jsp");
+        view.setPrependServletContext(false);
+        responseMock.expectAndReturn("encodeRedirectURL", "/bar/foo.jsp", "/bar/foo.jsp");
+        responseMock.expect("sendRedirect", C.args(C.eq("/bar/foo.jsp")));
+
+        try {
+            view.execute(ai);
+            requestMock.verify();
+            responseMock.verify();
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+
+    public void testRelativeRedirect() throws Exception {
+        view.setLocation("foo.jsp");
+        requestMock.expectAndReturn("getParameterMap", new HashMap());
+        requestMock.expectAndReturn("getServletPath", "/namespace/some.action");
+        requestMock.expectAndReturn("getRequestURI", "/namespace/some.action");
+        requestMock.expectAndReturn("getAttribute", C.ANY_ARGS, null);
+        responseMock.expectAndReturn("encodeRedirectURL", "/context/namespace/foo.jsp", "/context/namespace/foo.jsp");
+        responseMock.expect("sendRedirect", C.args(C.eq("/context/namespace/foo.jsp")));
+
+        view.execute(ai);
+
+        requestMock.verify();
+        responseMock.verify();
+    }
+    
+    public void testMultipleParametersRedirect() throws Exception {
+        view.setLocation("foo.jsp?foo=bar&baz=jim");
+        requestMock.expectAndReturn("getParameterMap", new HashMap());
+        requestMock.expectAndReturn("getServletPath", "/namespace/some.action");
+        requestMock.expectAndReturn("getRequestURI", "/namespace/some.action");
+        requestMock.expectAndReturn("getAttribute", C.ANY_ARGS, null);
+        responseMock.expectAndReturn("encodeRedirectURL", "/context/namespace/foo.jsp?foo=bar&baz=jim", "/context/namespace/foo.jsp?foo=bar&baz=jim");
+        responseMock.expect("sendRedirect", C.args(C.eq("/context/namespace/foo.jsp?foo=bar&baz=jim")));
+
+        view.execute(ai);
+
+        requestMock.verify();
+        responseMock.verify();
+    }
+
+    public void testIncludeParameterInResult() throws Exception {
+
+        ResultConfig resultConfig = new ResultConfig.Builder("", "")
+            .addParam("namespace", "someNamespace")
+            .addParam("encode", "true")
+            .addParam("parse", "true")
+            .addParam("location", "someLocation")
+            .addParam("prependServletContext", "true")
+            .addParam("method", "someMethod")
+            .addParam("statusCode", "333")
+            .addParam("param1", "value 1")
+            .addParam("param2", "value 2")
+            .addParam("param3", "value 3")
+            .build();
+
+        ActionContext context = ActionContext.getContext();
+        MockHttpServletRequest req = new MockHttpServletRequest();
+        MockHttpServletResponse res = new MockHttpServletResponse();
+        context.put(ServletActionContext.HTTP_REQUEST, req);
+        context.put(ServletActionContext.HTTP_RESPONSE, res);
+
+
+        Map<String, ResultConfig> results=  new HashMap<String, ResultConfig>();
+        results.put("myResult", resultConfig);
+
+        ActionConfig actionConfig = new ActionConfig.Builder("", "", "")
+                .addResultConfigs(results).build();
+
+        ServletRedirectResult result = new ServletRedirectResult();
+        result.setLocation("/myNamespace/myAction.action");
+        result.setParse(false);
+        result.setEncode(false);
+        result.setPrependServletContext(false);
+        result.setAnchor("fragment");
+        result.setUrlHelper(new DefaultUrlHelper());
+
+        IMocksControl control = createControl();
+        ActionProxy mockActionProxy = control.createMock(ActionProxy.class);
+        ActionInvocation mockInvocation = control.createMock(ActionInvocation.class);
+        expect(mockInvocation.getProxy()).andReturn(mockActionProxy);
+        expect(mockInvocation.getResultCode()).andReturn("myResult");
+        expect(mockActionProxy.getConfig()).andReturn(actionConfig);
+        expect(mockInvocation.getInvocationContext()).andReturn(context);
+
+        control.replay();
+        result.setActionMapper(container.getInstance(ActionMapper.class));
+        result.execute(mockInvocation);
+        assertEquals("/myNamespace/myAction.action?param1=value+1&param2=value+2&param3=value+3#fragment", res.getRedirectedUrl());
+        control.verify();
+    }
+
+    public void testIncludeCollectionParameterInResult() throws Exception {
+        List<String> paramValues = new ArrayList<String>();
+        paramValues.add("value 1");
+        paramValues.add("");
+        paramValues.add("value 2");
+        paramValues.add(null);
+
+        ResultConfig resultConfig = new ResultConfig.Builder("", "")
+            .addParam("namespace", "someNamespace")
+            .addParam("param", "${list}")
+            .build();
+
+        ActionContext context = ActionContext.getContext();
+        MockHttpServletRequest req = new MockHttpServletRequest();
+        MockHttpServletResponse res = new MockHttpServletResponse();
+        context.put(ServletActionContext.HTTP_REQUEST, req);
+        context.put(ServletActionContext.HTTP_RESPONSE, res);
+
+        Map<String, ResultConfig> results=  new HashMap<String, ResultConfig>();
+        results.put("myResult", resultConfig);
+
+        ActionConfig actionConfig = new ActionConfig.Builder("", "", "")
+                .addResultConfigs(results).build();
+
+        ServletRedirectResult result = new ServletRedirectResult();
+        result.setLocation("/myNamespace/myAction.action");
+        result.setParse(true);
+        result.setEncode(false);
+        result.setPrependServletContext(false);
+        result.setUrlHelper(new DefaultUrlHelper());
+        result.setSuppressEmptyParameters(true);
+
+        IMocksControl control = createControl();
+        ActionProxy mockActionProxy = control.createMock(ActionProxy.class);
+        ActionInvocation mockInvocation = control.createMock(ActionInvocation.class);
+
+        ValueStack mockValueStack = control.createMock(ValueStack.class);
+        Map<String, Object> mockContext = new HashMap<String, Object>();
+        mockContext.put(ActionContext.CONTAINER, container);
+
+        expect(mockInvocation.getStack()).andReturn(mockValueStack);
+        expect(mockValueStack.getContext()).andReturn(mockContext);
+
+        expect(mockInvocation.getStack()).andReturn(mockValueStack);
+
+        expect(mockValueStack.findValue("list")).andReturn(paramValues); // no asType !!!
+
+        expect(mockInvocation.getProxy()).andReturn(mockActionProxy);
+        expect(mockInvocation.getResultCode()).andReturn("myResult");
+        expect(mockActionProxy.getConfig()).andReturn(actionConfig);
+        expect(mockInvocation.getInvocationContext()).andReturn(context);
+
+        expect(mockValueStack.getContext()).andReturn(mockContext);
+
+        control.replay();
+        result.setActionMapper(container.getInstance(ActionMapper.class));
+        result.execute(mockInvocation);
+        assertEquals("/myNamespace/myAction.action?param=value+1&param=value+2", res.getRedirectedUrl());
+        control.verify();
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        configurationManager.getConfiguration().
+            addPackageConfig("foo", new PackageConfig.Builder("foo").namespace("/namespace").build());
+
+        view = new ServletRedirectResult();
+        container.inject(view);
+
+        responseMock = new Mock(HttpServletResponse.class);
+
+        requestMock = new Mock(HttpServletRequest.class);
+        requestMock.matchAndReturn("getContextPath", "/context");
+
+         ResultConfig resultConfig = new ResultConfig.Builder("", "").build();
+
+        Map<String, ResultConfig> results=  new HashMap<String, ResultConfig>();
+        results.put("myResult", resultConfig);
+
+        ActionConfig actionConfig = new ActionConfig.Builder("", "", "")
+                .addResultConfigs(results).build();
+
+        ActionContext ac = new ActionContext(Ognl.createDefaultContext(null));
+        ac.put(ServletActionContext.HTTP_REQUEST, requestMock.proxy());
+        ac.put(ServletActionContext.HTTP_RESPONSE, responseMock.proxy());
+        MockActionInvocation ai = new MockActionInvocation();
+        ai.setInvocationContext(ac);
+        ai.setResultCode("myResult");
+        ActionProxy mockActionProxy = createNiceMock(ActionProxy.class);
+        ai.setProxy(mockActionProxy);
+        expect(mockActionProxy.getConfig()).andReturn(actionConfig).anyTimes();
+        replay(mockActionProxy);
+        this.ai = ai;
+        ai.setStack(ActionContext.getContext().getValueStack());
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/result/StreamResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/result/StreamResultTest.java b/core/src/test/java/org/apache/struts2/result/StreamResultTest.java
new file mode 100644
index 0000000..fbb2525
--- /dev/null
+++ b/core/src/test/java/org/apache/struts2/result/StreamResultTest.java
@@ -0,0 +1,277 @@
+/*
+ * $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.result;
+
+import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.mock.MockActionInvocation;
+import com.opensymphony.xwork2.util.ClassLoaderUtil;
+import com.opensymphony.xwork2.util.ValueStack;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsInternalTestCase;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+
+/**
+ * Unit test for {@link StreamResult}.
+ *
+ */
+public class StreamResultTest extends StrutsInternalTestCase {
+
+    private StreamResult result;
+    private MockHttpServletResponse response;
+
+    private MockActionInvocation mai;
+    private ValueStack stack;
+    private int contentLength = 0;
+
+    public void testStreamResultNoInputName() throws Exception {
+        result.setParse(false);
+        result.setInputName(null);
+
+        try {
+            result.doExecute("helloworld", mai);
+            fail("Should have thrown an IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // success
+        }
+    }
+
+    public void testStreamResultParseNoInputName() throws Exception {
+        result.setParse(true);
+        result.setInputName("${top}");
+
+        try {
+            result.doExecute("helloworld", mai);
+            fail("Should have thrown an IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // success
+        }
+    }
+
+    public void testStreamResultDefault() throws Exception {
+        result.setInputName("streamForImage");
+
+        result.doExecute("helloworld", mai);
+
+        assertEquals(String.valueOf(contentLength), result.getContentLength());
+        assertEquals("text/plain", result.getContentType());
+        assertEquals("streamForImage", result.getInputName());
+        assertEquals(1024, result.getBufferSize()); // 1024 is default
+        assertEquals("inline", result.getContentDisposition());
+
+        assertEquals("text/plain", response.getContentType());
+        assertEquals(contentLength, response.getContentLength());
+        assertEquals("inline", response.getHeader("Content-disposition"));
+    }
+
+    public void testStreamResultWithCharSet() throws Exception {
+        result.setInputName("streamForImage");
+        result.setContentCharSet("ISO-8859-1");
+        result.doExecute("helloworld", mai);
+
+        assertEquals(String.valueOf(contentLength), result.getContentLength());
+        assertEquals("text/plain", result.getContentType());
+        assertEquals("streamForImage", result.getInputName());
+        assertEquals(1024, result.getBufferSize()); // 1024 is default
+        assertEquals("inline", result.getContentDisposition());
+        assertEquals("text/plain;charset=ISO-8859-1", response.getContentType());
+        assertEquals(contentLength, response.getContentLength());
+        assertEquals("inline", response.getHeader("Content-disposition"));
+    }
+
+    public void testStreamResultWithCharSet2() throws Exception {
+        result.setParse(true);
+        result.setInputName("streamForImage");
+        result.setContentCharSet("${contentCharSetMethod}");
+
+        result.doExecute("helloworld", mai);
+
+        assertEquals(String.valueOf(contentLength), result.getContentLength());
+        assertEquals("text/plain", result.getContentType());
+        assertEquals("streamForImage", result.getInputName());
+        assertEquals(1024, result.getBufferSize()); // 1024 is default
+        assertEquals("inline", result.getContentDisposition());
+        assertEquals("text/plain;charset=UTF-8", response.getContentType());
+        assertEquals(contentLength, response.getContentLength());
+        assertEquals("inline", response.getHeader("Content-disposition"));
+    }
+
+    public void testAllowCacheDefault() throws Exception {
+        result.setInputName("streamForImage");
+
+        result.doExecute("helloworld", mai);
+
+        //check that that headers are not set by default        
+        assertNull(response.getHeader("Pragma"));
+        assertNull(response.getHeader("Cache-Control"));
+    }
+
+     public void testAllowCacheFalse() throws Exception {
+        result.setInputName("streamForImage");
+        result.setAllowCaching(false);
+        result.doExecute("helloworld", mai);
+
+        //check that that headers are not set by default
+        assertEquals("no-cache", response.getHeader("Pragma"));
+        assertEquals("no-cache", response.getHeader("Cache-Control"));
+    }
+
+    public void testStreamResultNoDefault() throws Exception {
+        // it's not easy to test using easymock as we use getOutputStream on HttpServletResponse.
+        result.setParse(false);
+        result.setInputName("streamForImage");
+        result.setBufferSize(128);
+        result.setContentLength(String.valueOf(contentLength));
+        result.setContentDisposition("filename=\"logo.png\"");
+        result.setContentType("image/jpeg");
+
+        result.doExecute("helloworld", mai);
+
+        assertEquals(String.valueOf(contentLength), result.getContentLength());
+        assertEquals("image/jpeg", result.getContentType());
+        assertEquals("streamForImage", result.getInputName());
+        assertEquals(128, result.getBufferSize());
+        assertEquals("filename=\"logo.png\"", result.getContentDisposition());
+
+        assertEquals("image/jpeg", response.getContentType());
+        assertEquals(contentLength, response.getContentLength());
+        assertEquals("filename=\"logo.png\"", response.getHeader("Content-disposition"));
+    }
+
+    public void testStreamResultParse1() throws Exception {
+        ///////////////////
+        result.setParse(true);
+        // ${...} conditionalParse of Result, returns String,
+        // which gets evaluated to the stack, that's how it works.
+        // We use ${streamForImageAsString} that returns "streamForImage"
+        // which is a property that returns an InputStream object.
+        result.setInputName("${streamForImageAsString}");
+        result.setBufferSize(128);
+        result.setContentLength(String.valueOf(contentLength));
+        result.setContentDisposition("filename=\"logo.png\"");
+        result.setContentType("image/jpeg");
+
+        result.doExecute("helloworld", mai);
+
+        assertEquals(String.valueOf(contentLength), result.getContentLength());
+        assertEquals("image/jpeg", result.getContentType());
+        assertEquals("${streamForImageAsString}", result.getInputName());
+        assertEquals(128, result.getBufferSize());
+        assertEquals("filename=\"logo.png\"", result.getContentDisposition());
+
+        assertEquals("image/jpeg", response.getContentType());
+        assertEquals(contentLength, response.getContentLength());
+        assertEquals("filename=\"logo.png\"", response.getHeader("Content-disposition"));
+    }
+
+    public void testStreamResultParse2() throws Exception {
+        ///////////////////
+        result.setParse(true);
+        // This time we dun use ${...}, so streamForImage will
+        // be evaluated to the stack, which should reaturn an
+        // InputStream object, cause there's such a property in
+        // the action object itself.
+        result.setInputName("streamForImage");
+        result.setBufferSize(128);
+        result.setContentLength(String.valueOf(contentLength));
+        result.setContentDisposition("filename=\"logo.png\"");
+        result.setContentType("image/jpeg");
+
+        result.doExecute("helloworld", mai);
+
+        assertEquals(String.valueOf(contentLength), result.getContentLength());
+        assertEquals("image/jpeg", result.getContentType());
+        assertEquals("streamForImage", result.getInputName());
+        assertEquals(128, result.getBufferSize());
+        assertEquals("filename=\"logo.png\"", result.getContentDisposition());
+
+        assertEquals("image/jpeg", response.getContentType());
+        assertEquals(contentLength, response.getContentLength());
+        assertEquals("filename=\"logo.png\"", response.getHeader("Content-disposition"));
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        response = new MockHttpServletResponse();
+
+        result = new StreamResult();
+        stack = ActionContext.getContext().getValueStack();
+
+        MyImageAction action = new MyImageAction();
+        contentLength = (int) action.getContentLength();
+
+        mai = new com.opensymphony.xwork2.mock.MockActionInvocation();
+        mai.setAction(action);
+        mai.setStack(stack);
+        mai.setInvocationContext(ActionContext.getContext());
+        stack.push(action);
+
+        ActionContext.getContext().put(ServletActionContext.HTTP_RESPONSE, response);
+    }
+
+
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        response = null;
+        result = null;
+        stack = null;
+        contentLength = 0;
+        mai = null;
+    }
+
+    public class MyImageAction implements Action {
+
+        public InputStream getStreamForImage() throws Exception {
+            // just use src/test/log4j2.xml as test file
+            URL url = ClassLoaderUtil.getResource("log4j2.xml", StreamResultTest.class);
+            File file = new File(new URI(url.toString()));
+            FileInputStream fis = new FileInputStream(file);
+            return fis;
+        }
+
+        public String execute() throws Exception {
+            return SUCCESS;
+        }
+
+        public long getContentLength() throws Exception {
+            URL url = ClassLoaderUtil.getResource("log4j2.xml", StreamResultTest.class);
+            File file = new File(new URI(url.toString()));
+            return file.length();
+        }
+
+        public String getStreamForImageAsString() {
+            return "streamForImage";
+        }
+
+        public String getContentCharSetMethod() {
+            return "UTF-8";
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/result/StrutsResultSupportTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/result/StrutsResultSupportTest.java b/core/src/test/java/org/apache/struts2/result/StrutsResultSupportTest.java
new file mode 100644
index 0000000..6a8f90a
--- /dev/null
+++ b/core/src/test/java/org/apache/struts2/result/StrutsResultSupportTest.java
@@ -0,0 +1,156 @@
+/*
+ * $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.result;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.struts2.StrutsInternalTestCase;
+import org.apache.struts2.result.StrutsResultSupport;
+import org.easymock.EasyMock;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.util.ValueStack;
+
+/**
+ * Test case for StrutsResultSupport.
+ */
+public class StrutsResultSupportTest extends StrutsInternalTestCase {
+
+
+    public void testParse() throws Exception {
+        ValueStack stack = ActionContext.getContext().getValueStack();
+        stack.push(new ActionSupport() {
+            public String getMyLocation() {
+                return "ThisIsMyLocation";
+            }
+        });
+
+        ActionInvocation mockActionInvocation = EasyMock.createNiceMock(ActionInvocation.class);
+        mockActionInvocation.getStack();
+        EasyMock.expectLastCall().andReturn(stack);
+        EasyMock.replay(mockActionInvocation);
+
+        InternalStrutsResultSupport result = new InternalStrutsResultSupport();
+        result.setParse(true);
+        result.setEncode(false);
+        result.setLocation("/pages/myJsp.jsp?location=${myLocation}");
+
+        result.execute(mockActionInvocation);
+
+        assertNotNull(result.getInternalLocation());
+        assertEquals("/pages/myJsp.jsp?location=ThisIsMyLocation", result.getInternalLocation());
+        EasyMock.verify(mockActionInvocation);
+    }
+
+    public void testParseAndEncode() throws Exception {
+        ValueStack stack = ActionContext.getContext().getValueStack();
+        stack.push(new ActionSupport() {
+            public String getMyLocation() {
+                return "/myPage?param=value&param1=value1";
+            }
+        });
+
+        ActionInvocation mockActionInvocation = EasyMock.createNiceMock(ActionInvocation.class);
+        mockActionInvocation.getStack();
+        EasyMock.expectLastCall().andReturn(stack);
+        EasyMock.replay(mockActionInvocation);
+
+        InternalStrutsResultSupport result = new InternalStrutsResultSupport();
+        result.setParse(true);
+        result.setEncode(true);
+        result.setLocation("/pages/myJsp.jsp?location=${myLocation}");
+
+        result.execute(mockActionInvocation);
+
+        assertNotNull(result.getInternalLocation());
+        assertEquals("/pages/myJsp.jsp?location=%2FmyPage%3Fparam%3Dvalue%26param1%3Dvalue1", result.getInternalLocation());
+        EasyMock.verify(mockActionInvocation);
+    }
+
+
+    public void testNoParseAndEncode() throws Exception {
+        ValueStack stack = ActionContext.getContext().getValueStack();
+        stack.push(new ActionSupport() {
+            public String getMyLocation() {
+                return "myLocation.jsp";
+            }
+        });
+
+        ActionInvocation mockActionInvocation = EasyMock.createNiceMock(ActionInvocation.class);
+        EasyMock.replay(mockActionInvocation);
+
+        InternalStrutsResultSupport result = new InternalStrutsResultSupport();
+        result.setParse(false);
+        result.setEncode(false); // don't really need this, as encode is only valid when parse is true.
+        result.setLocation("/pages/myJsp.jsp?location=${myLocation}");
+
+        result.execute(mockActionInvocation);
+
+        assertNotNull(result.getInternalLocation());
+        assertEquals("/pages/myJsp.jsp?location=${myLocation}", result.getInternalLocation());
+        EasyMock.verify(mockActionInvocation);
+    }
+
+    public void testConditionalParseCollection() throws Exception {
+        ValueStack stack = ActionContext.getContext().getValueStack();
+        stack.push(new ActionSupport() {
+            public List<String> getList() {
+                return new ArrayList<String>(){{
+                    add("val 1");
+                    add("val 2");
+                }};
+            }
+        });
+
+        ActionInvocation mockActionInvocation = EasyMock.createNiceMock(ActionInvocation.class);
+        mockActionInvocation.getStack();
+        EasyMock.expectLastCall().andReturn(stack);
+        EasyMock.replay(mockActionInvocation);
+
+        InternalStrutsResultSupport result = new InternalStrutsResultSupport();
+        result.setParse(true);
+        result.setEncode(true);
+
+        Collection<String> collection = result.conditionalParseCollection("${list}", mockActionInvocation, true);
+
+        assertNotNull(collection);
+        assertEquals(2, collection.size());
+        assertTrue(collection.contains("val+1"));
+        assertTrue(collection.contains("val+2"));
+        EasyMock.verify(mockActionInvocation);
+    }
+
+    public static class InternalStrutsResultSupport extends StrutsResultSupport {
+        private String _internalLocation = null;
+
+        protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
+            _internalLocation = finalLocation;
+        }
+
+        public String getInternalLocation() {
+            return _internalLocation;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/result/VelocityResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/result/VelocityResultTest.java b/core/src/test/java/org/apache/struts2/result/VelocityResultTest.java
new file mode 100644
index 0000000..0a945ec
--- /dev/null
+++ b/core/src/test/java/org/apache/struts2/result/VelocityResultTest.java
@@ -0,0 +1,149 @@
+/*
+ * $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.result;
+
+import org.apache.struts2.StrutsInternalTestCase;
+import org.apache.struts2.result.StrutsResultSupport;
+import org.apache.struts2.result.VelocityResult;
+import org.apache.velocity.Template;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.exception.ParseErrorException;
+import org.apache.velocity.exception.ResourceNotFoundException;
+
+import com.mockobjects.dynamic.Mock;
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.ActionProxy;
+import com.opensymphony.xwork2.util.ValueStack;
+
+
+/**
+ *
+ */
+public class VelocityResultTest extends StrutsInternalTestCase {
+
+    ActionInvocation actionInvocation;
+    Mock mockActionProxy;
+    ValueStack stack;
+    String namespace;
+    TestVelocityEngine velocity;
+    VelocityResult result;
+
+
+    public void testCanResolveLocationUsingOgnl() throws Exception {
+        TestResult result = new TestResult();
+
+        String location = "/myaction.action";
+        Bean bean = new Bean();
+        bean.setLocation(location);
+
+        ValueStack stack = ActionContext.getContext().getValueStack();
+        stack.push(bean);
+
+        assertEquals(location, stack.findValue("location"));
+
+        result.setLocation("${location}");
+        result.execute(actionInvocation);
+        assertEquals(location, result.finalLocation);
+    }
+
+    public void testCanResolveLocationUsingStaticExpression() throws Exception {
+        TestResult result = new TestResult();
+        String location = "/any.action";
+        result.setLocation("${'" + location + "'}");
+        result.execute(actionInvocation);
+        assertEquals(location, result.finalLocation);
+    }
+
+    public void testResourcesFoundUsingAbsolutePath() throws Exception {
+        String location = "/WEB-INF/views/registration.vm";
+
+        Template template = result.getTemplate(stack, velocity, actionInvocation, location, "UTF-8");
+        assertNotNull(template);
+        assertEquals("expect absolute locations to be handled as is", location, velocity.templateName);
+    }
+
+    public void testResourcesFoundUsingNames() throws Exception {
+        String location = "Registration.vm";
+        String expectedTemplateName = namespace + "/" + location;
+
+        Template template = result.getTemplate(stack, velocity, actionInvocation, location, "UTF-8");
+        assertNotNull(template);
+        assertEquals("expect the prefix to be appended to the path when the location is not absolute", expectedTemplateName, velocity.templateName);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        namespace = "/html";
+        result = new VelocityResult();
+        stack = ActionContext.getContext().getValueStack();
+        ActionContext.getContext().setValueStack(stack);
+        velocity = new TestVelocityEngine();
+        mockActionProxy = new Mock(ActionProxy.class);
+        mockActionProxy.expectAndReturn("getNamespace", "/html");
+
+        Mock mockActionInvocation = new Mock(ActionInvocation.class);
+        mockActionInvocation.expectAndReturn("getProxy", mockActionProxy.proxy());
+        mockActionInvocation.expectAndReturn("getStack", stack);
+        actionInvocation = (ActionInvocation) mockActionInvocation.proxy();
+    }
+
+
+    class Bean {
+        private String location;
+
+        public void setLocation(String location) {
+            this.location = location;
+        }
+
+        public String getLocation() {
+            return location;
+        }
+    }
+
+    class TestResult extends StrutsResultSupport {
+
+        private static final long serialVersionUID = -1512206785088317315L;
+
+        public String finalLocation;
+
+        protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
+            this.finalLocation = finalLocation;
+        }
+    }
+
+    class TestVelocityEngine extends VelocityEngine {
+        public String templateName;
+
+        public Template getTemplate(String templateName) throws ResourceNotFoundException, ParseErrorException, Exception {
+            this.templateName = templateName;
+
+            return new Template();
+        }
+
+        public Template getTemplate(String templateName, String charSet) throws ResourceNotFoundException, ParseErrorException, Exception {
+            this.templateName = templateName;
+
+            return new Template();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/convention/src/test/java/org/apache/struts2/convention/ConventionUnknownHandlerTest.java
----------------------------------------------------------------------
diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention/ConventionUnknownHandlerTest.java b/plugins/convention/src/test/java/org/apache/struts2/convention/ConventionUnknownHandlerTest.java
index 10733af..ad40e59 100644
--- a/plugins/convention/src/test/java/org/apache/struts2/convention/ConventionUnknownHandlerTest.java
+++ b/plugins/convention/src/test/java/org/apache/struts2/convention/ConventionUnknownHandlerTest.java
@@ -27,7 +27,7 @@ import com.opensymphony.xwork2.config.entities.PackageConfig;
 import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
 import com.opensymphony.xwork2.inject.Container;
 import junit.framework.TestCase;
-import org.apache.struts2.dispatcher.ServletDispatcherResult;
+import org.apache.struts2.result.ServletDispatcherResult;
 import org.easymock.EasyMock;
 
 import javax.servlet.ServletContext;

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/convention/src/test/java/org/apache/struts2/convention/DefaultResultMapBuilderTest.java
----------------------------------------------------------------------
diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention/DefaultResultMapBuilderTest.java b/plugins/convention/src/test/java/org/apache/struts2/convention/DefaultResultMapBuilderTest.java
index 502b202..abda7b3 100644
--- a/plugins/convention/src/test/java/org/apache/struts2/convention/DefaultResultMapBuilderTest.java
+++ b/plugins/convention/src/test/java/org/apache/struts2/convention/DefaultResultMapBuilderTest.java
@@ -29,7 +29,7 @@ import org.apache.struts2.convention.actions.NoAnnotationAction;
 import org.apache.struts2.convention.actions.result.*;
 import org.apache.struts2.convention.actions.resultpath.ClassLevelResultPathAction;
 import org.apache.struts2.convention.annotation.Action;
-import org.apache.struts2.dispatcher.ServletDispatcherResult;
+import org.apache.struts2.result.ServletDispatcherResult;
 import org.easymock.EasyMock;
 import org.easymock.IAnswer;
 
@@ -205,7 +205,7 @@ public class DefaultResultMapBuilderTest extends TestCase {
         assertEquals(4, results.size());
         assertEquals("success", results.get("success").getName());
         assertEquals(3, results.get("success").getParams().size());
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("success").getClassName());
         assertEquals("/WEB-INF/location/namespace/no-annotation-success.jsp", results.get("success").getParams().get("location"));
         assertEquals(1, results.get("input").getParams().size());
         assertEquals("org.apache.struts2.views.freemarker.FreemarkerResult", results.get("input").getClassName());
@@ -214,7 +214,7 @@ public class DefaultResultMapBuilderTest extends TestCase {
         assertEquals("org.apache.struts2.views.freemarker.FreemarkerResult", results.get("error").getClassName());
         assertEquals("/WEB-INF/location/namespace/no-annotation.ftl", results.get("error").getParams().get("location"));
         assertEquals(3, results.get("failure").getParams().size());
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("success").getClassName());
         assertEquals("/WEB-INF/location/namespace/no-annotation-failure.jsp", results.get("failure").getParams().get("location"));
         EasyMock.verify(context);
 
@@ -243,7 +243,7 @@ public class DefaultResultMapBuilderTest extends TestCase {
 
         assertEquals("success", results.get("success").getName());
         assertEquals(3, results.get("success").getParams().size());
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("success").getClassName());
         assertEquals("/WEB-INF/location/namespace/no-annotation/success.jsp", results.get("success").getParams().get("location"));
 
         assertEquals(1, results.get("index").getParams().size());
@@ -251,7 +251,7 @@ public class DefaultResultMapBuilderTest extends TestCase {
         assertEquals("/WEB-INF/location/namespace/no-annotation/index.ftl", results.get("index").getParams().get("location"));
 
         assertEquals(3, results.get("failure").getParams().size());
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("success").getClassName());
         assertEquals("/WEB-INF/location/namespace/no-annotation/failure.jsp", results.get("failure").getParams().get("location"));
         EasyMock.verify(context);
     }
@@ -274,7 +274,7 @@ public class DefaultResultMapBuilderTest extends TestCase {
         assertEquals(1, results.size());
         assertEquals("success", results.get("success").getName());
         assertEquals(3, results.get("success").getParams().size());
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("success").getClassName());
         assertEquals("/WEB-INF/location/namespace/no-annotation-success.jsp", results.get("success").getParams().get("location"));
         EasyMock.verify(context);
 
@@ -296,7 +296,7 @@ public class DefaultResultMapBuilderTest extends TestCase {
         assertEquals(1, results.size());
         assertEquals("error", results.get("error").getName());
         assertEquals(3, results.get("error").getParams().size());
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("error").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("error").getClassName());
         assertEquals("/WEB-INF/location/namespace/error.jsp", results.get("error").getParams().get("location"));
         assertEquals("value", results.get("error").getParams().get("key"));
         assertEquals("value1", results.get("error").getParams().get("key1"));
@@ -319,7 +319,7 @@ public class DefaultResultMapBuilderTest extends TestCase {
         assertEquals(1, results.size());
         assertEquals("error", results.get("error").getName());
         assertEquals(3, results.get("error").getParams().size());
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("error").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("error").getClassName());
         assertEquals("/WEB-INF/location/namespace/error.jsp", results.get("error").getParams().get("location"));
         assertEquals("value", results.get("error").getParams().get("key"));
         assertEquals("value1", results.get("error").getParams().get("key1"));
@@ -342,7 +342,7 @@ public class DefaultResultMapBuilderTest extends TestCase {
         assertEquals(1, results.size());
         assertEquals("error", results.get("error").getName());
         assertEquals(5, results.get("error").getParams().size());
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("error").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("error").getClassName());
         assertEquals("/WEB-INF/location/namespace/error.jsp", results.get("error").getParams().get("location"));
         assertEquals("value", results.get("error").getParams().get("key"));
         assertEquals("value1", results.get("error").getParams().get("key1"));
@@ -370,21 +370,21 @@ public class DefaultResultMapBuilderTest extends TestCase {
         assertEquals("success", results.get("success").getName());
         assertEquals("failure", results.get("failure").getName());
         assertEquals(3, results.get("error").getParams().size());
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("error").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("error").getClassName());
         assertEquals("/WEB-INF/location/namespace/error.jsp", results.get("error").getParams().get("location"));
         assertEquals("ann-value", results.get("error").getParams().get("key"));
         assertEquals("ann-value1", results.get("error").getParams().get("key1"));
         assertEquals(1, results.get("input").getParams().size());
         assertEquals("foo.action", results.get("input").getParams().get("actionName"));
-        assertEquals("org.apache.struts2.dispatcher.ServletActionRedirectResult", results.get("input").getClassName());
+        assertEquals("org.apache.struts2.result.ServletActionRedirectResult", results.get("input").getClassName());
         assertEquals(3, results.get("failure").getParams().size());
         assertEquals("/WEB-INF/location/namespace/action-failure.jsp", results.get("failure").getParams().get("location"));
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("failure").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("failure").getClassName());
         assertEquals("value", results.get("failure").getParams().get("key"));
         assertEquals("value1", results.get("failure").getParams().get("key1"));
         assertEquals(3, results.get("success").getParams().size());
         assertEquals("/WEB-INF/location/namespace/action-success.jsp", results.get("success").getParams().get("location"));
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("success").getClassName());
         assertEquals("value", results.get("success").getParams().get("key"));
         assertEquals("value1", results.get("success").getParams().get("key1"));
         EasyMock.verify(context);
@@ -409,21 +409,21 @@ public class DefaultResultMapBuilderTest extends TestCase {
         assertEquals("success", results.get("success").getName());
         assertEquals("failure", results.get("failure").getName());
         assertEquals(3, results.get("error").getParams().size());
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("error").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("error").getClassName());
         assertEquals("/WEB-INF/location/namespace/error.jsp", results.get("error").getParams().get("location"));
         assertEquals("ann-value", results.get("error").getParams().get("key"));
         assertEquals("ann-value1", results.get("error").getParams().get("key1"));
         assertEquals(1, results.get("input").getParams().size());
         assertEquals("foo.action", results.get("input").getParams().get("actionName"));
-        assertEquals("org.apache.struts2.dispatcher.ServletActionRedirectResult", results.get("input").getClassName());
+        assertEquals("org.apache.struts2.result.ServletActionRedirectResult", results.get("input").getClassName());
         assertEquals(3, results.get("failure").getParams().size());
         assertEquals("/WEB-INF/location/namespace/action-failure.jsp", results.get("failure").getParams().get("location"));
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("failure").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("failure").getClassName());
         assertEquals("value", results.get("failure").getParams().get("key"));
         assertEquals("value1", results.get("failure").getParams().get("key1"));
         assertEquals(3, results.get("success").getParams().size());
         assertEquals("/WEB-INF/location/namespace/action-success.jsp", results.get("success").getParams().get("location"));
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("success").getClassName());
         assertEquals("value", results.get("success").getParams().get("key"));
         assertEquals("value1", results.get("success").getParams().get("key1"));
         EasyMock.verify(context);
@@ -445,7 +445,7 @@ public class DefaultResultMapBuilderTest extends TestCase {
         assertEquals(1, results.size());
         assertEquals("success", results.get("success").getName());
         assertEquals(3, results.get("success").getParams().size());
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("success").getClassName());
         assertEquals("/WEB-INF/location/namespace/action-success.jsp", results.get("success").getParams().get("location"));
         assertEquals("value", results.get("success").getParams().get("key"));
         assertEquals("value1", results.get("success").getParams().get("key1"));
@@ -471,26 +471,26 @@ public class DefaultResultMapBuilderTest extends TestCase {
         assertEquals("success", results.get("success").getName());
         assertEquals("failure", results.get("failure").getName());
         assertEquals(3, results.get("error").getParams().size());
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("error").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("error").getClassName());
         assertEquals("/WEB-INF/location/namespace/error.jsp", results.get("error").getParams().get("location"));
         assertEquals("value", results.get("success").getParams().get("key"));
         assertEquals("value1", results.get("success").getParams().get("key1"));
         assertEquals(1, results.get("input").getParams().size());
         assertEquals("foo.action", results.get("input").getParams().get("actionName"));
-        assertEquals("org.apache.struts2.dispatcher.ServletActionRedirectResult", results.get("input").getClassName());
+        assertEquals("org.apache.struts2.result.ServletActionRedirectResult", results.get("input").getClassName());
         assertEquals(3, results.get("failure").getParams().size());
         assertEquals("/WEB-INF/location/namespace/action-failure.jsp", results.get("failure").getParams().get("location"));
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("failure").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("failure").getClassName());
         assertEquals(3, results.get("success").getParams().size());
         assertEquals("/WEB-INF/location/namespace/action-success.jsp", results.get("success").getParams().get("location"));
-        assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
+        assertEquals("org.apache.struts2.result.ServletDispatcherResult", results.get("success").getClassName());
         EasyMock.verify(context);
     }
 
     public void testClassPath() throws Exception {
         ServletContext context = EasyMock.createNiceMock(ServletContext.class);
 
-        ResultTypeConfig resultType = new ResultTypeConfig.Builder("freemarker", "org.apache.struts2.dispatcher.ServletDispatcherResult").
+        ResultTypeConfig resultType = new ResultTypeConfig.Builder("freemarker", "org.apache.struts2.result.ServletDispatcherResult").
                 defaultResultParam("location").build();
         PackageConfig packageConfig = new PackageConfig.Builder("package").
                 defaultResultType("dispatcher").addResultTypeConfig(resultType).build();
@@ -514,11 +514,11 @@ public class DefaultResultMapBuilderTest extends TestCase {
     }
 
     private PackageConfig createPackageConfigBuilder(String namespace) {
-        ResultTypeConfig resultType = new ResultTypeConfig.Builder("dispatcher", "org.apache.struts2.dispatcher.ServletDispatcherResult").
+        ResultTypeConfig resultType = new ResultTypeConfig.Builder("dispatcher", "org.apache.struts2.result.ServletDispatcherResult").
                 addParam("key", "value").addParam("key1", "value1").defaultResultParam("location").build();
 
         ResultTypeConfig redirect = new ResultTypeConfig.Builder("redirectAction",
-                "org.apache.struts2.dispatcher.ServletActionRedirectResult").defaultResultParam("actionName").build();
+                "org.apache.struts2.result.ServletActionRedirectResult").defaultResultParam("actionName").build();
 
         ResultTypeConfig ftlResultType = new ResultTypeConfig.Builder("freemarker",
                 "org.apache.struts2.views.freemarker.FreemarkerResult").defaultResultParam("location").build();

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
----------------------------------------------------------------------
diff --git a/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java b/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
index 7fbd420..38403a0 100644
--- a/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
+++ b/plugins/convention/src/test/java/org/apache/struts2/convention/PackageBasedActionConfigBuilderTest.java
@@ -65,7 +65,7 @@ import org.apache.struts2.convention.actions.transactions.TransNameAction;
 import org.apache.struts2.convention.annotation.Action;
 import org.apache.struts2.convention.annotation.Actions;
 import org.apache.struts2.convention.dontfind.DontFindMeAction;
-import org.apache.struts2.dispatcher.ServletDispatcherResult;
+import org.apache.struts2.result.ServletDispatcherResult;
 import org.easymock.EasyMock;
 
 import javax.servlet.ServletContext;

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/embeddedjsp/src/main/java/org/apache/struts2/EmbeddedJSPResult.java
----------------------------------------------------------------------
diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/EmbeddedJSPResult.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/EmbeddedJSPResult.java
index c402cb5..7be0910 100644
--- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/EmbeddedJSPResult.java
+++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/EmbeddedJSPResult.java
@@ -22,7 +22,7 @@ package org.apache.struts2;
 
 import com.opensymphony.xwork2.ActionInvocation;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.struts2.dispatcher.StrutsResultSupport;
+import org.apache.struts2.result.StrutsResultSupport;
 
 /**
  * Can render jsps from the classpath. "includes" in the jsps must not use relative paths

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/JasperReportsResult.java
----------------------------------------------------------------------
diff --git a/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/JasperReportsResult.java b/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/JasperReportsResult.java
index 56cd4b0..a8492af 100644
--- a/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/JasperReportsResult.java
+++ b/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/JasperReportsResult.java
@@ -32,11 +32,10 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.dispatcher.StrutsResultSupport;
+import org.apache.struts2.result.StrutsResultSupport;
 
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
-import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/jfreechart/src/main/java/org/apache/struts2/dispatcher/ChartResult.java
----------------------------------------------------------------------
diff --git a/plugins/jfreechart/src/main/java/org/apache/struts2/dispatcher/ChartResult.java b/plugins/jfreechart/src/main/java/org/apache/struts2/dispatcher/ChartResult.java
index 76c2936..4a1886e 100644
--- a/plugins/jfreechart/src/main/java/org/apache/struts2/dispatcher/ChartResult.java
+++ b/plugins/jfreechart/src/main/java/org/apache/struts2/dispatcher/ChartResult.java
@@ -25,6 +25,7 @@ import org.apache.struts2.ServletActionContext;
 import com.opensymphony.xwork2.ActionInvocation;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.LogManager;
+import org.apache.struts2.result.StrutsResultSupport;
 import org.jfree.chart.ChartUtilities;
 import org.jfree.chart.JFreeChart;
 
@@ -247,4 +248,4 @@ public class ChartResult extends StrutsResultSupport {
         }
     }
 
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/portlet-tiles/src/main/java/org/apache/struts2/views/tiles/PortletTilesResult.java
----------------------------------------------------------------------
diff --git a/plugins/portlet-tiles/src/main/java/org/apache/struts2/views/tiles/PortletTilesResult.java b/plugins/portlet-tiles/src/main/java/org/apache/struts2/views/tiles/PortletTilesResult.java
index c08a99b..d10693c 100644
--- a/plugins/portlet-tiles/src/main/java/org/apache/struts2/views/tiles/PortletTilesResult.java
+++ b/plugins/portlet-tiles/src/main/java/org/apache/struts2/views/tiles/PortletTilesResult.java
@@ -3,7 +3,7 @@ package org.apache.struts2.views.tiles;
 import com.opensymphony.xwork2.ActionInvocation;
 import freemarker.template.TemplateException;
 import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.dispatcher.ServletDispatcherResult;
+import org.apache.struts2.result.ServletDispatcherResult;
 import org.apache.struts2.portlet.PortletConstants;
 import org.apache.struts2.portlet.context.PortletActionContext;
 import org.apache.tiles.TilesContainer;

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletActionRedirectResult.java
----------------------------------------------------------------------
diff --git a/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletActionRedirectResult.java b/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletActionRedirectResult.java
index 04729c1..5ef5a1a 100644
--- a/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletActionRedirectResult.java
+++ b/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletActionRedirectResult.java
@@ -23,7 +23,7 @@ package org.apache.struts2.portlet.result;
 import com.opensymphony.xwork2.ActionInvocation;
 import com.opensymphony.xwork2.config.entities.ResultConfig;
 import com.opensymphony.xwork2.inject.Inject;
-import org.apache.struts2.dispatcher.ServletActionRedirectResult;
+import org.apache.struts2.result.ServletActionRedirectResult;
 import org.apache.struts2.dispatcher.mapper.ActionMapper;
 import org.apache.struts2.dispatcher.mapper.ActionMapping;
 import org.apache.struts2.portlet.PortletConstants;

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletResult.java
----------------------------------------------------------------------
diff --git a/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletResult.java b/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletResult.java
index 7fa2336..50fa223 100644
--- a/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletResult.java
+++ b/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletResult.java
@@ -26,7 +26,7 @@ import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.LogManager;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.dispatcher.StrutsResultSupport;
+import org.apache.struts2.result.StrutsResultSupport;
 import org.apache.struts2.portlet.PortletConstants;
 import org.apache.struts2.portlet.PortletPhase;
 import org.apache.struts2.portlet.context.PortletActionContext;

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletVelocityResult.java
----------------------------------------------------------------------
diff --git a/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletVelocityResult.java b/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletVelocityResult.java
index 2d43c27..ccfec82 100644
--- a/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletVelocityResult.java
+++ b/plugins/portlet/src/main/java/org/apache/struts2/portlet/result/PortletVelocityResult.java
@@ -28,7 +28,7 @@ import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.LogManager;
 import org.apache.struts2.ServletActionContext;
 import org.apache.struts2.StrutsConstants;
-import org.apache.struts2.dispatcher.StrutsResultSupport;
+import org.apache.struts2.result.StrutsResultSupport;
 import org.apache.struts2.portlet.PortletConstants;
 import org.apache.struts2.portlet.PortletPhase;
 import org.apache.struts2.portlet.context.PortletActionContext;
@@ -115,7 +115,7 @@ public class PortletVelocityResult extends StrutsResultSupport {
     }
 
     /* (non-Javadoc)
-     * @see org.apache.struts2.dispatcher.StrutsResultSupport#doExecute(java.lang.String, com.opensymphony.xwork2.ActionInvocation)
+     * @see org.apache.struts2.result.StrutsResultSupport#doExecute(java.lang.String, com.opensymphony.xwork2.ActionInvocation)
      */
     public void doExecute(String location, ActionInvocation invocation) throws Exception {
         PortletPhase phase = PortletActionContext.getPhase();

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/portlet/src/main/java/org/apache/struts2/views/freemarker/PortletFreemarkerResult.java
----------------------------------------------------------------------
diff --git a/plugins/portlet/src/main/java/org/apache/struts2/views/freemarker/PortletFreemarkerResult.java b/plugins/portlet/src/main/java/org/apache/struts2/views/freemarker/PortletFreemarkerResult.java
index 71d0cee..036bd14 100644
--- a/plugins/portlet/src/main/java/org/apache/struts2/views/freemarker/PortletFreemarkerResult.java
+++ b/plugins/portlet/src/main/java/org/apache/struts2/views/freemarker/PortletFreemarkerResult.java
@@ -30,7 +30,7 @@ import freemarker.template.TemplateException;
 import freemarker.template.TemplateModel;
 import freemarker.template.TemplateModelException;
 import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.dispatcher.StrutsResultSupport;
+import org.apache.struts2.result.StrutsResultSupport;
 import org.apache.struts2.portlet.PortletConstants;
 import org.apache.struts2.portlet.PortletPhase;
 import org.apache.struts2.portlet.context.PortletActionContext;

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionInvocation.java
----------------------------------------------------------------------
diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionInvocation.java b/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionInvocation.java
index 65e6084..c5a687f 100644
--- a/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionInvocation.java
+++ b/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionInvocation.java
@@ -32,7 +32,7 @@ import org.apache.commons.lang3.BooleanUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.dispatcher.HttpHeaderResult;
+import org.apache.struts2.result.HttpHeaderResult;
 import org.apache.struts2.rest.handler.ContentTypeHandler;
 import org.apache.struts2.rest.handler.HtmlHandler;
 

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/rest/src/main/resources/struts-plugin.xml
----------------------------------------------------------------------
diff --git a/plugins/rest/src/main/resources/struts-plugin.xml b/plugins/rest/src/main/resources/struts-plugin.xml
index 1e95d4eaf..0f0937e 100644
--- a/plugins/rest/src/main/resources/struts-plugin.xml
+++ b/plugins/rest/src/main/resources/struts-plugin.xml
@@ -48,10 +48,10 @@
 
     <package name="rest-default" extends="struts-default">
         <result-types>
-            <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult">
+            <result-type name="redirect" class="org.apache.struts2.result.ServletRedirectResult">
                 <param name="statusCode">303</param>
             </result-type>
-            <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult">
+            <result-type name="redirectAction" class="org.apache.struts2.result.ServletActionRedirectResult">
                 <param name="statusCode">303</param>
             </result-type>
         </result-types>

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionInvocationTest.java
----------------------------------------------------------------------
diff --git a/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionInvocationTest.java b/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionInvocationTest.java
index 6db05f1..1ebdc94 100644
--- a/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionInvocationTest.java
+++ b/plugins/rest/src/test/java/org/apache/struts2/rest/RestActionInvocationTest.java
@@ -14,7 +14,7 @@ import com.opensymphony.xwork2.ognl.OgnlUtil;
 import com.opensymphony.xwork2.util.XWorkTestCaseHelper;
 import junit.framework.TestCase;
 import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.dispatcher.HttpHeaderResult;
+import org.apache.struts2.result.HttpHeaderResult;
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
 
@@ -174,7 +174,7 @@ public class RestActionInvocationTest extends TestCase {
 		
 		restActionInvocation.setDefaultErrorResultName("default-error");
 		ResultConfig resultConfig = new ResultConfig.Builder("default-error", 
-			"org.apache.struts2.dispatcher.HttpHeaderResult")
+			"org.apache.struts2.result.HttpHeaderResult")
 	    	.addParam("status", "123").build();
 	    ActionConfig actionConfig = new ActionConfig.Builder("org.apache.rest", 
 				"RestAction", "org.apache.rest.RestAction")
@@ -219,7 +219,7 @@ public class RestActionInvocationTest extends TestCase {
 
 	    // Define result 'success'
 		ResultConfig resultConfig = new ResultConfig.Builder("success", 
-			"org.apache.struts2.dispatcher.HttpHeaderResult")
+			"org.apache.struts2.result.HttpHeaderResult")
 	    	.addParam("status", "123").build();
 	    ActionConfig actionConfig = new ActionConfig.Builder("org.apache.rest", 
 				"RestAction", "org.apache.rest.RestAction")

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java
----------------------------------------------------------------------
diff --git a/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java b/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java
index 6135302..490de79 100644
--- a/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java
+++ b/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java
@@ -26,7 +26,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.dispatcher.ServletDispatcherResult;
+import org.apache.struts2.result.ServletDispatcherResult;
 import org.apache.tiles.TilesContainer;
 import org.apache.tiles.access.TilesAccess;
 

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/plugins/tiles3/src/main/java/org/apache/struts2/views/tiles/TilesResult.java
----------------------------------------------------------------------
diff --git a/plugins/tiles3/src/main/java/org/apache/struts2/views/tiles/TilesResult.java b/plugins/tiles3/src/main/java/org/apache/struts2/views/tiles/TilesResult.java
index a774edb..6bc15bb 100644
--- a/plugins/tiles3/src/main/java/org/apache/struts2/views/tiles/TilesResult.java
+++ b/plugins/tiles3/src/main/java/org/apache/struts2/views/tiles/TilesResult.java
@@ -23,7 +23,7 @@ package org.apache.struts2.views.tiles;
 
 import com.opensymphony.xwork2.ActionInvocation;
 import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.dispatcher.ServletDispatcherResult;
+import org.apache.struts2.result.ServletDispatcherResult;
 import org.apache.tiles.TilesContainer;
 import org.apache.tiles.access.TilesAccess;
 import org.apache.tiles.request.ApplicationContext;


[4/4] struts git commit: WW-4518 Moves results to dedicated package

Posted by lu...@apache.org.
WW-4518 Moves results to dedicated package


Project: http://git-wip-us.apache.org/repos/asf/struts/repo
Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/6bc99ab9
Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/6bc99ab9
Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/6bc99ab9

Branch: refs/heads/master
Commit: 6bc99ab9399591b0caac113d95601acda2ca8b69
Parents: 8de090f
Author: Lukasz Lenart <lu...@apache.org>
Authored: Tue Jun 23 17:14:27 2015 +0200
Committer: Lukasz Lenart <lu...@apache.org>
Committed: Tue Jun 23 17:14:27 2015 +0200

----------------------------------------------------------------------
 .../src/main/webapp/WEB-INF/decorators/main.jsp |   5 +-
 .../struts2/dispatcher/HttpHeaderResult.java    | 210 -----------
 .../struts2/dispatcher/PlainTextResult.java     | 183 ----------
 .../struts2/dispatcher/PostbackResult.java      | 232 ------------
 .../dispatcher/ServletActionRedirectResult.java | 227 ------------
 .../dispatcher/ServletDispatcherResult.java     | 174 ---------
 .../dispatcher/ServletRedirectResult.java       | 322 -----------------
 .../apache/struts2/dispatcher/StreamResult.java | 329 -----------------
 .../struts2/dispatcher/StrutsResultSupport.java | 266 --------------
 .../struts2/dispatcher/VelocityResult.java      | 233 ------------
 .../interceptor/MessageStoreInterceptor.java    |   2 +-
 .../apache/struts2/result/HttpHeaderResult.java | 210 +++++++++++
 .../apache/struts2/result/PlainTextResult.java  | 183 ++++++++++
 .../apache/struts2/result/PostbackResult.java   | 232 ++++++++++++
 .../result/ServletActionRedirectResult.java     | 227 ++++++++++++
 .../struts2/result/ServletDispatcherResult.java | 174 +++++++++
 .../struts2/result/ServletRedirectResult.java   | 323 +++++++++++++++++
 .../org/apache/struts2/result/StreamResult.java | 329 +++++++++++++++++
 .../struts2/result/StrutsResultSupport.java     | 266 ++++++++++++++
 .../apache/struts2/result/VelocityResult.java   | 233 ++++++++++++
 .../views/freemarker/FreemarkerResult.java      |   2 +-
 core/src/main/resources/struts-default.xml      |  16 +-
 .../struts2/TestConfigurationProvider.java      |   2 +-
 .../dispatcher/HttpHeaderResultTest.java        | 133 -------
 .../struts2/dispatcher/PlainTextResultTest.java | 156 --------
 .../ServletActionRedirectResultTest.java        | 188 ----------
 .../dispatcher/ServletDispatcherResultTest.java | 109 ------
 .../dispatcher/ServletRedirectResultTest.java   | 360 ------------------
 .../struts2/dispatcher/StreamResultTest.java    | 277 --------------
 .../dispatcher/StrutsResultSupportTest.java     | 155 --------
 .../struts2/dispatcher/VelocityResultTest.java  | 147 --------
 .../mapper/DefaultActionMapperTest.java         |   2 +-
 .../MessageStoreInterceptorTest.java            |   2 +-
 .../struts2/result/HttpHeaderResultTest.java    | 134 +++++++
 .../struts2/result/PlainTextResultTest.java     | 156 ++++++++
 .../result/ServletActionRedirectResultTest.java | 189 ++++++++++
 .../result/ServletDispatcherResultTest.java     | 110 ++++++
 .../result/ServletRedirectResultTest.java       | 361 +++++++++++++++++++
 .../apache/struts2/result/StreamResultTest.java | 277 ++++++++++++++
 .../struts2/result/StrutsResultSupportTest.java | 156 ++++++++
 .../struts2/result/VelocityResultTest.java      | 149 ++++++++
 .../ConventionUnknownHandlerTest.java           |   2 +-
 .../convention/DefaultResultMapBuilderTest.java |  50 +--
 .../PackageBasedActionConfigBuilderTest.java    |   2 +-
 .../org/apache/struts2/EmbeddedJSPResult.java   |   2 +-
 .../jasperreports/JasperReportsResult.java      |   3 +-
 .../apache/struts2/dispatcher/ChartResult.java  |   3 +-
 .../struts2/views/tiles/PortletTilesResult.java |   2 +-
 .../result/PortletActionRedirectResult.java     |   2 +-
 .../struts2/portlet/result/PortletResult.java   |   2 +-
 .../portlet/result/PortletVelocityResult.java   |   4 +-
 .../freemarker/PortletFreemarkerResult.java     |   2 +-
 .../struts2/rest/RestActionInvocation.java      |   2 +-
 .../rest/src/main/resources/struts-plugin.xml   |   4 +-
 .../struts2/rest/RestActionInvocationTest.java  |   6 +-
 .../apache/struts2/views/tiles/TilesResult.java |   2 +-
 .../apache/struts2/views/tiles/TilesResult.java |   2 +-
 57 files changed, 3770 insertions(+), 3761 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
----------------------------------------------------------------------
diff --git a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
index d4a6187..22ffc60 100644
--- a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
+++ b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
@@ -1,3 +1,4 @@
+<%@ page import="org.apache.struts2.result.StrutsResultSupport" %>
 <!DOCTYPE html>
 <%@ page
         language="java"
@@ -21,8 +22,8 @@
         }
         sourceUrl += "&className=" + inv.getProxy().getConfig().getClassName();
 
-        if (inv.getResult() != null && inv.getResult() instanceof org.apache.struts2.dispatcher.StrutsResultSupport) {
-            sourceUrl += "&page=" + mapping.getNamespace() + "/" + ((org.apache.struts2.dispatcher.StrutsResultSupport) inv.getResult()).getLastFinalLocation();
+        if (inv.getResult() != null && inv.getResult() instanceof StrutsResultSupport) {
+            sourceUrl += "&page=" + mapping.getNamespace() + "/" + ((StrutsResultSupport) inv.getResult()).getLastFinalLocation();
         }
     } else {
         sourceUrl += "?page=" + request.getServletPath();

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/dispatcher/HttpHeaderResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/dispatcher/HttpHeaderResult.java b/core/src/main/java/org/apache/struts2/dispatcher/HttpHeaderResult.java
deleted file mode 100644
index 3613502..0000000
--- a/core/src/main/java/org/apache/struts2/dispatcher/HttpHeaderResult.java
+++ /dev/null
@@ -1,210 +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.dispatcher;
-
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.Result;
-import com.opensymphony.xwork2.util.TextParseUtil;
-import com.opensymphony.xwork2.util.ValueStack;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.struts2.ServletActionContext;
-
-import javax.servlet.http.HttpServletResponse;
-import java.util.HashMap;
-import java.util.Map;
-
-
-/**
- * <!-- START SNIPPET: description -->
- * <p/>
- * A custom Result type for setting HTTP headers and status by optionally evaluating against the ValueStack.
- * This result can also be used to send and error to the client. All the parameters can be evaluated against the ValueStack.
- * <p/>
- * <!-- END SNIPPET: description -->
- * <p/>
- * <b>This result type takes the following parameters:</b>
- * <p/>
- * <!-- START SNIPPET: params -->
- * <p/>
- * <ul>
- * <p/>
- * <li><b>status</b> - the http servlet response status code that should be set on a response.</li>
- * <p/>
- * <li><b>parse</b> - true by default. If set to false, the headers param will not be parsed for Ognl expressions.</li>
- * <p/>
- * <li><b>headers</b> - header values.</li>
- * <p/>
- * <li><b>error</b> - the http servlet response error code that should be set on a response.</li>
- * <p/>
- * <li><b>errorMessage</b> - error message to be set on response if 'error' is set.</li>
- * </ul>
- * <p/>
- * <!-- END SNIPPET: params -->
- * <p/>
- * <b>Example:</b>
- * <p/>
- * <pre><!-- START SNIPPET: example -->
- * &lt;result name="success" type="httpheader"&gt;
- *   &lt;param name="status"&gt;204&lt;/param&gt;
- *   &lt;param name="headers.a"&gt;a custom header value&lt;/param&gt;
- *   &lt;param name="headers.b"&gt;another custom header value&lt;/param&gt;
- * &lt;/result&gt;
- * <p/>
- * &lt;result name="proxyRequired" type="httpheader"&gt;
- *   &lt;param name="error"&gt;305&lt;/param&gt;
- *   &lt;param name="errorMessage"&gt;this action must be accessed through a prozy&lt;/param&gt;
- * &lt;/result&gt;
- * <!-- END SNIPPET: example --></pre>
- */
-public class HttpHeaderResult implements Result {
-
-    private static final long serialVersionUID = 195648957144219214L;
-    private static final Logger LOG = LogManager.getLogger(HttpHeaderResult.class);
-
-    /**
-     * This result type doesn't have a default param, null is ok to reduce noise in logs
-     */
-    public static final String DEFAULT_PARAM = null;
-
-    private boolean parse = true;
-    private Map<String, String> headers;
-    private int status = -1;
-    private String error = null;
-    private String errorMessage;
-
-    public HttpHeaderResult() {
-        super();
-        headers = new HashMap<>();
-    }
-
-    public HttpHeaderResult(int status) {
-        this();
-        this.status = status;
-        this.parse = false;
-    }
-
-    /**
-     * Sets the http servlet error code that should be set on the response
-     *
-     * @param error the Http error code
-     * @see javax.servlet.http.HttpServletResponse#sendError(int)
-     */
-    public void setError(String error) {
-        this.error = error;
-    }
-
-    /**
-     * Sets the error message that should be set on the reponse
-     *
-     * @param errorMessage error message send to the client
-     * @see javax.servlet.http.HttpServletResponse#sendError(int, String)
-     */
-    public void setErrorMessage(String errorMessage) {
-        this.errorMessage = errorMessage;
-    }
-
-    /**
-     * Returns a Map of all HTTP headers.
-     *
-     * @return a Map of all HTTP headers.
-     */
-    public Map<String, String> getHeaders() {
-        return headers;
-    }
-
-    /**
-     * Sets whether or not the HTTP header values should be evaluated against the ValueStack (by default they are).
-     *
-     * @param parse <tt>true</tt> if HTTP header values should be evaluated against the ValueStack, <tt>false</tt>
-     *              otherwise.
-     */
-    public void setParse(boolean parse) {
-        this.parse = parse;
-    }
-
-    /**
-     * Sets the http servlet response status code that should be set on a response.
-     *
-     * @param status the Http status code
-     * @see javax.servlet.http.HttpServletResponse#setStatus(int)
-     */
-    public void setStatus(int status) {
-        this.status = status;
-    }
-
-    public int getStatus() {
-        return status;
-    }
-
-    /**
-     * Adds an HTTP header to the response
-     *
-     * @param name  header name
-     * @param value header value
-     */
-    public void addHeader(String name, String value) {
-        headers.put(name, value);
-    }
-
-    /**
-     * Sets the optional HTTP response status code and also re-sets HTTP headers after they've
-     * been optionally evaluated against the ValueStack.
-     *
-     * @param invocation an encapsulation of the action execution state.
-     * @throws Exception if an error occurs when re-setting the headers.
-     */
-    public void execute(ActionInvocation invocation) throws Exception {
-        HttpServletResponse response = ServletActionContext.getResponse();
-        ValueStack stack = ActionContext.getContext().getValueStack();
-
-        if (status != -1) {
-            response.setStatus(status);
-        }
-
-        if (headers != null) {
-            for (Map.Entry<String, String> entry : headers.entrySet()) {
-                String value = entry.getValue();
-                String finalValue = parse ? TextParseUtil.translateVariables(value, stack) : value;
-                response.addHeader(entry.getKey(), finalValue);
-            }
-        }
-
-        if (status == -1 && error != null) {
-            int errorCode = -1;
-            try {
-                errorCode = Integer.parseInt(parse ? TextParseUtil.translateVariables(error, stack) : error);
-            } catch (Exception e) {
-                LOG.error("Cannot parse errorCode [{}] value as Integer!", error, e);
-            }
-            if (errorCode != -1) {
-                if (errorMessage != null) {
-                    String finalMessage = parse ? TextParseUtil.translateVariables(errorMessage, stack) : errorMessage;
-                    response.sendError(errorCode, finalMessage);
-                } else {
-                    response.sendError(errorCode);
-                }
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/dispatcher/PlainTextResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/dispatcher/PlainTextResult.java b/core/src/main/java/org/apache/struts2/dispatcher/PlainTextResult.java
deleted file mode 100644
index 8d36bf6..0000000
--- a/core/src/main/java/org/apache/struts2/dispatcher/PlainTextResult.java
+++ /dev/null
@@ -1,183 +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.dispatcher;
-
-import com.opensymphony.xwork2.ActionInvocation;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.nio.charset.Charset;
-
-/**
- * <!-- START SNIPPET: description -->
- *
- * A result that send the content out as plain text. Useful typically when needed
- * to display the raw content of a JSP or Html file for example.
- *
- * <!-- END SNIPPET: description -->
- *
- *
- * <!-- START SNIPPET: params -->
- *
- * <ul>
- *  <li>location (default) = location of the file (jsp/html) to be displayed as plain text.</li>
- *  <li>charSet (optional) = character set to be used. This character set will be used to set the
- *  response type (eg. Content-Type=text/plain; charset=UTF-8) and when reading
- *  using a Reader. Some example of charSet would be UTF-8, ISO-8859-1 etc.
- * </ul>
- *
- * <!-- END SNIPPET: params -->
- *
- *
- * <pre>
- * <!-- START SNIPPET: example -->
- *
- * &lt;action name="displayJspRawContent" &gt;
- *   &lt;result type="plainText"&gt;/myJspFile.jsp&lt;/result&gt;
- * &lt;/action&gt;
- *
- *
- * &lt;action name="displayJspRawContent" &gt;
- *   &lt;result type="plainText"&gt;
- *      &lt;param name="location"&gt;/myJspFile.jsp&lt;/param&gt;
- *      &lt;param name="charSet"&gt;UTF-8&lt;/param&gt;
- *   &lt;/result&gt;
- * &lt;/action&gt;
- *
- * <!-- END SNIPPET: example -->
- * </pre>
- *
- */
-public class PlainTextResult extends StrutsResultSupport {
-
-    public static final int BUFFER_SIZE = 1024;
-
-    private static final Logger LOG = LogManager.getLogger(PlainTextResult.class);
-
-    private static final long serialVersionUID = 3633371605905583950L;
-
-    private String charSet;
-
-    public PlainTextResult() {
-        super();
-    }
-
-    public PlainTextResult(String location) {
-        super(location);
-    }
-
-    /**
-     * Set the character set
-     *
-     * @return The character set
-     */
-    public String getCharSet() {
-        return charSet;
-    }
-
-    /**
-     * Set the character set
-     *
-     * @param charSet The character set
-     */
-    public void setCharSet(String charSet) {
-        this.charSet = charSet;
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.struts2.dispatcher.StrutsResultSupport#doExecute(java.lang.String, com.opensymphony.xwork2.ActionInvocation)
-     */
-    protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
-        // verify charset
-        Charset charset = readCharset();
-
-        HttpServletResponse response = (HttpServletResponse) invocation.getInvocationContext().get(HTTP_RESPONSE);
-
-        applyCharset(charset, response);
-        applyAdditionalHeaders(response);
-        String location = adjustLocation(finalLocation);
-
-        try (PrintWriter writer = response.getWriter();
-                InputStream resourceAsStream = readStream(invocation, location);
-                InputStreamReader reader = new InputStreamReader(resourceAsStream, charset == null ? Charset.defaultCharset() : charset)) {
-            logWrongStream(finalLocation, resourceAsStream);
-            sendStream(writer, reader);
-        }
-    }
-
-    protected InputStream readStream(ActionInvocation invocation, String location) {
-        ServletContext servletContext = (ServletContext) invocation.getInvocationContext().get(SERVLET_CONTEXT);
-        return servletContext.getResourceAsStream(location);
-    }
-
-    protected void logWrongStream(String finalLocation, InputStream resourceAsStream) {
-        if (resourceAsStream == null) {
-            LOG.warn("Resource at location [{}] cannot be obtained (return null) from ServletContext !!!", finalLocation);
-        }
-    }
-
-    protected void sendStream(PrintWriter writer, InputStreamReader reader) throws IOException {
-        char[] buffer = new char[BUFFER_SIZE];
-        int charRead;
-        while((charRead = reader.read(buffer)) != -1) {
-            writer.write(buffer, 0, charRead);
-        }
-    }
-
-    protected String adjustLocation(String location) {
-        if (location.charAt(0) != '/') {
-            return "/" + location;
-        }
-        return location;
-    }
-
-    protected void applyAdditionalHeaders(HttpServletResponse response) {
-        response.setHeader("Content-Disposition", "inline");
-    }
-
-    protected void applyCharset(Charset charset, HttpServletResponse response) {
-        if (charset != null) {
-            response.setContentType("text/plain; charset=" + charSet);
-        } else {
-            response.setContentType("text/plain");
-        }
-    }
-
-    protected Charset readCharset() {
-        Charset charset = null;
-        if (charSet != null) {
-            if (Charset.isSupported(charSet)) {
-                charset = Charset.forName(charSet);
-            } else {
-                LOG.warn("charset [{}] is not recognized", charset);
-                charset = null;
-            }
-        }
-        return charset;
-    }
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/dispatcher/PostbackResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/dispatcher/PostbackResult.java b/core/src/main/java/org/apache/struts2/dispatcher/PostbackResult.java
deleted file mode 100644
index 89e3400..0000000
--- a/core/src/main/java/org/apache/struts2/dispatcher/PostbackResult.java
+++ /dev/null
@@ -1,232 +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.dispatcher;
-
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.inject.Inject;
-import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.dispatcher.mapper.ActionMapper;
-import org.apache.struts2.dispatcher.mapper.ActionMapping;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.Map;
-
-/**
- * <!-- START SNIPPET: description -->
- * A result that renders the current request parameters as a form which
- * immediately submits a <a href="http://en.wikipedia.org/wiki/Postback">postback</a>
- * to the specified destination.
- * <!-- END SNIPPET: description -->
- * <p/>
- * <b>Parameters:</b>
- * <!-- START SNIPPET: params -->
- * <ul>
- *     <li>location - http location to post the form</li>
- *     <li>prependServletContext (true|false) -  when location is relative, controls if to add Servlet Context, default "true"</li>
- *     <li>actionName - action name to post the form (resolved as an expression)</li>
- *     <li>namespace - action's namespace to use (resolved as an expression)</li>
- *     <li>method - actions' method to use (resolved as an expression)</li>
- *     <li>cache (true|false) - when set to true adds cache control headers, default "true"</li>
- *     <li>parse (true|false) - when set to true actionName, namespace and method are parsed, default "true"</li>
- * </ul>
- * <!-- END SNIPPET: params -->
- * <p/>
- * <b>Examples:</b>
- * <pre>
- * <!-- START SNIPPET: example -->
- * &lt;action name="registerThirdParty" &gt;
- *   &lt;result type="postback"&gt;https://www.example.com/register&lt;/result&gt;
- * &lt;/action&gt;
- *
- * &lt;action name="registerThirdParty" &gt;
- *   &lt;result type="postback"&gt;
- *     &lt;param name="namespace"&gt;/secure&lt;/param&gt;
- *     &lt;param name="actionName"&gt;register2&lt;/param&gt;
- *   &lt;/result&gt;
- * &lt;/action&gt;
- * <!-- END SNIPPET: example -->
- * </pre>
- */
-public class PostbackResult extends StrutsResultSupport {
-
-    private String actionName;
-    private String namespace;
-    private String method;
-    private boolean prependServletContext = true;
-    private boolean cache = true;
-
-    protected ActionMapper actionMapper;
-
-    @Override
-    protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
-        ActionContext ctx = invocation.getInvocationContext();
-        HttpServletRequest request = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
-        HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);
-
-        // Cache?
-        if (!cache) {
-            response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1
-            response.setHeader("Pragma", "no-cache"); // HTTP 1.0
-            response.setDateHeader("Expires", 0); // Proxies
-        }
-
-        // Render
-        PrintWriter pw = new PrintWriter(response.getOutputStream());
-        pw.write("<!DOCTYPE html><html><body><form action=\"" + finalLocation + "\" method=\"POST\">");
-        writeFormElements(request, pw);
-        writePrologueScript(pw);
-        pw.write("</html>");
-        pw.flush();
-    }
-
-    @Override
-    public void execute(ActionInvocation invocation) throws Exception {
-        String postbackUri = makePostbackUri(invocation);
-        setLocation(postbackUri);
-        super.execute(invocation);
-    }
-
-    /**
-     * Determines if the specified form input element should be included.
-     *
-     * @param name the input element name
-     * @param values the input element values
-     * @return {@code true} if included; otherwise {@code false}
-     */
-    protected boolean isElementIncluded(String name, String[] values) {
-        return !name.startsWith("action:");
-    }
-
-    protected String makePostbackUri(ActionInvocation invocation) {
-        ActionContext ctx = invocation.getInvocationContext();
-        HttpServletRequest request = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
-        String postbackUri;
-
-        if (actionName != null) {
-            actionName = conditionalParse(actionName, invocation);
-            if (namespace == null) {
-                namespace = invocation.getProxy().getNamespace();
-            } else {
-                namespace = conditionalParse(namespace, invocation);
-            }
-            if (method == null) {
-                method = "";
-            } else {
-                method = conditionalParse(method, invocation);
-            }
-            postbackUri = request.getContextPath() + actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null));
-        } else {
-            String location = getLocation();
-            // Do not prepend if the URL is a FQN
-            if (!location.matches("^([a-zA-z]+:)?//.*")) {
-                // If the URL is relative to the servlet context, prepend the servlet context path
-                if (prependServletContext && (request.getContextPath() != null) && (request.getContextPath().length() > 0)) {
-                    location = request.getContextPath() + location;
-                }
-            }
-            postbackUri = location;
-        }
-
-        return postbackUri;
-    }
-
-    @Inject
-    public final void setActionMapper(ActionMapper mapper) {
-        this.actionMapper = mapper;
-    }
-
-    /**
-     * Sets the name of the destination action.
-     *
-     * @param actionName the action name
-     */
-    public final void setActionName(String actionName) {
-        this.actionName = actionName;
-    }
-
-    /**
-     * Stores the option to cache the rendered intermediate page. The default
-     * is {@code true}.
-     *
-     * @return {@code true} to cache; otherwise {@code false}
-     */
-    public final void setCache(boolean cache) {
-        this.cache = cache;
-    }
-
-    /**
-     * Sets the method of the destination action.
-     *
-     * @param method the method
-     */
-    public final void setMethod(String method) {
-        this.method = method;
-    }
-
-    /**
-     * Sets the namespace of the destination action.
-     *
-     * @param namespace the namespace
-     */
-    public final void setNamespace(String namespace) {
-        this.namespace = namespace;
-    }
-
-    public final void setPrependServletContext(boolean prependServletContext) {
-        this.prependServletContext = prependServletContext;
-    }
-
-    protected void writeFormElement(PrintWriter pw, String name, String[] values) throws UnsupportedEncodingException {
-        for (String value : values) {
-            String encName = URLEncoder.encode(name, "UTF-8");
-            String encValue = URLEncoder.encode(value, "UTF-8");
-            pw.write("<input type=\"hidden\" name=\"" + encName + "\" value=\"" + encValue + "\"/>");
-        }
-    }
-
-    private void writeFormElements(HttpServletRequest request, PrintWriter pw) throws UnsupportedEncodingException {
-        Map<String, String[]> params = request.getParameterMap();
-        for (String name : params.keySet()) {
-            String[] values = params.get(name);
-            if (isElementIncluded(name, values)) {
-                writeFormElement(pw, name, values);
-            }
-        }
-    }
-
-    /**
-     * Outputs the script after the form has been emitted. The default script
-     * is to submit the form using a JavaScript time out that immediately expires.
-     *
-     * @param pw the print writer
-     */
-    protected void writePrologueScript(PrintWriter pw) {
-        pw.write("<script>");
-        pw.write("setTimeout(function(){document.forms[0].submit();},0);");
-        pw.write("</script>");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/dispatcher/ServletActionRedirectResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/dispatcher/ServletActionRedirectResult.java b/core/src/main/java/org/apache/struts2/dispatcher/ServletActionRedirectResult.java
deleted file mode 100644
index 5e0f835..0000000
--- a/core/src/main/java/org/apache/struts2/dispatcher/ServletActionRedirectResult.java
+++ /dev/null
@@ -1,227 +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.dispatcher;
-
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler;
-import org.apache.struts2.dispatcher.mapper.ActionMapper;
-import org.apache.struts2.dispatcher.mapper.ActionMapping;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * <!-- START SNIPPET: description -->
- *
- * This result uses the {@link ActionMapper} provided by the
- * {@link ActionMapperFactory} to redirect the browser to a URL that invokes the
- * specified action and (optional) namespace. This is better than the
- * {@link ServletRedirectResult} because it does not require you to encode the
- * URL patterns processed by the {@link ActionMapper} in to your struts.xml
- * configuration files. This means you can change your URL patterns at any point
- * and your application will still work. It is strongly recommended that if you
- * are redirecting to another action, you use this result rather than the
- * standard redirect result.
- *
- * See examples below for an example of how request parameters could be passed
- * in.
- *
- * <!-- END SNIPPET: description -->
- *
- * <b>This result type takes the following parameters:</b>
- *
- * <!-- START SNIPPET: params -->
- *
- * <ul>
- *
- * <li><b>actionName (default)</b> - The name of the action that will be
- * redirected to.</li>
- *
- * <li><b>namespace</b> - Used to determine which namespace the action is in
- * that we're redirecting to.  If namespace is null, the default will be the
- * current namespace.</li>
- *
- * <li><b>suppressEmptyParameters</b> - Optional boolean (defaults to false) that
- * can prevent parameters with no values from being included in the redirect
- * URL.</li>
- *
- * <li><b>parse</b> - Boolean, true by default.  If set to false, the actionName
- * param will not be parsed for Ognl expressions.</li>
- *
- * <li><b>anchor</b> - Optional.  Also known as "fragment" or colloquially as
- * "hash".  You can specify an anchor for a result.</li>
- * </ul>
- *
- * <!-- END SNIPPET: params -->
- *
- * <b>Example:</b>
- *
- * <pre>
- * <!-- START SNIPPET: example -->
- * &lt;package name="public" extends="struts-default"&gt;
- *     &lt;action name="login" class="..."&gt;
- *         &lt;!-- Redirect to another namespace --&gt;
- *         &lt;result type="redirectAction"&gt;
- *             &lt;param name="actionName"&gt;dashboard&lt;/param&gt;
- *             &lt;param name="namespace"&gt;/secure&lt;/param&gt;
- *         &lt;/result&gt;
- *     &lt;/action&gt;
- * &lt;/package&gt;
- *
- * &lt;package name="secure" extends="struts-default" namespace="/secure"&gt;
- *     &lt;-- Redirect to an action in the same namespace --&gt;
- *     &lt;action name="dashboard" class="..."&gt;
- *         &lt;result&gt;dashboard.jsp&lt;/result&gt;
- *         &lt;result name="error" type="redirectAction"&gt;error&lt;/result&gt;
- *     &lt;/action&gt;
- *
- *     &lt;action name="error" class="..."&gt;
- *         &lt;result&gt;error.jsp&lt;/result&gt;
- *     &lt;/action&gt;
- * &lt;/package&gt;
- *
- * &lt;package name="passingRequestParameters" extends="struts-default" namespace="/passingRequestParameters"&gt;
- *    &lt;!-- Pass parameters (reportType, width and height) --&gt;
- *    &lt;!--
- *    The redirectAction url generated will be :
- *    /genReport/generateReport.action?reportType=pie&width=100&height=100#summary
- *    --&gt;
- *    &lt;action name="gatherReportInfo" class="..."&gt;
- *       &lt;result name="showReportResult" type="redirectAction"&gt;
- *          &lt;param name="actionName"&gt;generateReport&lt;/param&gt;
- *          &lt;param name="namespace"&gt;/genReport&lt;/param&gt;
- *          &lt;param name="reportType"&gt;pie&lt;/param&gt;
- *          &lt;param name="width"&gt;100&lt;/param&gt;
- *          &lt;param name="height"&gt;100&lt;/param&gt;
- *          &lt;param name="empty"&gt;&lt;/param&gt;
- *          &lt;param name="suppressEmptyParameters"&gt;true&lt;/param&gt;
- *          &lt;param name="anchor"&gt;summary&lt;/param&gt;
- *       &lt;/result&gt;
- *    &lt;/action&gt;
- * &lt;/package&gt;
- *
- *
- * <!-- END SNIPPET: example -->
- * </pre>
- *
- * @see ActionMapper
- */
-public class ServletActionRedirectResult extends ServletRedirectResult implements ReflectionExceptionHandler {
-
-    private static final long serialVersionUID = -9042425229314584066L;
-
-    /* The default parameter */
-    public static final String DEFAULT_PARAM = "actionName";
-
-    protected String actionName;
-    protected String namespace;
-    protected String method;
-
-    public ServletActionRedirectResult() {
-        super();
-    }
-
-    public ServletActionRedirectResult(String actionName) {
-        this(null, actionName, null, null);
-    }
-
-    public ServletActionRedirectResult(String actionName, String method) {
-        this(null, actionName, method, null);
-    }
-
-    public ServletActionRedirectResult(String namespace, String actionName, String method) {
-        this(namespace, actionName, method, null);
-    }
-
-    public ServletActionRedirectResult(String namespace, String actionName, String method, String anchor) {
-        super(null, anchor);
-        this.namespace = namespace;
-        this.actionName = actionName;
-        this.method = method;
-    }
-
-    /**
-     * @see com.opensymphony.xwork2.Result#execute(com.opensymphony.xwork2.ActionInvocation)
-     */
-    public void execute(ActionInvocation invocation) throws Exception {
-        actionName = conditionalParse(actionName, invocation);
-        if (namespace == null) {
-            namespace = invocation.getProxy().getNamespace();
-        } else {
-            namespace = conditionalParse(namespace, invocation);
-        }
-        if (method == null) {
-            method = "";
-        } else {
-            method = conditionalParse(method, invocation);
-        }
-
-        String tmpLocation = actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null));
-
-        setLocation(tmpLocation);
-
-        super.execute(invocation);
-    }
-
-    /**
-     * Sets the action name
-     *
-     * @param actionName The name
-     */
-    public void setActionName(String actionName) {
-        this.actionName = actionName;
-    }
-
-    /**
-     * Sets the namespace
-     *
-     * @param namespace The namespace
-     */
-    public void setNamespace(String namespace) {
-        this.namespace = namespace;
-    }
-
-    /**
-     * Sets the method
-     *
-     * @param method The method
-     */
-    public void setMethod(String method) {
-        this.method = method;
-    }
-
-    protected List<String> getProhibitedResultParams() {
-        return Arrays.asList(
-                DEFAULT_PARAM,
-                "namespace",
-                "method",
-                "encode",
-                "parse",
-                "location",
-                "prependServletContext",
-                "suppressEmptyParameters",
-                "anchor",
-                "statusCode"
-        );
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/dispatcher/ServletDispatcherResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/dispatcher/ServletDispatcherResult.java b/core/src/main/java/org/apache/struts2/dispatcher/ServletDispatcherResult.java
deleted file mode 100644
index 52d4f67..0000000
--- a/core/src/main/java/org/apache/struts2/dispatcher/ServletDispatcherResult.java
+++ /dev/null
@@ -1,174 +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.dispatcher;
-
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.inject.Inject;
-import org.apache.commons.lang3.ObjectUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.StrutsStatics;
-import org.apache.struts2.views.util.UrlHelper;
-
-import javax.servlet.RequestDispatcher;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.jsp.PageContext;
-import java.util.Map;
-
-
-/**
- * <!-- START SNIPPET: description -->
- *
- * Includes or forwards to a view (usually a jsp). Behind the scenes Struts
- * will use a RequestDispatcher, where the target servlet/JSP receives the same
- * request/response objects as the original servlet/JSP. Therefore, you can pass
- * data between them using request.setAttribute() - the Struts action is
- * available.
- * <p/>
- * There are three possible ways the result can be executed:
- *
- * <ul>
- *
- * <li>If we are in the scope of a JSP (a PageContext is available), PageContext's
- * {@link PageContext#include(String) include} method is called.</li>
- *
- * <li>If there is no PageContext and we're not in any sort of include (there is no
- * "javax.servlet.include.servlet_path" in the request attributes), then a call to
- * {@link RequestDispatcher#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse) forward}
- * is made.</li>
- *
- * <li>Otherwise, {@link RequestDispatcher#include(javax.servlet.ServletRequest, javax.servlet.ServletResponse) include}
- * is called.</li>
- *
- * </ul>
- * <!-- END SNIPPET: description -->
- *
- * <b>This result type takes the following parameters:</b>
- *
- * <!-- START SNIPPET: params -->
- *
- * <ul>
- *
- * <li><b>location (default)</b> - the location to go to after execution (ex. jsp).</li>
- *
- * <li><b>parse</b> - true by default. If set to false, the location param will not be parsed for Ognl expressions.</li>
- *
- * </ul>
- *
- * <!-- END SNIPPET: params -->
- *
- * <b>Example:</b>
- *
- * <pre><!-- START SNIPPET: example -->
- * &lt;result name="success" type="dispatcher"&gt;
- *   &lt;param name="location"&gt;foo.jsp&lt;/param&gt;
- * &lt;/result&gt;
- * <!-- END SNIPPET: example --></pre>
- *
- * This result follows the same rules from {@link StrutsResultSupport}.
- *
- * @see javax.servlet.RequestDispatcher
- */
-public class ServletDispatcherResult extends StrutsResultSupport {
-
-    private static final long serialVersionUID = -1970659272360685627L;
-
-    private static final Logger LOG = LogManager.getLogger(ServletDispatcherResult.class);
-
-    private UrlHelper urlHelper;
-
-    public ServletDispatcherResult() {
-        super();
-    }
-
-    public ServletDispatcherResult(String location) {
-        super(location);
-    }
-
-    @Inject
-    public void setUrlHelper(UrlHelper urlHelper) {
-        this.urlHelper = urlHelper;
-    }
-
-    /**
-     * Dispatches to the given location. Does its forward via a RequestDispatcher. If the
-     * dispatch fails a 404 error will be sent back in the http response.
-     *
-     * @param finalLocation the location to dispatch to.
-     * @param invocation    the execution state of the action
-     * @throws Exception if an error occurs. If the dispatch fails the error will go back via the
-     *                   HTTP request.
-     */
-    public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
-        LOG.debug("Forwarding to location: {}", finalLocation);
-
-        PageContext pageContext = ServletActionContext.getPageContext();
-
-        if (pageContext != null) {
-            pageContext.include(finalLocation);
-        } else {
-            HttpServletRequest request = ServletActionContext.getRequest();
-            HttpServletResponse response = ServletActionContext.getResponse();
-            RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation);
-
-            //add parameters passed on the location to #parameters
-            // see WW-2120
-            if (StringUtils.isNotEmpty(finalLocation) && finalLocation.indexOf("?") > 0) {
-                String queryString = finalLocation.substring(finalLocation.indexOf("?") + 1);
-                Map<String, Object> parameters = getParameters(invocation);
-                Map<String, Object> queryParams = urlHelper.parseQueryString(queryString, true);
-                if (queryParams != null && !queryParams.isEmpty())
-                    parameters.putAll(queryParams);
-            }
-
-            // if the view doesn't exist, let's do a 404
-            if (dispatcher == null) {
-                response.sendError(404, "result '" + finalLocation + "' not found");
-                return;
-            }
-
-            //if we are inside an action tag, we always need to do an include
-            Boolean insideActionTag = (Boolean) ObjectUtils.defaultIfNull(request.getAttribute(StrutsStatics.STRUTS_ACTION_TAG_INVOCATION), Boolean.FALSE);
-
-            // If we're included, then include the view
-            // Otherwise do forward
-            // This allow the page to, for example, set content type
-            if (!insideActionTag && !response.isCommitted() && (request.getAttribute("javax.servlet.include.servlet_path") == null)) {
-                request.setAttribute("struts.view_uri", finalLocation);
-                request.setAttribute("struts.request_uri", request.getRequestURI());
-
-                dispatcher.forward(request, response);
-            } else {
-                dispatcher.include(request, response);
-            }
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private Map<String, Object> getParameters(ActionInvocation invocation) {
-        return (Map<String, Object>) invocation.getInvocationContext().getContextMap().get("parameters");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/dispatcher/ServletRedirectResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/dispatcher/ServletRedirectResult.java b/core/src/main/java/org/apache/struts2/dispatcher/ServletRedirectResult.java
deleted file mode 100644
index 99317f3..0000000
--- a/core/src/main/java/org/apache/struts2/dispatcher/ServletRedirectResult.java
+++ /dev/null
@@ -1,322 +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.dispatcher;
-
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.config.entities.ResultConfig;
-import com.opensymphony.xwork2.inject.Inject;
-import com.opensymphony.xwork2.util.reflection.ReflectionException;
-import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.dispatcher.mapper.ActionMapper;
-import org.apache.struts2.dispatcher.mapper.ActionMapping;
-import org.apache.struts2.views.util.UrlHelper;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URL;
-import java.util.*;
-
-import static javax.servlet.http.HttpServletResponse.SC_FOUND;
-
-/**
- * <!-- START SNIPPET: description -->
- * 
- * Calls the {@link HttpServletResponse#sendRedirect(String) sendRedirect}
- * method to the location specified. The response is told to redirect the
- * browser to the specified location (a new request from the client). The
- * consequence of doing this means that the action (action instance, action
- * errors, field errors, etc) that was just executed is lost and no longer
- * available. This is because actions are built on a single-thread model. The
- * only way to pass data is through the session or with web parameters
- * (url?name=value) which can be OGNL expressions.
- * 
- * <!-- END SNIPPET: description -->
- * <p/>
- * <b>This result type takes the following parameters:</b>
- * 
- * <!-- START SNIPPET: params -->
- * 
- * <ul>
- * 
- * <li><b>location (default)</b> - the location to go to after execution.</li>
- * 
- * <li><b>parse</b> - true by default. If set to false, the location param will
- * not be parsed for Ognl expressions.</li>
- * 
- * <li><b>anchor</b> - Optional.  Also known as "fragment" or colloquially as 
- * "hash".  You can specify an anchor for a result.</li>
- * </ul>
- * 
- * <p>
- * This result follows the same rules from {@link StrutsResultSupport}.
- * </p>
- * 
- * <!-- END SNIPPET: params -->
- * 
- * <b>Example:</b>
- * 
- * <pre>
- * <!-- START SNIPPET: example -->
- * &lt;!--
- *   The redirect URL generated will be:
- *   /foo.jsp#FRAGMENT
- * --&gt;
- * &lt;result name="success" type="redirect"&gt;
- *   &lt;param name="location"&gt;foo.jsp&lt;/param&gt;
- *   &lt;param name="parse"&gt;false&lt;/param&gt;
- *   &lt;param name="anchor"&gt;FRAGMENT&lt;/param&gt;
- * &lt;/result&gt;
- * <!-- END SNIPPET: example -->
- * </pre>
- * 
- */
-public class ServletRedirectResult extends StrutsResultSupport implements ReflectionExceptionHandler {
-
-    private static final long serialVersionUID = 6316947346435301270L;
-
-    private static final Logger LOG = LogManager.getLogger(ServletRedirectResult.class);
-
-    protected boolean prependServletContext = true;
-    protected ActionMapper actionMapper;
-    protected int statusCode = SC_FOUND;
-    protected boolean suppressEmptyParameters = false;
-    protected Map<String, Object> requestParameters = new LinkedHashMap<>();
-    protected String anchor;
-
-    private UrlHelper urlHelper;
-
-    public ServletRedirectResult() {
-        super();
-    }
-
-    public ServletRedirectResult(String location) {
-        this(location, null);
-    }
-
-    public ServletRedirectResult(String location, String anchor) {
-        super(location);
-        this.anchor = anchor;
-    }
-
-    @Inject
-    public void setActionMapper(ActionMapper mapper) {
-        this.actionMapper = mapper;
-    }
-
-    @Inject
-    public void setUrlHelper(UrlHelper urlHelper) {
-        this.urlHelper = urlHelper;
-    }
-
-    public void setStatusCode(int code) {
-        this.statusCode = code;
-    }
-
-    /**
-     * Set the optional anchor value.
-     * 
-     * @param anchor
-     */
-    public void setAnchor(String anchor) {
-        this.anchor = anchor;
-    }
-
-    /**
-     * Sets whether or not to prepend the servlet context path to the redirected
-     * URL.
-     * 
-     * @param prependServletContext <tt>true</tt> to prepend the location with the servlet context path, <tt>false</tt> otherwise.
-     */
-    public void setPrependServletContext(boolean prependServletContext) {
-        this.prependServletContext = prependServletContext;
-    }
-
-    public void execute(ActionInvocation invocation) throws Exception {
-        if (anchor != null) {
-            anchor = conditionalParse(anchor, invocation);
-        }
-        super.execute(invocation);
-    }
-
-    /**
-     * Redirects to the location specified by calling
-     * {@link HttpServletResponse#sendRedirect(String)}.
-     * 
-     * @param finalLocation the location to redirect to.
-     * @param invocation an encapsulation of the action execution state.
-     * @throws Exception if an error occurs when redirecting.
-     */
-    protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
-        ActionContext ctx = invocation.getInvocationContext();
-        HttpServletRequest request = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
-        HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);
-
-        if (isPathUrl(finalLocation)) {
-            if (!finalLocation.startsWith("/")) {
-                ActionMapping mapping = actionMapper.getMapping(request, Dispatcher.getInstance().getConfigurationManager());
-                String namespace = null;
-                if (mapping != null) {
-                    namespace = mapping.getNamespace();
-                }
-
-                if ((namespace != null) && (namespace.length() > 0) && (!"/".equals(namespace))) {
-                    finalLocation = namespace + "/" + finalLocation;
-                } else {
-                    finalLocation = "/" + finalLocation;
-                }
-            }
-
-            // if the URL's are relative to the servlet context, append the servlet context path
-            if (prependServletContext && (request.getContextPath() != null) && (request.getContextPath().length() > 0)) {
-                finalLocation = request.getContextPath() + finalLocation;
-            }
-        }
-        ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(invocation.getResultCode());
-        if (resultConfig != null) {
-            Map<String, String> resultConfigParams = resultConfig.getParams();
-
-            List<String> prohibitedResultParams = getProhibitedResultParams();
-            for (Map.Entry<String, String> e : resultConfigParams.entrySet()) {
-                if (!prohibitedResultParams.contains(e.getKey())) {
-                    Collection<String> values = conditionalParseCollection(e.getValue(), invocation, suppressEmptyParameters);
-                    if (!suppressEmptyParameters || !values.isEmpty()) {
-                        requestParameters.put(e.getKey(), values);
-                    }
-                }
-            }
-        }
-
-        StringBuilder tmpLocation = new StringBuilder(finalLocation);
-        urlHelper.buildParametersString(requestParameters, tmpLocation, "&");
-
-        // add the anchor
-        if (anchor != null) {
-            tmpLocation.append('#').append(anchor);
-        }
-
-        finalLocation = response.encodeRedirectURL(tmpLocation.toString());
-
-        LOG.debug("Redirecting to finalLocation: {}", finalLocation);
-
-        sendRedirect(response, finalLocation);
-    }
-
-    protected List<String> getProhibitedResultParams() {
-        return Arrays.asList(
-                DEFAULT_PARAM,
-                "namespace",
-                "method",
-                "encode",
-                "parse",
-                "location",
-                "prependServletContext",
-                "suppressEmptyParameters",
-                "anchor",
-                "statusCode"
-        );
-    }
-
-    /**
-     * Sends the redirection. Can be overridden to customize how the redirect is
-     * handled (i.e. to use a different status code)
-     * 
-     * @param response The response
-     * @param finalLocation The location URI
-     * @throws IOException
-     */
-    protected void sendRedirect(HttpServletResponse response, String finalLocation) throws IOException {
-        if (SC_FOUND == statusCode) {
-            response.sendRedirect(finalLocation);
-        } else {
-            response.setStatus(statusCode);
-            response.setHeader("Location", finalLocation);
-            response.getWriter().write(finalLocation);
-            response.getWriter().close();
-        }
-
-    }
-
-    /**
-     * Checks if url is simple path or either full url
-     *
-     * @param url string
-     * @return true if it's just a path not a full url
-     */
-    protected boolean isPathUrl(String url) {
-        try {
-            String rawUrl = url;
-            if (url.contains("?")) {
-                rawUrl = url.substring(0, url.indexOf("?"));
-            }
-            URI uri = URI.create(rawUrl.replaceAll(" ", "%20"));
-            if (uri.isAbsolute()) {
-                URL validUrl = uri.toURL();
-                LOG.debug("[{}] is full url, not a path", url);
-                return validUrl.getProtocol() == null;
-            } else {
-                LOG.debug("[{}] isn't absolute URI, assuming it's a path", url);
-                return true;
-            }
-        } catch (IllegalArgumentException e) {
-            LOG.debug("[{}] isn't a valid URL, assuming it's a path", url, e);
-            return true;
-        } catch (MalformedURLException e) {
-            LOG.debug("[{}] isn't a valid URL, assuming it's a path", url, e);
-            return true;
-        }
-    }
-
-    /**
-     * Sets the suppressEmptyParameters option
-     * 
-     * @param suppressEmptyParameters The new value for this option
-     */
-    public void setSuppressEmptyParameters(boolean suppressEmptyParameters) {
-        this.suppressEmptyParameters = suppressEmptyParameters;
-    }
-
-    /**
-     * Adds a request parameter to be added to the redirect url
-     * 
-     * @param key The parameter name
-     * @param value The parameter value
-     */
-    public ServletRedirectResult addParameter(String key, Object value) {
-        requestParameters.put(key, String.valueOf(value));
-        return this;
-    }
-
-    public void handle(ReflectionException ex) {
-        // Only log as debug as they are probably parameters to be appended to the url
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(ex.getMessage(), ex);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/dispatcher/StreamResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/dispatcher/StreamResult.java b/core/src/main/java/org/apache/struts2/dispatcher/StreamResult.java
deleted file mode 100644
index 4d51223..0000000
--- a/core/src/main/java/org/apache/struts2/dispatcher/StreamResult.java
+++ /dev/null
@@ -1,329 +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.dispatcher;
-
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.util.ValueStack;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import javax.servlet.http.HttpServletResponse;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * <!-- START SNIPPET: description -->
- *
- * A custom Result type for sending raw data (via an InputStream) directly to the
- * HttpServletResponse. Very useful for allowing users to download content.
- *
- * <!-- END SNIPPET: description -->
- * <p/>
- * <b>This result type takes the following parameters:</b>
- *
- * <!-- START SNIPPET: params -->
- *
- * <ul>
- *
- * <li><b>contentType</b> - the stream mime-type as sent to the web browser
- * (default = <code>text/plain</code>).</li>
- *
- * <li><b>contentLength</b> - the stream length in bytes (the browser displays a
- * progress bar).</li>
- *
- * <li><b>contentDisposition</b> - the content disposition header value for
- * specifing the file name (default = <code>inline</code>, values are typically
- * <i>attachment;filename="document.pdf"</i>.</li>
- *
- * <li><b>inputName</b> - the name of the InputStream property from the chained
- * action (default = <code>inputStream</code>).</li>
- *
- * <li><b>bufferSize</b> - the size of the buffer to copy from input to output
- * (default = <code>1024</code>).</li>
- *
- * <li><b>allowCaching</b> if set to 'false' it will set the headers 'Pragma' and 'Cache-Control'
- * to 'no-cahce', and prevent client from caching the content. (default = <code>true</code>)
- *
- * <li><b>contentCharSet</b> if set to a string, ';charset=value' will be added to the
- * content-type header, where value is the string set. If set to an expression, the result
- * of evaluating the expression will be used. If not set, then no charset will be set on
- * the header</li>
- * </ul>
- * 
- * <p>These parameters can also be set by exposing a similarly named getter method on your Action.  For example, you can
- * provide <code>getContentType()</code> to override that parameter for the current action.</p>
- *
- * <!-- END SNIPPET: params -->
- *
- * <b>Example:</b>
- *
- * <pre><!-- START SNIPPET: example -->
- * &lt;result name="success" type="stream"&gt;
- *   &lt;param name="contentType"&gt;image/jpeg&lt;/param&gt;
- *   &lt;param name="inputName"&gt;imageStream&lt;/param&gt;
- *   &lt;param name="contentDisposition"&gt;attachment;filename="document.pdf"&lt;/param&gt;
- *   &lt;param name="bufferSize"&gt;1024&lt;/param&gt;
- * &lt;/result&gt;
- * <!-- END SNIPPET: example --></pre>
- *
- */
-public class StreamResult extends StrutsResultSupport {
-
-    private static final long serialVersionUID = -1468409635999059850L;
-
-    protected static final Logger LOG = LogManager.getLogger(StreamResult.class);
-
-    public static final String DEFAULT_PARAM = "inputName";
-
-    protected String contentType = "text/plain";
-    protected String contentLength;
-    protected String contentDisposition = "inline";
-    protected String contentCharSet ;
-    protected String inputName = "inputStream";
-    protected InputStream inputStream;
-    protected int bufferSize = 1024;
-    protected boolean allowCaching = true;
-
-    public StreamResult() {
-        super();
-    }
-
-    public StreamResult(InputStream in) {
-        this.inputStream = in;
-    }
-
-     /**
-     * @return Returns the whether or not the client should be requested to allow caching of the data stream.
-     */
-    public boolean getAllowCaching() {
-        return allowCaching;
-    }
-
-    /**
-     * Set allowCaching to <tt>false</tt> to indicate that the client should be requested not to cache the data stream.
-     * This is set to <tt>false</tt> by default
-     *
-     * @param allowCaching Enable caching.
-     */
-    public void setAllowCaching(boolean allowCaching) {
-        this.allowCaching = allowCaching;
-    }
-
-
-    /**
-     * @return Returns the bufferSize.
-     */
-    public int getBufferSize() {
-        return (bufferSize);
-    }
-
-    /**
-     * @param bufferSize The bufferSize to set.
-     */
-    public void setBufferSize(int bufferSize) {
-        this.bufferSize = bufferSize;
-    }
-
-    /**
-     * @return Returns the contentType.
-     */
-    public String getContentType() {
-        return (contentType);
-    }
-
-    /**
-     * @param contentType The contentType to set.
-     */
-    public void setContentType(String contentType) {
-        this.contentType = contentType;
-    }
-
-    /**
-     * @return Returns the contentLength.
-     */
-    public String getContentLength() {
-        return contentLength;
-    }
-
-    /**
-     * @param contentLength The contentLength to set.
-     */
-    public void setContentLength(String contentLength) {
-        this.contentLength = contentLength;
-    }
-
-    /**
-     * @return Returns the Content-disposition header value.
-     */
-    public String getContentDisposition() {
-        return contentDisposition;
-    }
-
-    /**
-     * @param contentDisposition the Content-disposition header value to use.
-     */
-    public void setContentDisposition(String contentDisposition) {
-        this.contentDisposition = contentDisposition;
-    }
-
-    /**
-     * @return Returns the charset specified by the user
-     */
-    public String getContentCharSet() {
-        return contentCharSet;
-    }
-
-    /**
-     * @param contentCharSet the charset to use on the header when sending the stream
-     */
-    public void setContentCharSet(String contentCharSet) {
-        this.contentCharSet = contentCharSet;
-    }
-
-    /**
-     * @return Returns the inputName.
-     */
-    public String getInputName() {
-        return (inputName);
-    }
-
-    /**
-     * @param inputName The inputName to set.
-     */
-    public void setInputName(String inputName) {
-        this.inputName = inputName;
-    }
-
-    /**
-     * @see org.apache.struts2.dispatcher.StrutsResultSupport#doExecute(java.lang.String, com.opensymphony.xwork2.ActionInvocation)
-     */
-    protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
-
-        // Override any parameters using values on the stack
-        resolveParamsFromStack(invocation.getStack(), invocation);
-
-        // Find the Response in context
-        HttpServletResponse oResponse = (HttpServletResponse) invocation.getInvocationContext().get(HTTP_RESPONSE);
-        try (OutputStream oOutput = oResponse.getOutputStream()) {
-            if (inputStream == null) {
-                // Find the inputstream from the invocation variable stack
-                inputStream = (InputStream) invocation.getStack().findValue(conditionalParse(inputName, invocation));
-            }
-
-            if (inputStream == null) {
-                String msg = ("Can not find a java.io.InputStream with the name [" + inputName + "] in the invocation stack. " +
-                    "Check the <param name=\"inputName\"> tag specified for this action.");
-                LOG.error(msg);
-                throw new IllegalArgumentException(msg);
-            }
-
-            // Set the content type
-            if (contentCharSet != null && ! contentCharSet.equals("")) {
-                oResponse.setContentType(conditionalParse(contentType, invocation)+";charset="+contentCharSet);
-            }
-            else {
-                oResponse.setContentType(conditionalParse(contentType, invocation));
-            }
-
-            // Set the content length
-            if (contentLength != null) {
-                String _contentLength = conditionalParse(contentLength, invocation);
-                int _contentLengthAsInt = -1;
-                try {
-                    _contentLengthAsInt = Integer.parseInt(_contentLength);
-                    if (_contentLengthAsInt >= 0) {
-                        oResponse.setContentLength(_contentLengthAsInt);
-                    }
-                }
-                catch(NumberFormatException e) {
-                    LOG.warn("failed to recognize {} as a number, contentLength header will not be set", _contentLength, e);
-                }
-            }
-
-            // Set the content-disposition
-            if (contentDisposition != null) {
-                oResponse.addHeader("Content-Disposition", conditionalParse(contentDisposition, invocation));
-            }
-
-            // Set the cache control headers if neccessary
-            if (!allowCaching) {
-                oResponse.addHeader("Pragma", "no-cache");
-                oResponse.addHeader("Cache-Control", "no-cache");
-            }
-
-            LOG.debug("Streaming result [{}] type=[{}] length=[{}] content-disposition=[{}] charset=[{}]",
-                    inputName, contentType, contentLength, contentDisposition, contentCharSet);
-
-            // Copy input to output
-        	LOG.debug("Streaming to output buffer +++ START +++");
-            byte[] oBuff = new byte[bufferSize];
-            int iSize;
-            while (-1 != (iSize = inputStream.read(oBuff))) {
-                oOutput.write(oBuff, 0, iSize);
-            }
-        	LOG.debug("Streaming to output buffer +++ END +++");
-
-            // Flush
-            oOutput.flush();
-        }
-    }
-
-    /**
-     * Tries to lookup the parameters on the stack.  Will override any existing parameters
-     *
-     * @param stack The current value stack
-     */
-    protected void resolveParamsFromStack(ValueStack stack, ActionInvocation invocation) {
-        String disposition = stack.findString("contentDisposition");
-        if (disposition != null) {
-            setContentDisposition(disposition);
-        }
-
-        String contentType = stack.findString("contentType");
-        if (contentType != null) {
-            setContentType(contentType);
-        }
-
-        String inputName = stack.findString("inputName");
-        if (inputName != null) {
-            setInputName(inputName);
-        }
-
-        String contentLength = stack.findString("contentLength");
-        if (contentLength != null) {
-            setContentLength(contentLength);
-        }
-
-        Integer bufferSize = (Integer) stack.findValue("bufferSize", Integer.class);
-        if (bufferSize != null) {
-            setBufferSize(bufferSize);
-        }
-
-        if (contentCharSet != null ) {
-            contentCharSet = conditionalParse(contentCharSet, invocation);
-        }
-        else {
-            contentCharSet = stack.findString("contentCharSet");
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/dispatcher/StrutsResultSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/dispatcher/StrutsResultSupport.java b/core/src/main/java/org/apache/struts2/dispatcher/StrutsResultSupport.java
deleted file mode 100644
index f8f4ee1..0000000
--- a/core/src/main/java/org/apache/struts2/dispatcher/StrutsResultSupport.java
+++ /dev/null
@@ -1,266 +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.dispatcher;
-
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.Result;
-import com.opensymphony.xwork2.util.TextParseUtil;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.struts2.StrutsStatics;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Collection;
-
-
-/**
- * <!-- START SNIPPET: javadoc -->
- *
- * A base class for all Struts action execution results.
- * The "location" param is the default parameter, meaning the most common usage of this result would be:
- * <p/>
- * This class provides two common parameters for any subclass:
- * <ul>
- * <li>location - the location to go to after execution (could be a jsp page or another action).
- * It can be parsed as per the rules definied in the
- * {@link TextParseUtil#translateVariables(java.lang.String, com.opensymphony.xwork2.util.ValueStack) translateVariables}
- * method</li>
- * <li>parse - true by default. If set to false, the location param will not be parsed for expressions</li>
- * <li>encode - false by default. If set to false, the location param will not be url encoded. This only have effect when parse is true</li>
- * </ul>
- *
- * <b>NOTE:</b>
- * The encode param will only have effect when parse is true
- *
- * <!-- END SNIPPET: javadoc -->
- *
- * <p/>
- *
- * <!-- START SNIPPET: example -->
- *
- * <p/>
- * In the struts.xml configuration file, these would be included as:
- * <p/>
- * <pre>
- *  &lt;result name="success" type="redirect"&gt;
- *      &lt;param name="<b>location</b>"&gt;foo.jsp&lt;/param&gt;
- *  &lt;/result&gt;</pre>
- * <p/>
- * or
- * <p/>
- * <pre>
- *  &lt;result name="success" type="redirect" &gt;
- *      &lt;param name="<b>location</b>"&gt;foo.jsp?url=${myUrl}&lt;/param&gt;
- *      &lt;param name="<b>parse</b>"&gt;true&lt;/param&gt;
- *      &lt;param name="<b>encode</b>"&gt;true&lt;/param&gt;
- *  &lt;/result&gt;</pre>
- * <p/>
- * In the above case, myUrl will be parsed against Ognl Value Stack and then
- * URL encoded.
- * <p/>
- * or when using the default parameter feature
- * <p/>
- * <pre>
- *  &lt;result name="success" type="redirect"&gt;<b>foo.jsp</b>&lt;/result&gt;</pre>
- * <p/>
- * You should subclass this class if you're interested in adding more parameters or functionality
- * to your Result. If you do subclass this class you will need to
- * override {@link #doExecute(String, ActionInvocation)}.<p>
- * <p/>
- * Any custom result can be defined in struts.xml as:
- * <p/>
- * <pre>
- *  &lt;result-types&gt;
- *      ...
- *      &lt;result-type name="myresult" class="com.foo.MyResult" /&gt;
- *  &lt;/result-types&gt;</pre>
- * <p/>
- * Please see the {@link com.opensymphony.xwork2.Result} class for more info on Results in general.
- *
- * <!-- END SNIPPET: example -->
- *
- * @see com.opensymphony.xwork2.Result
- */
-public abstract class StrutsResultSupport implements Result, StrutsStatics {
-
-    private static final Logger LOG = LogManager.getLogger(StrutsResultSupport.class);
-
-    /** The default parameter */
-    public static final String DEFAULT_PARAM = "location";
-
-    /** use UTF-8 as this is the recommended encoding by W3C to avoid incompatibilities. */
-    public static final String DEFAULT_URL_ENCODING = "UTF-8";
-
-    private boolean parse;
-    private boolean encode;
-    private String location;
-    private String lastFinalLocation;
-
-    public StrutsResultSupport() {
-        this(null, true, false);
-    }
-
-    public StrutsResultSupport(String location) {
-        this(location, true, false);
-    }
-
-    public StrutsResultSupport(String location, boolean parse, boolean encode) {
-        this.location = location;
-        this.parse = parse;
-        this.encode = encode;
-    }
-
-    /**
-     * The location to go to after action execution. This could be a JSP page or another action.
-     * The location can contain OGNL expressions which will be evaulated if the <tt>parse</tt>
-     * parameter is set to <tt>true</tt>.
-     *
-     * @param location the location to go to after action execution.
-     * @see #setParse(boolean)
-     */
-    public void setLocation(String location) {
-        this.location = location;
-    }
-    
-    /**
-     * Gets the location it was created with, mainly for testing
-     */
-    public String getLocation() {
-        return location;
-    }
-
-    /**
-     * Returns the last parsed and encoded location value
-     */
-    public String getLastFinalLocation() {
-        return lastFinalLocation;
-    }
-
-    /**
-     * Set parse to <tt>true</tt> to indicate that the location should be parsed as an OGNL expression. This
-     * is set to <tt>true</tt> by default.
-     *
-     * @param parse <tt>true</tt> if the location parameter is an OGNL expression, <tt>false</tt> otherwise.
-     */
-    public void setParse(boolean parse) {
-        this.parse = parse;
-    }
-
-    /**
-     * Set encode to <tt>true</tt> to indicate that the location should be url encoded. This is set to
-     * <tt>true</tt> by default
-     *
-     * @param encode <tt>true</tt> if the location parameter should be url encode, <tt>false</tt> otherwise.
-     */
-    public void setEncode(boolean encode) {
-        this.encode = encode;
-    }
-
-    /**
-     * Implementation of the <tt>execute</tt> method from the <tt>Result</tt> interface. This will call
-     * the abstract method {@link #doExecute(String, ActionInvocation)} after optionally evaluating the
-     * location as an OGNL evaluation.
-     *
-     * @param invocation the execution state of the action.
-     * @throws Exception if an error occurs while executing the result.
-     */
-    public void execute(ActionInvocation invocation) throws Exception {
-        lastFinalLocation = conditionalParse(location, invocation);
-        doExecute(lastFinalLocation, invocation);
-    }
-
-    /**
-     * Parses the parameter for OGNL expressions against the valuestack
-     *
-     * @param param The parameter value
-     * @param invocation The action invocation instance
-     * @return The resulting string
-     */
-    protected String conditionalParse(String param, ActionInvocation invocation) {
-        if (parse && param != null && invocation != null) {
-            return TextParseUtil.translateVariables(
-                param, 
-                invocation.getStack(),
-                new EncodingParsedValueEvaluator());
-        } else {
-            return param;
-        }
-    }
-
-    /**
-     * As {@link #conditionalParse(String, ActionInvocation)} but does not
-     * convert found object into String. If found object is a collection it is
-     * returned if found object is not a collection it is wrapped in one.
-     * 
-     * @param param
-     * @param invocation
-     * @param excludeEmptyElements
-     * @return
-     */
-    protected Collection<String> conditionalParseCollection(String param, ActionInvocation invocation, boolean excludeEmptyElements) {
-        if (parse && param != null && invocation != null) {
-            return TextParseUtil.translateVariablesCollection(
-                param, 
-                invocation.getStack(),
-                excludeEmptyElements,
-                new EncodingParsedValueEvaluator());
-        } else {
-            Collection<String> collection = new ArrayList<>(1);
-            collection.add(param);
-            return collection;
-        }
-    }
-
-    /**
-     * {@link com.opensymphony.xwork2.util.TextParseUtil.ParsedValueEvaluator} to do URL encoding for found values. To be
-     * used for single strings or collections.
-     * 
-     */
-    private final class EncodingParsedValueEvaluator implements TextParseUtil.ParsedValueEvaluator {
-        public Object evaluate(String parsedValue) {
-            if (encode) {
-                if (parsedValue != null) {
-                    try {
-                        return URLEncoder.encode(parsedValue, DEFAULT_URL_ENCODING);
-                    }
-                    catch(UnsupportedEncodingException e) {
-                        LOG.warn("error while trying to encode [{}]", parsedValue, e);
-                    }
-                }
-            }
-            return parsedValue;
-        }
-    }
-
-    /**
-     * Executes the result given a final location (jsp page, action, etc) and the action invocation
-     * (the state in which the action was executed). Subclasses must implement this class to handle
-     * custom logic for result handling.
-     *
-     * @param finalLocation the location (jsp page, action, etc) to go to.
-     * @param invocation    the execution state of the action.
-     * @throws Exception if an error occurs while executing the result.
-     */
-    protected abstract void doExecute(String finalLocation, ActionInvocation invocation) throws Exception;
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/dispatcher/VelocityResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/dispatcher/VelocityResult.java b/core/src/main/java/org/apache/struts2/dispatcher/VelocityResult.java
deleted file mode 100644
index ff9d9df..0000000
--- a/core/src/main/java/org/apache/struts2/dispatcher/VelocityResult.java
+++ /dev/null
@@ -1,233 +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.dispatcher;
-
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.inject.Inject;
-import com.opensymphony.xwork2.util.ValueStack;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.StrutsConstants;
-import org.apache.struts2.views.JspSupportServlet;
-import org.apache.struts2.views.velocity.VelocityManager;
-import org.apache.velocity.Template;
-import org.apache.velocity.app.VelocityEngine;
-import org.apache.velocity.context.Context;
-
-import javax.servlet.Servlet;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.jsp.JspFactory;
-import javax.servlet.jsp.PageContext;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-
-
-/**
- * <!-- START SNIPPET: description -->
- *
- * Using the Servlet container's {@link JspFactory}, this result mocks a JSP
- * execution environment and then displays a Velocity template that will be
- * streamed directly to the servlet output.
- *
- * <!-- END SNIPPET: description -->
- * <p/>
- * <b>This result type takes the following parameters:</b>
- *
- * <!-- START SNIPPET: params -->
- *
- * <ul>
- *
- * <li><b>location (default)</b> - the location of the template to process.</li>
- *
- * <li><b>parse</b> - true by default. If set to false, the location param will
- * not be parsed for Ognl expressions.</li>
- *
- * </ul>
- * <p>
- * This result follows the same rules from {@link StrutsResultSupport}.
- * </p>
- *
- * <!-- END SNIPPET: params -->
- *
- * <b>Example:</b>
- *
- * <pre><!-- START SNIPPET: example -->
- * &lt;result name="success" type="velocity"&gt;
- *   &lt;param name="location"&gt;foo.vm&lt;/param&gt;
- * &lt;/result&gt;
- * <!-- END SNIPPET: example --></pre>
- *
- */
-public class VelocityResult extends StrutsResultSupport {
-
-    private static final long serialVersionUID = 7268830767762559424L;
-
-    private static final Logger LOG = LogManager.getLogger(VelocityResult.class);
-    
-    private String defaultEncoding;
-    private VelocityManager velocityManager;
-    private JspFactory jspFactory = JspFactory.getDefaultFactory();
-
-    public VelocityResult() {
-        super();
-    }
-
-    public VelocityResult(String location) {
-        super(location);
-    }
-    
-    @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
-    public void setDefaultEncoding(String val) {
-        defaultEncoding = val;
-    }
-    
-    @Inject
-    public void setVelocityManager(VelocityManager mgr) {
-        this.velocityManager = mgr;
-    }
-
-    /**
-     * Creates a Velocity context from the action, loads a Velocity template and executes the
-     * template. Output is written to the servlet output stream.
-     *
-     * @param finalLocation the location of the Velocity template
-     * @param invocation    an encapsulation of the action execution state.
-     * @throws Exception if an error occurs when creating the Velocity context, loading or executing
-     *                   the template or writing output to the servlet response stream.
-     */
-    public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
-        ValueStack stack = ActionContext.getContext().getValueStack();
-
-        HttpServletRequest request = ServletActionContext.getRequest();
-        HttpServletResponse response = ServletActionContext.getResponse();
-        ServletContext servletContext = ServletActionContext.getServletContext();
-        Servlet servlet = JspSupportServlet.jspSupportServlet;
-
-        velocityManager.init(servletContext);
-
-        boolean usedJspFactory = false;
-        PageContext pageContext = (PageContext) ActionContext.getContext().get(ServletActionContext.PAGE_CONTEXT);
-
-        if (pageContext == null && servlet != null) {
-            pageContext = jspFactory.getPageContext(servlet, request, response, null, true, 8192, true);
-            ActionContext.getContext().put(ServletActionContext.PAGE_CONTEXT, pageContext);
-            usedJspFactory = true;
-        }
-
-        try {
-            String encoding = getEncoding(finalLocation);
-            String contentType = getContentType(finalLocation);
-
-            if (encoding != null) {
-                contentType = contentType + ";charset=" + encoding;
-            }
-
-            Template t = getTemplate(stack, velocityManager.getVelocityEngine(), invocation, finalLocation, encoding);
-
-            Context context = createContext(velocityManager, stack, request, response, finalLocation);
-            Writer writer = new OutputStreamWriter(response.getOutputStream(), encoding);
-
-
-            response.setContentType(contentType);
-
-            t.merge(context, writer);
-
-            // always flush the writer (we used to only flush it if this was a jspWriter, but someone asked
-            // to do it all the time (WW-829). Since Velocity support is being deprecated, we'll oblige :)
-            writer.flush();
-        } catch (Exception e) {
-            LOG.error("Unable to render velocity template: '{}'", finalLocation, e);
-            throw e;
-        } finally {
-            if (usedJspFactory) {
-                jspFactory.releasePageContext(pageContext);
-            }
-        }
-    }
-
-    /**
-     * Retrieve the content type for this template.
-     * <p/>
-     * People can override this method if they want to provide specific content types for specific templates (eg text/xml).
-     *
-     * @return The content type associated with this template (default "text/html")
-     */
-    protected String getContentType(String templateLocation) {
-        return "text/html";
-    }
-
-    /**
-     * Retrieve the encoding for this template.
-     * <p/>
-     * People can override this method if they want to provide specific encodings for specific templates.
-     *
-     * @return The encoding associated with this template (defaults to the value of 'struts.i18n.encoding' property)
-     */
-    protected String getEncoding(String templateLocation) {
-        String encoding = defaultEncoding;
-        if (encoding == null) {
-            encoding = System.getProperty("file.encoding");
-        }
-        if (encoding == null) {
-            encoding = "UTF-8";
-        }
-        return encoding;
-    }
-
-    /**
-     * Given a value stack, a Velocity engine, and an action invocation, this method returns the appropriate
-     * Velocity template to render.
-     *
-     * @param stack      the value stack to resolve the location again (when parse equals true)
-     * @param velocity   the velocity engine to process the request against
-     * @param invocation an encapsulation of the action execution state.
-     * @param location   the location of the template
-     * @param encoding   the charset encoding of the template
-     * @return the template to render
-     * @throws Exception when the requested template could not be found
-     */
-    protected Template getTemplate(ValueStack stack, VelocityEngine velocity, ActionInvocation invocation, String location, String encoding) throws Exception {
-        if (!location.startsWith("/")) {
-            location = invocation.getProxy().getNamespace() + "/" + location;
-        }
-
-        Template template = velocity.getTemplate(location, encoding);
-
-        return template;
-    }
-
-    /**
-     * Creates the VelocityContext that we'll use to render this page.
-     *
-     * @param velocityManager a reference to the velocityManager to use
-     * @param stack           the value stack to resolve the location against (when parse equals true)
-     * @param location        the name of the template that is being used
-     * @return the a minted Velocity context.
-     */
-    protected Context createContext(VelocityManager velocityManager, ValueStack stack, HttpServletRequest request, HttpServletResponse response, String location) {
-        return velocityManager.createContext(stack, request, response);
-    }
-}


[3/4] struts git commit: WW-4518 Moves results to dedicated package

Posted by lu...@apache.org.
http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/interceptor/MessageStoreInterceptor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/interceptor/MessageStoreInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/MessageStoreInterceptor.java
index 82d2a55..f10cd48 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/MessageStoreInterceptor.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/MessageStoreInterceptor.java
@@ -27,7 +27,7 @@ import com.opensymphony.xwork2.interceptor.ValidationAware;
 import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-import org.apache.struts2.dispatcher.ServletRedirectResult;
+import org.apache.struts2.result.ServletRedirectResult;
 
 import java.util.ArrayList;
 import java.util.Collection;

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/result/HttpHeaderResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/result/HttpHeaderResult.java b/core/src/main/java/org/apache/struts2/result/HttpHeaderResult.java
new file mode 100644
index 0000000..4745475
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/result/HttpHeaderResult.java
@@ -0,0 +1,210 @@
+/*
+ * $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.result;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.Result;
+import com.opensymphony.xwork2.util.TextParseUtil;
+import com.opensymphony.xwork2.util.ValueStack;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts2.ServletActionContext;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * <!-- START SNIPPET: description -->
+ * <p/>
+ * A custom Result type for setting HTTP headers and status by optionally evaluating against the ValueStack.
+ * This result can also be used to send and error to the client. All the parameters can be evaluated against the ValueStack.
+ * <p/>
+ * <!-- END SNIPPET: description -->
+ * <p/>
+ * <b>This result type takes the following parameters:</b>
+ * <p/>
+ * <!-- START SNIPPET: params -->
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li><b>status</b> - the http servlet response status code that should be set on a response.</li>
+ * <p/>
+ * <li><b>parse</b> - true by default. If set to false, the headers param will not be parsed for Ognl expressions.</li>
+ * <p/>
+ * <li><b>headers</b> - header values.</li>
+ * <p/>
+ * <li><b>error</b> - the http servlet response error code that should be set on a response.</li>
+ * <p/>
+ * <li><b>errorMessage</b> - error message to be set on response if 'error' is set.</li>
+ * </ul>
+ * <p/>
+ * <!-- END SNIPPET: params -->
+ * <p/>
+ * <b>Example:</b>
+ * <p/>
+ * <pre><!-- START SNIPPET: example -->
+ * &lt;result name="success" type="httpheader"&gt;
+ *   &lt;param name="status"&gt;204&lt;/param&gt;
+ *   &lt;param name="headers.a"&gt;a custom header value&lt;/param&gt;
+ *   &lt;param name="headers.b"&gt;another custom header value&lt;/param&gt;
+ * &lt;/result&gt;
+ * <p/>
+ * &lt;result name="proxyRequired" type="httpheader"&gt;
+ *   &lt;param name="error"&gt;305&lt;/param&gt;
+ *   &lt;param name="errorMessage"&gt;this action must be accessed through a prozy&lt;/param&gt;
+ * &lt;/result&gt;
+ * <!-- END SNIPPET: example --></pre>
+ */
+public class HttpHeaderResult implements Result {
+
+    private static final long serialVersionUID = 195648957144219214L;
+    private static final Logger LOG = LogManager.getLogger(HttpHeaderResult.class);
+
+    /**
+     * This result type doesn't have a default param, null is ok to reduce noise in logs
+     */
+    public static final String DEFAULT_PARAM = null;
+
+    private boolean parse = true;
+    private Map<String, String> headers;
+    private int status = -1;
+    private String error = null;
+    private String errorMessage;
+
+    public HttpHeaderResult() {
+        super();
+        headers = new HashMap<>();
+    }
+
+    public HttpHeaderResult(int status) {
+        this();
+        this.status = status;
+        this.parse = false;
+    }
+
+    /**
+     * Sets the http servlet error code that should be set on the response
+     *
+     * @param error the Http error code
+     * @see javax.servlet.http.HttpServletResponse#sendError(int)
+     */
+    public void setError(String error) {
+        this.error = error;
+    }
+
+    /**
+     * Sets the error message that should be set on the reponse
+     *
+     * @param errorMessage error message send to the client
+     * @see javax.servlet.http.HttpServletResponse#sendError(int, String)
+     */
+    public void setErrorMessage(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+
+    /**
+     * Returns a Map of all HTTP headers.
+     *
+     * @return a Map of all HTTP headers.
+     */
+    public Map<String, String> getHeaders() {
+        return headers;
+    }
+
+    /**
+     * Sets whether or not the HTTP header values should be evaluated against the ValueStack (by default they are).
+     *
+     * @param parse <tt>true</tt> if HTTP header values should be evaluated against the ValueStack, <tt>false</tt>
+     *              otherwise.
+     */
+    public void setParse(boolean parse) {
+        this.parse = parse;
+    }
+
+    /**
+     * Sets the http servlet response status code that should be set on a response.
+     *
+     * @param status the Http status code
+     * @see javax.servlet.http.HttpServletResponse#setStatus(int)
+     */
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+    public int getStatus() {
+        return status;
+    }
+
+    /**
+     * Adds an HTTP header to the response
+     *
+     * @param name  header name
+     * @param value header value
+     */
+    public void addHeader(String name, String value) {
+        headers.put(name, value);
+    }
+
+    /**
+     * Sets the optional HTTP response status code and also re-sets HTTP headers after they've
+     * been optionally evaluated against the ValueStack.
+     *
+     * @param invocation an encapsulation of the action execution state.
+     * @throws Exception if an error occurs when re-setting the headers.
+     */
+    public void execute(ActionInvocation invocation) throws Exception {
+        HttpServletResponse response = ServletActionContext.getResponse();
+        ValueStack stack = ActionContext.getContext().getValueStack();
+
+        if (status != -1) {
+            response.setStatus(status);
+        }
+
+        if (headers != null) {
+            for (Map.Entry<String, String> entry : headers.entrySet()) {
+                String value = entry.getValue();
+                String finalValue = parse ? TextParseUtil.translateVariables(value, stack) : value;
+                response.addHeader(entry.getKey(), finalValue);
+            }
+        }
+
+        if (status == -1 && error != null) {
+            int errorCode = -1;
+            try {
+                errorCode = Integer.parseInt(parse ? TextParseUtil.translateVariables(error, stack) : error);
+            } catch (Exception e) {
+                LOG.error("Cannot parse errorCode [{}] value as Integer!", error, e);
+            }
+            if (errorCode != -1) {
+                if (errorMessage != null) {
+                    String finalMessage = parse ? TextParseUtil.translateVariables(errorMessage, stack) : errorMessage;
+                    response.sendError(errorCode, finalMessage);
+                } else {
+                    response.sendError(errorCode);
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/result/PlainTextResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/result/PlainTextResult.java b/core/src/main/java/org/apache/struts2/result/PlainTextResult.java
new file mode 100644
index 0000000..44d9302
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/result/PlainTextResult.java
@@ -0,0 +1,183 @@
+/*
+ * $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.result;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.nio.charset.Charset;
+
+/**
+ * <!-- START SNIPPET: description -->
+ *
+ * A result that send the content out as plain text. Useful typically when needed
+ * to display the raw content of a JSP or Html file for example.
+ *
+ * <!-- END SNIPPET: description -->
+ *
+ *
+ * <!-- START SNIPPET: params -->
+ *
+ * <ul>
+ *  <li>location (default) = location of the file (jsp/html) to be displayed as plain text.</li>
+ *  <li>charSet (optional) = character set to be used. This character set will be used to set the
+ *  response type (eg. Content-Type=text/plain; charset=UTF-8) and when reading
+ *  using a Reader. Some example of charSet would be UTF-8, ISO-8859-1 etc.
+ * </ul>
+ *
+ * <!-- END SNIPPET: params -->
+ *
+ *
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ *
+ * &lt;action name="displayJspRawContent" &gt;
+ *   &lt;result type="plainText"&gt;/myJspFile.jsp&lt;/result&gt;
+ * &lt;/action&gt;
+ *
+ *
+ * &lt;action name="displayJspRawContent" &gt;
+ *   &lt;result type="plainText"&gt;
+ *      &lt;param name="location"&gt;/myJspFile.jsp&lt;/param&gt;
+ *      &lt;param name="charSet"&gt;UTF-8&lt;/param&gt;
+ *   &lt;/result&gt;
+ * &lt;/action&gt;
+ *
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ *
+ */
+public class PlainTextResult extends StrutsResultSupport {
+
+    public static final int BUFFER_SIZE = 1024;
+
+    private static final Logger LOG = LogManager.getLogger(PlainTextResult.class);
+
+    private static final long serialVersionUID = 3633371605905583950L;
+
+    private String charSet;
+
+    public PlainTextResult() {
+        super();
+    }
+
+    public PlainTextResult(String location) {
+        super(location);
+    }
+
+    /**
+     * Set the character set
+     *
+     * @return The character set
+     */
+    public String getCharSet() {
+        return charSet;
+    }
+
+    /**
+     * Set the character set
+     *
+     * @param charSet The character set
+     */
+    public void setCharSet(String charSet) {
+        this.charSet = charSet;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.struts2.result.StrutsResultSupport#doExecute(java.lang.String, com.opensymphony.xwork2.ActionInvocation)
+     */
+    protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
+        // verify charset
+        Charset charset = readCharset();
+
+        HttpServletResponse response = (HttpServletResponse) invocation.getInvocationContext().get(HTTP_RESPONSE);
+
+        applyCharset(charset, response);
+        applyAdditionalHeaders(response);
+        String location = adjustLocation(finalLocation);
+
+        try (PrintWriter writer = response.getWriter();
+                InputStream resourceAsStream = readStream(invocation, location);
+                InputStreamReader reader = new InputStreamReader(resourceAsStream, charset == null ? Charset.defaultCharset() : charset)) {
+            logWrongStream(finalLocation, resourceAsStream);
+            sendStream(writer, reader);
+        }
+    }
+
+    protected InputStream readStream(ActionInvocation invocation, String location) {
+        ServletContext servletContext = (ServletContext) invocation.getInvocationContext().get(SERVLET_CONTEXT);
+        return servletContext.getResourceAsStream(location);
+    }
+
+    protected void logWrongStream(String finalLocation, InputStream resourceAsStream) {
+        if (resourceAsStream == null) {
+            LOG.warn("Resource at location [{}] cannot be obtained (return null) from ServletContext !!!", finalLocation);
+        }
+    }
+
+    protected void sendStream(PrintWriter writer, InputStreamReader reader) throws IOException {
+        char[] buffer = new char[BUFFER_SIZE];
+        int charRead;
+        while((charRead = reader.read(buffer)) != -1) {
+            writer.write(buffer, 0, charRead);
+        }
+    }
+
+    protected String adjustLocation(String location) {
+        if (location.charAt(0) != '/') {
+            return "/" + location;
+        }
+        return location;
+    }
+
+    protected void applyAdditionalHeaders(HttpServletResponse response) {
+        response.setHeader("Content-Disposition", "inline");
+    }
+
+    protected void applyCharset(Charset charset, HttpServletResponse response) {
+        if (charset != null) {
+            response.setContentType("text/plain; charset=" + charSet);
+        } else {
+            response.setContentType("text/plain");
+        }
+    }
+
+    protected Charset readCharset() {
+        Charset charset = null;
+        if (charSet != null) {
+            if (Charset.isSupported(charSet)) {
+                charset = Charset.forName(charSet);
+            } else {
+                LOG.warn("charset [{}] is not recognized", charset);
+                charset = null;
+            }
+        }
+        return charset;
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/result/PostbackResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/result/PostbackResult.java b/core/src/main/java/org/apache/struts2/result/PostbackResult.java
new file mode 100644
index 0000000..ee14384
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/result/PostbackResult.java
@@ -0,0 +1,232 @@
+/*
+ * $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.result;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.inject.Inject;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.dispatcher.mapper.ActionMapper;
+import org.apache.struts2.dispatcher.mapper.ActionMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Map;
+
+/**
+ * <!-- START SNIPPET: description -->
+ * A result that renders the current request parameters as a form which
+ * immediately submits a <a href="http://en.wikipedia.org/wiki/Postback">postback</a>
+ * to the specified destination.
+ * <!-- END SNIPPET: description -->
+ * <p/>
+ * <b>Parameters:</b>
+ * <!-- START SNIPPET: params -->
+ * <ul>
+ *     <li>location - http location to post the form</li>
+ *     <li>prependServletContext (true|false) -  when location is relative, controls if to add Servlet Context, default "true"</li>
+ *     <li>actionName - action name to post the form (resolved as an expression)</li>
+ *     <li>namespace - action's namespace to use (resolved as an expression)</li>
+ *     <li>method - actions' method to use (resolved as an expression)</li>
+ *     <li>cache (true|false) - when set to true adds cache control headers, default "true"</li>
+ *     <li>parse (true|false) - when set to true actionName, namespace and method are parsed, default "true"</li>
+ * </ul>
+ * <!-- END SNIPPET: params -->
+ * <p/>
+ * <b>Examples:</b>
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ * &lt;action name="registerThirdParty" &gt;
+ *   &lt;result type="postback"&gt;https://www.example.com/register&lt;/result&gt;
+ * &lt;/action&gt;
+ *
+ * &lt;action name="registerThirdParty" &gt;
+ *   &lt;result type="postback"&gt;
+ *     &lt;param name="namespace"&gt;/secure&lt;/param&gt;
+ *     &lt;param name="actionName"&gt;register2&lt;/param&gt;
+ *   &lt;/result&gt;
+ * &lt;/action&gt;
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ */
+public class PostbackResult extends StrutsResultSupport {
+
+    private String actionName;
+    private String namespace;
+    private String method;
+    private boolean prependServletContext = true;
+    private boolean cache = true;
+
+    protected ActionMapper actionMapper;
+
+    @Override
+    protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
+        ActionContext ctx = invocation.getInvocationContext();
+        HttpServletRequest request = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
+        HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);
+
+        // Cache?
+        if (!cache) {
+            response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1
+            response.setHeader("Pragma", "no-cache"); // HTTP 1.0
+            response.setDateHeader("Expires", 0); // Proxies
+        }
+
+        // Render
+        PrintWriter pw = new PrintWriter(response.getOutputStream());
+        pw.write("<!DOCTYPE html><html><body><form action=\"" + finalLocation + "\" method=\"POST\">");
+        writeFormElements(request, pw);
+        writePrologueScript(pw);
+        pw.write("</html>");
+        pw.flush();
+    }
+
+    @Override
+    public void execute(ActionInvocation invocation) throws Exception {
+        String postbackUri = makePostbackUri(invocation);
+        setLocation(postbackUri);
+        super.execute(invocation);
+    }
+
+    /**
+     * Determines if the specified form input element should be included.
+     *
+     * @param name the input element name
+     * @param values the input element values
+     * @return {@code true} if included; otherwise {@code false}
+     */
+    protected boolean isElementIncluded(String name, String[] values) {
+        return !name.startsWith("action:");
+    }
+
+    protected String makePostbackUri(ActionInvocation invocation) {
+        ActionContext ctx = invocation.getInvocationContext();
+        HttpServletRequest request = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
+        String postbackUri;
+
+        if (actionName != null) {
+            actionName = conditionalParse(actionName, invocation);
+            if (namespace == null) {
+                namespace = invocation.getProxy().getNamespace();
+            } else {
+                namespace = conditionalParse(namespace, invocation);
+            }
+            if (method == null) {
+                method = "";
+            } else {
+                method = conditionalParse(method, invocation);
+            }
+            postbackUri = request.getContextPath() + actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null));
+        } else {
+            String location = getLocation();
+            // Do not prepend if the URL is a FQN
+            if (!location.matches("^([a-zA-z]+:)?//.*")) {
+                // If the URL is relative to the servlet context, prepend the servlet context path
+                if (prependServletContext && (request.getContextPath() != null) && (request.getContextPath().length() > 0)) {
+                    location = request.getContextPath() + location;
+                }
+            }
+            postbackUri = location;
+        }
+
+        return postbackUri;
+    }
+
+    @Inject
+    public final void setActionMapper(ActionMapper mapper) {
+        this.actionMapper = mapper;
+    }
+
+    /**
+     * Sets the name of the destination action.
+     *
+     * @param actionName the action name
+     */
+    public final void setActionName(String actionName) {
+        this.actionName = actionName;
+    }
+
+    /**
+     * Stores the option to cache the rendered intermediate page. The default
+     * is {@code true}.
+     *
+     * @return {@code true} to cache; otherwise {@code false}
+     */
+    public final void setCache(boolean cache) {
+        this.cache = cache;
+    }
+
+    /**
+     * Sets the method of the destination action.
+     *
+     * @param method the method
+     */
+    public final void setMethod(String method) {
+        this.method = method;
+    }
+
+    /**
+     * Sets the namespace of the destination action.
+     *
+     * @param namespace the namespace
+     */
+    public final void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+
+    public final void setPrependServletContext(boolean prependServletContext) {
+        this.prependServletContext = prependServletContext;
+    }
+
+    protected void writeFormElement(PrintWriter pw, String name, String[] values) throws UnsupportedEncodingException {
+        for (String value : values) {
+            String encName = URLEncoder.encode(name, "UTF-8");
+            String encValue = URLEncoder.encode(value, "UTF-8");
+            pw.write("<input type=\"hidden\" name=\"" + encName + "\" value=\"" + encValue + "\"/>");
+        }
+    }
+
+    private void writeFormElements(HttpServletRequest request, PrintWriter pw) throws UnsupportedEncodingException {
+        Map<String, String[]> params = request.getParameterMap();
+        for (String name : params.keySet()) {
+            String[] values = params.get(name);
+            if (isElementIncluded(name, values)) {
+                writeFormElement(pw, name, values);
+            }
+        }
+    }
+
+    /**
+     * Outputs the script after the form has been emitted. The default script
+     * is to submit the form using a JavaScript time out that immediately expires.
+     *
+     * @param pw the print writer
+     */
+    protected void writePrologueScript(PrintWriter pw) {
+        pw.write("<script>");
+        pw.write("setTimeout(function(){document.forms[0].submit();},0);");
+        pw.write("</script>");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/result/ServletActionRedirectResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/result/ServletActionRedirectResult.java b/core/src/main/java/org/apache/struts2/result/ServletActionRedirectResult.java
new file mode 100644
index 0000000..2d12606
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/result/ServletActionRedirectResult.java
@@ -0,0 +1,227 @@
+/*
+ * $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.result;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler;
+import org.apache.struts2.dispatcher.mapper.ActionMapper;
+import org.apache.struts2.dispatcher.mapper.ActionMapping;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * <!-- START SNIPPET: description -->
+ *
+ * This result uses the {@link ActionMapper} provided by the
+ * {@link ActionMapperFactory} to redirect the browser to a URL that invokes the
+ * specified action and (optional) namespace. This is better than the
+ * {@link ServletRedirectResult} because it does not require you to encode the
+ * URL patterns processed by the {@link ActionMapper} in to your struts.xml
+ * configuration files. This means you can change your URL patterns at any point
+ * and your application will still work. It is strongly recommended that if you
+ * are redirecting to another action, you use this result rather than the
+ * standard redirect result.
+ *
+ * See examples below for an example of how request parameters could be passed
+ * in.
+ *
+ * <!-- END SNIPPET: description -->
+ *
+ * <b>This result type takes the following parameters:</b>
+ *
+ * <!-- START SNIPPET: params -->
+ *
+ * <ul>
+ *
+ * <li><b>actionName (default)</b> - The name of the action that will be
+ * redirected to.</li>
+ *
+ * <li><b>namespace</b> - Used to determine which namespace the action is in
+ * that we're redirecting to.  If namespace is null, the default will be the
+ * current namespace.</li>
+ *
+ * <li><b>suppressEmptyParameters</b> - Optional boolean (defaults to false) that
+ * can prevent parameters with no values from being included in the redirect
+ * URL.</li>
+ *
+ * <li><b>parse</b> - Boolean, true by default.  If set to false, the actionName
+ * param will not be parsed for Ognl expressions.</li>
+ *
+ * <li><b>anchor</b> - Optional.  Also known as "fragment" or colloquially as
+ * "hash".  You can specify an anchor for a result.</li>
+ * </ul>
+ *
+ * <!-- END SNIPPET: params -->
+ *
+ * <b>Example:</b>
+ *
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ * &lt;package name="public" extends="struts-default"&gt;
+ *     &lt;action name="login" class="..."&gt;
+ *         &lt;!-- Redirect to another namespace --&gt;
+ *         &lt;result type="redirectAction"&gt;
+ *             &lt;param name="actionName"&gt;dashboard&lt;/param&gt;
+ *             &lt;param name="namespace"&gt;/secure&lt;/param&gt;
+ *         &lt;/result&gt;
+ *     &lt;/action&gt;
+ * &lt;/package&gt;
+ *
+ * &lt;package name="secure" extends="struts-default" namespace="/secure"&gt;
+ *     &lt;-- Redirect to an action in the same namespace --&gt;
+ *     &lt;action name="dashboard" class="..."&gt;
+ *         &lt;result&gt;dashboard.jsp&lt;/result&gt;
+ *         &lt;result name="error" type="redirectAction"&gt;error&lt;/result&gt;
+ *     &lt;/action&gt;
+ *
+ *     &lt;action name="error" class="..."&gt;
+ *         &lt;result&gt;error.jsp&lt;/result&gt;
+ *     &lt;/action&gt;
+ * &lt;/package&gt;
+ *
+ * &lt;package name="passingRequestParameters" extends="struts-default" namespace="/passingRequestParameters"&gt;
+ *    &lt;!-- Pass parameters (reportType, width and height) --&gt;
+ *    &lt;!--
+ *    The redirectAction url generated will be :
+ *    /genReport/generateReport.action?reportType=pie&width=100&height=100#summary
+ *    --&gt;
+ *    &lt;action name="gatherReportInfo" class="..."&gt;
+ *       &lt;result name="showReportResult" type="redirectAction"&gt;
+ *          &lt;param name="actionName"&gt;generateReport&lt;/param&gt;
+ *          &lt;param name="namespace"&gt;/genReport&lt;/param&gt;
+ *          &lt;param name="reportType"&gt;pie&lt;/param&gt;
+ *          &lt;param name="width"&gt;100&lt;/param&gt;
+ *          &lt;param name="height"&gt;100&lt;/param&gt;
+ *          &lt;param name="empty"&gt;&lt;/param&gt;
+ *          &lt;param name="suppressEmptyParameters"&gt;true&lt;/param&gt;
+ *          &lt;param name="anchor"&gt;summary&lt;/param&gt;
+ *       &lt;/result&gt;
+ *    &lt;/action&gt;
+ * &lt;/package&gt;
+ *
+ *
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ *
+ * @see ActionMapper
+ */
+public class ServletActionRedirectResult extends ServletRedirectResult implements ReflectionExceptionHandler {
+
+    private static final long serialVersionUID = -9042425229314584066L;
+
+    /* The default parameter */
+    public static final String DEFAULT_PARAM = "actionName";
+
+    protected String actionName;
+    protected String namespace;
+    protected String method;
+
+    public ServletActionRedirectResult() {
+        super();
+    }
+
+    public ServletActionRedirectResult(String actionName) {
+        this(null, actionName, null, null);
+    }
+
+    public ServletActionRedirectResult(String actionName, String method) {
+        this(null, actionName, method, null);
+    }
+
+    public ServletActionRedirectResult(String namespace, String actionName, String method) {
+        this(namespace, actionName, method, null);
+    }
+
+    public ServletActionRedirectResult(String namespace, String actionName, String method, String anchor) {
+        super(null, anchor);
+        this.namespace = namespace;
+        this.actionName = actionName;
+        this.method = method;
+    }
+
+    /**
+     * @see com.opensymphony.xwork2.Result#execute(com.opensymphony.xwork2.ActionInvocation)
+     */
+    public void execute(ActionInvocation invocation) throws Exception {
+        actionName = conditionalParse(actionName, invocation);
+        if (namespace == null) {
+            namespace = invocation.getProxy().getNamespace();
+        } else {
+            namespace = conditionalParse(namespace, invocation);
+        }
+        if (method == null) {
+            method = "";
+        } else {
+            method = conditionalParse(method, invocation);
+        }
+
+        String tmpLocation = actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null));
+
+        setLocation(tmpLocation);
+
+        super.execute(invocation);
+    }
+
+    /**
+     * Sets the action name
+     *
+     * @param actionName The name
+     */
+    public void setActionName(String actionName) {
+        this.actionName = actionName;
+    }
+
+    /**
+     * Sets the namespace
+     *
+     * @param namespace The namespace
+     */
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+
+    /**
+     * Sets the method
+     *
+     * @param method The method
+     */
+    public void setMethod(String method) {
+        this.method = method;
+    }
+
+    protected List<String> getProhibitedResultParams() {
+        return Arrays.asList(
+                DEFAULT_PARAM,
+                "namespace",
+                "method",
+                "encode",
+                "parse",
+                "location",
+                "prependServletContext",
+                "suppressEmptyParameters",
+                "anchor",
+                "statusCode"
+        );
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/result/ServletDispatcherResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/result/ServletDispatcherResult.java b/core/src/main/java/org/apache/struts2/result/ServletDispatcherResult.java
new file mode 100644
index 0000000..8d20e99
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/result/ServletDispatcherResult.java
@@ -0,0 +1,174 @@
+/*
+ * $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.result;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.inject.Inject;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsStatics;
+import org.apache.struts2.views.util.UrlHelper;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.PageContext;
+import java.util.Map;
+
+
+/**
+ * <!-- START SNIPPET: description -->
+ *
+ * Includes or forwards to a view (usually a jsp). Behind the scenes Struts
+ * will use a RequestDispatcher, where the target servlet/JSP receives the same
+ * request/response objects as the original servlet/JSP. Therefore, you can pass
+ * data between them using request.setAttribute() - the Struts action is
+ * available.
+ * <p/>
+ * There are three possible ways the result can be executed:
+ *
+ * <ul>
+ *
+ * <li>If we are in the scope of a JSP (a PageContext is available), PageContext's
+ * {@link PageContext#include(String) include} method is called.</li>
+ *
+ * <li>If there is no PageContext and we're not in any sort of include (there is no
+ * "javax.servlet.include.servlet_path" in the request attributes), then a call to
+ * {@link RequestDispatcher#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse) forward}
+ * is made.</li>
+ *
+ * <li>Otherwise, {@link RequestDispatcher#include(javax.servlet.ServletRequest, javax.servlet.ServletResponse) include}
+ * is called.</li>
+ *
+ * </ul>
+ * <!-- END SNIPPET: description -->
+ *
+ * <b>This result type takes the following parameters:</b>
+ *
+ * <!-- START SNIPPET: params -->
+ *
+ * <ul>
+ *
+ * <li><b>location (default)</b> - the location to go to after execution (ex. jsp).</li>
+ *
+ * <li><b>parse</b> - true by default. If set to false, the location param will not be parsed for Ognl expressions.</li>
+ *
+ * </ul>
+ *
+ * <!-- END SNIPPET: params -->
+ *
+ * <b>Example:</b>
+ *
+ * <pre><!-- START SNIPPET: example -->
+ * &lt;result name="success" type="dispatcher"&gt;
+ *   &lt;param name="location"&gt;foo.jsp&lt;/param&gt;
+ * &lt;/result&gt;
+ * <!-- END SNIPPET: example --></pre>
+ *
+ * This result follows the same rules from {@link StrutsResultSupport}.
+ *
+ * @see javax.servlet.RequestDispatcher
+ */
+public class ServletDispatcherResult extends StrutsResultSupport {
+
+    private static final long serialVersionUID = -1970659272360685627L;
+
+    private static final Logger LOG = LogManager.getLogger(ServletDispatcherResult.class);
+
+    private UrlHelper urlHelper;
+
+    public ServletDispatcherResult() {
+        super();
+    }
+
+    public ServletDispatcherResult(String location) {
+        super(location);
+    }
+
+    @Inject
+    public void setUrlHelper(UrlHelper urlHelper) {
+        this.urlHelper = urlHelper;
+    }
+
+    /**
+     * Dispatches to the given location. Does its forward via a RequestDispatcher. If the
+     * dispatch fails a 404 error will be sent back in the http response.
+     *
+     * @param finalLocation the location to dispatch to.
+     * @param invocation    the execution state of the action
+     * @throws Exception if an error occurs. If the dispatch fails the error will go back via the
+     *                   HTTP request.
+     */
+    public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
+        LOG.debug("Forwarding to location: {}", finalLocation);
+
+        PageContext pageContext = ServletActionContext.getPageContext();
+
+        if (pageContext != null) {
+            pageContext.include(finalLocation);
+        } else {
+            HttpServletRequest request = ServletActionContext.getRequest();
+            HttpServletResponse response = ServletActionContext.getResponse();
+            RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation);
+
+            //add parameters passed on the location to #parameters
+            // see WW-2120
+            if (StringUtils.isNotEmpty(finalLocation) && finalLocation.indexOf("?") > 0) {
+                String queryString = finalLocation.substring(finalLocation.indexOf("?") + 1);
+                Map<String, Object> parameters = getParameters(invocation);
+                Map<String, Object> queryParams = urlHelper.parseQueryString(queryString, true);
+                if (queryParams != null && !queryParams.isEmpty())
+                    parameters.putAll(queryParams);
+            }
+
+            // if the view doesn't exist, let's do a 404
+            if (dispatcher == null) {
+                response.sendError(404, "result '" + finalLocation + "' not found");
+                return;
+            }
+
+            //if we are inside an action tag, we always need to do an include
+            Boolean insideActionTag = (Boolean) ObjectUtils.defaultIfNull(request.getAttribute(StrutsStatics.STRUTS_ACTION_TAG_INVOCATION), Boolean.FALSE);
+
+            // If we're included, then include the view
+            // Otherwise do forward
+            // This allow the page to, for example, set content type
+            if (!insideActionTag && !response.isCommitted() && (request.getAttribute("javax.servlet.include.servlet_path") == null)) {
+                request.setAttribute("struts.view_uri", finalLocation);
+                request.setAttribute("struts.request_uri", request.getRequestURI());
+
+                dispatcher.forward(request, response);
+            } else {
+                dispatcher.include(request, response);
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private Map<String, Object> getParameters(ActionInvocation invocation) {
+        return (Map<String, Object>) invocation.getInvocationContext().getContextMap().get("parameters");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/result/ServletRedirectResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/result/ServletRedirectResult.java b/core/src/main/java/org/apache/struts2/result/ServletRedirectResult.java
new file mode 100644
index 0000000..c3fe70b
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/result/ServletRedirectResult.java
@@ -0,0 +1,323 @@
+/*
+ * $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.result;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.config.entities.ResultConfig;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.reflection.ReflectionException;
+import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.dispatcher.Dispatcher;
+import org.apache.struts2.dispatcher.mapper.ActionMapper;
+import org.apache.struts2.dispatcher.mapper.ActionMapping;
+import org.apache.struts2.views.util.UrlHelper;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.*;
+
+import static javax.servlet.http.HttpServletResponse.SC_FOUND;
+
+/**
+ * <!-- START SNIPPET: description -->
+ * 
+ * Calls the {@link HttpServletResponse#sendRedirect(String) sendRedirect}
+ * method to the location specified. The response is told to redirect the
+ * browser to the specified location (a new request from the client). The
+ * consequence of doing this means that the action (action instance, action
+ * errors, field errors, etc) that was just executed is lost and no longer
+ * available. This is because actions are built on a single-thread model. The
+ * only way to pass data is through the session or with web parameters
+ * (url?name=value) which can be OGNL expressions.
+ * 
+ * <!-- END SNIPPET: description -->
+ * <p/>
+ * <b>This result type takes the following parameters:</b>
+ * 
+ * <!-- START SNIPPET: params -->
+ * 
+ * <ul>
+ * 
+ * <li><b>location (default)</b> - the location to go to after execution.</li>
+ * 
+ * <li><b>parse</b> - true by default. If set to false, the location param will
+ * not be parsed for Ognl expressions.</li>
+ * 
+ * <li><b>anchor</b> - Optional.  Also known as "fragment" or colloquially as 
+ * "hash".  You can specify an anchor for a result.</li>
+ * </ul>
+ * 
+ * <p>
+ * This result follows the same rules from {@link StrutsResultSupport}.
+ * </p>
+ * 
+ * <!-- END SNIPPET: params -->
+ * 
+ * <b>Example:</b>
+ * 
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ * &lt;!--
+ *   The redirect URL generated will be:
+ *   /foo.jsp#FRAGMENT
+ * --&gt;
+ * &lt;result name="success" type="redirect"&gt;
+ *   &lt;param name="location"&gt;foo.jsp&lt;/param&gt;
+ *   &lt;param name="parse"&gt;false&lt;/param&gt;
+ *   &lt;param name="anchor"&gt;FRAGMENT&lt;/param&gt;
+ * &lt;/result&gt;
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ * 
+ */
+public class ServletRedirectResult extends StrutsResultSupport implements ReflectionExceptionHandler {
+
+    private static final long serialVersionUID = 6316947346435301270L;
+
+    private static final Logger LOG = LogManager.getLogger(ServletRedirectResult.class);
+
+    protected boolean prependServletContext = true;
+    protected ActionMapper actionMapper;
+    protected int statusCode = SC_FOUND;
+    protected boolean suppressEmptyParameters = false;
+    protected Map<String, Object> requestParameters = new LinkedHashMap<>();
+    protected String anchor;
+
+    private UrlHelper urlHelper;
+
+    public ServletRedirectResult() {
+        super();
+    }
+
+    public ServletRedirectResult(String location) {
+        this(location, null);
+    }
+
+    public ServletRedirectResult(String location, String anchor) {
+        super(location);
+        this.anchor = anchor;
+    }
+
+    @Inject
+    public void setActionMapper(ActionMapper mapper) {
+        this.actionMapper = mapper;
+    }
+
+    @Inject
+    public void setUrlHelper(UrlHelper urlHelper) {
+        this.urlHelper = urlHelper;
+    }
+
+    public void setStatusCode(int code) {
+        this.statusCode = code;
+    }
+
+    /**
+     * Set the optional anchor value.
+     * 
+     * @param anchor
+     */
+    public void setAnchor(String anchor) {
+        this.anchor = anchor;
+    }
+
+    /**
+     * Sets whether or not to prepend the servlet context path to the redirected
+     * URL.
+     * 
+     * @param prependServletContext <tt>true</tt> to prepend the location with the servlet context path, <tt>false</tt> otherwise.
+     */
+    public void setPrependServletContext(boolean prependServletContext) {
+        this.prependServletContext = prependServletContext;
+    }
+
+    public void execute(ActionInvocation invocation) throws Exception {
+        if (anchor != null) {
+            anchor = conditionalParse(anchor, invocation);
+        }
+        super.execute(invocation);
+    }
+
+    /**
+     * Redirects to the location specified by calling
+     * {@link HttpServletResponse#sendRedirect(String)}.
+     * 
+     * @param finalLocation the location to redirect to.
+     * @param invocation an encapsulation of the action execution state.
+     * @throws Exception if an error occurs when redirecting.
+     */
+    protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
+        ActionContext ctx = invocation.getInvocationContext();
+        HttpServletRequest request = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
+        HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);
+
+        if (isPathUrl(finalLocation)) {
+            if (!finalLocation.startsWith("/")) {
+                ActionMapping mapping = actionMapper.getMapping(request, Dispatcher.getInstance().getConfigurationManager());
+                String namespace = null;
+                if (mapping != null) {
+                    namespace = mapping.getNamespace();
+                }
+
+                if ((namespace != null) && (namespace.length() > 0) && (!"/".equals(namespace))) {
+                    finalLocation = namespace + "/" + finalLocation;
+                } else {
+                    finalLocation = "/" + finalLocation;
+                }
+            }
+
+            // if the URL's are relative to the servlet context, append the servlet context path
+            if (prependServletContext && (request.getContextPath() != null) && (request.getContextPath().length() > 0)) {
+                finalLocation = request.getContextPath() + finalLocation;
+            }
+        }
+        ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(invocation.getResultCode());
+        if (resultConfig != null) {
+            Map<String, String> resultConfigParams = resultConfig.getParams();
+
+            List<String> prohibitedResultParams = getProhibitedResultParams();
+            for (Map.Entry<String, String> e : resultConfigParams.entrySet()) {
+                if (!prohibitedResultParams.contains(e.getKey())) {
+                    Collection<String> values = conditionalParseCollection(e.getValue(), invocation, suppressEmptyParameters);
+                    if (!suppressEmptyParameters || !values.isEmpty()) {
+                        requestParameters.put(e.getKey(), values);
+                    }
+                }
+            }
+        }
+
+        StringBuilder tmpLocation = new StringBuilder(finalLocation);
+        urlHelper.buildParametersString(requestParameters, tmpLocation, "&");
+
+        // add the anchor
+        if (anchor != null) {
+            tmpLocation.append('#').append(anchor);
+        }
+
+        finalLocation = response.encodeRedirectURL(tmpLocation.toString());
+
+        LOG.debug("Redirecting to finalLocation: {}", finalLocation);
+
+        sendRedirect(response, finalLocation);
+    }
+
+    protected List<String> getProhibitedResultParams() {
+        return Arrays.asList(
+                DEFAULT_PARAM,
+                "namespace",
+                "method",
+                "encode",
+                "parse",
+                "location",
+                "prependServletContext",
+                "suppressEmptyParameters",
+                "anchor",
+                "statusCode"
+        );
+    }
+
+    /**
+     * Sends the redirection. Can be overridden to customize how the redirect is
+     * handled (i.e. to use a different status code)
+     * 
+     * @param response The response
+     * @param finalLocation The location URI
+     * @throws IOException
+     */
+    protected void sendRedirect(HttpServletResponse response, String finalLocation) throws IOException {
+        if (SC_FOUND == statusCode) {
+            response.sendRedirect(finalLocation);
+        } else {
+            response.setStatus(statusCode);
+            response.setHeader("Location", finalLocation);
+            response.getWriter().write(finalLocation);
+            response.getWriter().close();
+        }
+
+    }
+
+    /**
+     * Checks if url is simple path or either full url
+     *
+     * @param url string
+     * @return true if it's just a path not a full url
+     */
+    protected boolean isPathUrl(String url) {
+        try {
+            String rawUrl = url;
+            if (url.contains("?")) {
+                rawUrl = url.substring(0, url.indexOf("?"));
+            }
+            URI uri = URI.create(rawUrl.replaceAll(" ", "%20"));
+            if (uri.isAbsolute()) {
+                URL validUrl = uri.toURL();
+                LOG.debug("[{}] is full url, not a path", url);
+                return validUrl.getProtocol() == null;
+            } else {
+                LOG.debug("[{}] isn't absolute URI, assuming it's a path", url);
+                return true;
+            }
+        } catch (IllegalArgumentException e) {
+            LOG.debug("[{}] isn't a valid URL, assuming it's a path", url, e);
+            return true;
+        } catch (MalformedURLException e) {
+            LOG.debug("[{}] isn't a valid URL, assuming it's a path", url, e);
+            return true;
+        }
+    }
+
+    /**
+     * Sets the suppressEmptyParameters option
+     * 
+     * @param suppressEmptyParameters The new value for this option
+     */
+    public void setSuppressEmptyParameters(boolean suppressEmptyParameters) {
+        this.suppressEmptyParameters = suppressEmptyParameters;
+    }
+
+    /**
+     * Adds a request parameter to be added to the redirect url
+     * 
+     * @param key The parameter name
+     * @param value The parameter value
+     */
+    public ServletRedirectResult addParameter(String key, Object value) {
+        requestParameters.put(key, String.valueOf(value));
+        return this;
+    }
+
+    public void handle(ReflectionException ex) {
+        // Only log as debug as they are probably parameters to be appended to the url
+        if (LOG.isDebugEnabled()) {
+            LOG.debug(ex.getMessage(), ex);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/result/StreamResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/result/StreamResult.java b/core/src/main/java/org/apache/struts2/result/StreamResult.java
new file mode 100644
index 0000000..5574cc1
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/result/StreamResult.java
@@ -0,0 +1,329 @@
+/*
+ * $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.result;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.util.ValueStack;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * <!-- START SNIPPET: description -->
+ *
+ * A custom Result type for sending raw data (via an InputStream) directly to the
+ * HttpServletResponse. Very useful for allowing users to download content.
+ *
+ * <!-- END SNIPPET: description -->
+ * <p/>
+ * <b>This result type takes the following parameters:</b>
+ *
+ * <!-- START SNIPPET: params -->
+ *
+ * <ul>
+ *
+ * <li><b>contentType</b> - the stream mime-type as sent to the web browser
+ * (default = <code>text/plain</code>).</li>
+ *
+ * <li><b>contentLength</b> - the stream length in bytes (the browser displays a
+ * progress bar).</li>
+ *
+ * <li><b>contentDisposition</b> - the content disposition header value for
+ * specifing the file name (default = <code>inline</code>, values are typically
+ * <i>attachment;filename="document.pdf"</i>.</li>
+ *
+ * <li><b>inputName</b> - the name of the InputStream property from the chained
+ * action (default = <code>inputStream</code>).</li>
+ *
+ * <li><b>bufferSize</b> - the size of the buffer to copy from input to output
+ * (default = <code>1024</code>).</li>
+ *
+ * <li><b>allowCaching</b> if set to 'false' it will set the headers 'Pragma' and 'Cache-Control'
+ * to 'no-cahce', and prevent client from caching the content. (default = <code>true</code>)
+ *
+ * <li><b>contentCharSet</b> if set to a string, ';charset=value' will be added to the
+ * content-type header, where value is the string set. If set to an expression, the result
+ * of evaluating the expression will be used. If not set, then no charset will be set on
+ * the header</li>
+ * </ul>
+ * 
+ * <p>These parameters can also be set by exposing a similarly named getter method on your Action.  For example, you can
+ * provide <code>getContentType()</code> to override that parameter for the current action.</p>
+ *
+ * <!-- END SNIPPET: params -->
+ *
+ * <b>Example:</b>
+ *
+ * <pre><!-- START SNIPPET: example -->
+ * &lt;result name="success" type="stream"&gt;
+ *   &lt;param name="contentType"&gt;image/jpeg&lt;/param&gt;
+ *   &lt;param name="inputName"&gt;imageStream&lt;/param&gt;
+ *   &lt;param name="contentDisposition"&gt;attachment;filename="document.pdf"&lt;/param&gt;
+ *   &lt;param name="bufferSize"&gt;1024&lt;/param&gt;
+ * &lt;/result&gt;
+ * <!-- END SNIPPET: example --></pre>
+ *
+ */
+public class StreamResult extends StrutsResultSupport {
+
+    private static final long serialVersionUID = -1468409635999059850L;
+
+    protected static final Logger LOG = LogManager.getLogger(StreamResult.class);
+
+    public static final String DEFAULT_PARAM = "inputName";
+
+    protected String contentType = "text/plain";
+    protected String contentLength;
+    protected String contentDisposition = "inline";
+    protected String contentCharSet ;
+    protected String inputName = "inputStream";
+    protected InputStream inputStream;
+    protected int bufferSize = 1024;
+    protected boolean allowCaching = true;
+
+    public StreamResult() {
+        super();
+    }
+
+    public StreamResult(InputStream in) {
+        this.inputStream = in;
+    }
+
+     /**
+     * @return Returns the whether or not the client should be requested to allow caching of the data stream.
+     */
+    public boolean getAllowCaching() {
+        return allowCaching;
+    }
+
+    /**
+     * Set allowCaching to <tt>false</tt> to indicate that the client should be requested not to cache the data stream.
+     * This is set to <tt>false</tt> by default
+     *
+     * @param allowCaching Enable caching.
+     */
+    public void setAllowCaching(boolean allowCaching) {
+        this.allowCaching = allowCaching;
+    }
+
+
+    /**
+     * @return Returns the bufferSize.
+     */
+    public int getBufferSize() {
+        return (bufferSize);
+    }
+
+    /**
+     * @param bufferSize The bufferSize to set.
+     */
+    public void setBufferSize(int bufferSize) {
+        this.bufferSize = bufferSize;
+    }
+
+    /**
+     * @return Returns the contentType.
+     */
+    public String getContentType() {
+        return (contentType);
+    }
+
+    /**
+     * @param contentType The contentType to set.
+     */
+    public void setContentType(String contentType) {
+        this.contentType = contentType;
+    }
+
+    /**
+     * @return Returns the contentLength.
+     */
+    public String getContentLength() {
+        return contentLength;
+    }
+
+    /**
+     * @param contentLength The contentLength to set.
+     */
+    public void setContentLength(String contentLength) {
+        this.contentLength = contentLength;
+    }
+
+    /**
+     * @return Returns the Content-disposition header value.
+     */
+    public String getContentDisposition() {
+        return contentDisposition;
+    }
+
+    /**
+     * @param contentDisposition the Content-disposition header value to use.
+     */
+    public void setContentDisposition(String contentDisposition) {
+        this.contentDisposition = contentDisposition;
+    }
+
+    /**
+     * @return Returns the charset specified by the user
+     */
+    public String getContentCharSet() {
+        return contentCharSet;
+    }
+
+    /**
+     * @param contentCharSet the charset to use on the header when sending the stream
+     */
+    public void setContentCharSet(String contentCharSet) {
+        this.contentCharSet = contentCharSet;
+    }
+
+    /**
+     * @return Returns the inputName.
+     */
+    public String getInputName() {
+        return (inputName);
+    }
+
+    /**
+     * @param inputName The inputName to set.
+     */
+    public void setInputName(String inputName) {
+        this.inputName = inputName;
+    }
+
+    /**
+     * @see StrutsResultSupport#doExecute(java.lang.String, com.opensymphony.xwork2.ActionInvocation)
+     */
+    protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
+
+        // Override any parameters using values on the stack
+        resolveParamsFromStack(invocation.getStack(), invocation);
+
+        // Find the Response in context
+        HttpServletResponse oResponse = (HttpServletResponse) invocation.getInvocationContext().get(HTTP_RESPONSE);
+        try (OutputStream oOutput = oResponse.getOutputStream()) {
+            if (inputStream == null) {
+                // Find the inputstream from the invocation variable stack
+                inputStream = (InputStream) invocation.getStack().findValue(conditionalParse(inputName, invocation));
+            }
+
+            if (inputStream == null) {
+                String msg = ("Can not find a java.io.InputStream with the name [" + inputName + "] in the invocation stack. " +
+                    "Check the <param name=\"inputName\"> tag specified for this action.");
+                LOG.error(msg);
+                throw new IllegalArgumentException(msg);
+            }
+
+            // Set the content type
+            if (contentCharSet != null && ! contentCharSet.equals("")) {
+                oResponse.setContentType(conditionalParse(contentType, invocation)+";charset="+contentCharSet);
+            }
+            else {
+                oResponse.setContentType(conditionalParse(contentType, invocation));
+            }
+
+            // Set the content length
+            if (contentLength != null) {
+                String _contentLength = conditionalParse(contentLength, invocation);
+                int _contentLengthAsInt = -1;
+                try {
+                    _contentLengthAsInt = Integer.parseInt(_contentLength);
+                    if (_contentLengthAsInt >= 0) {
+                        oResponse.setContentLength(_contentLengthAsInt);
+                    }
+                }
+                catch(NumberFormatException e) {
+                    LOG.warn("failed to recognize {} as a number, contentLength header will not be set", _contentLength, e);
+                }
+            }
+
+            // Set the content-disposition
+            if (contentDisposition != null) {
+                oResponse.addHeader("Content-Disposition", conditionalParse(contentDisposition, invocation));
+            }
+
+            // Set the cache control headers if neccessary
+            if (!allowCaching) {
+                oResponse.addHeader("Pragma", "no-cache");
+                oResponse.addHeader("Cache-Control", "no-cache");
+            }
+
+            LOG.debug("Streaming result [{}] type=[{}] length=[{}] content-disposition=[{}] charset=[{}]",
+                    inputName, contentType, contentLength, contentDisposition, contentCharSet);
+
+            // Copy input to output
+        	LOG.debug("Streaming to output buffer +++ START +++");
+            byte[] oBuff = new byte[bufferSize];
+            int iSize;
+            while (-1 != (iSize = inputStream.read(oBuff))) {
+                oOutput.write(oBuff, 0, iSize);
+            }
+        	LOG.debug("Streaming to output buffer +++ END +++");
+
+            // Flush
+            oOutput.flush();
+        }
+    }
+
+    /**
+     * Tries to lookup the parameters on the stack.  Will override any existing parameters
+     *
+     * @param stack The current value stack
+     */
+    protected void resolveParamsFromStack(ValueStack stack, ActionInvocation invocation) {
+        String disposition = stack.findString("contentDisposition");
+        if (disposition != null) {
+            setContentDisposition(disposition);
+        }
+
+        String contentType = stack.findString("contentType");
+        if (contentType != null) {
+            setContentType(contentType);
+        }
+
+        String inputName = stack.findString("inputName");
+        if (inputName != null) {
+            setInputName(inputName);
+        }
+
+        String contentLength = stack.findString("contentLength");
+        if (contentLength != null) {
+            setContentLength(contentLength);
+        }
+
+        Integer bufferSize = (Integer) stack.findValue("bufferSize", Integer.class);
+        if (bufferSize != null) {
+            setBufferSize(bufferSize);
+        }
+
+        if (contentCharSet != null ) {
+            contentCharSet = conditionalParse(contentCharSet, invocation);
+        }
+        else {
+            contentCharSet = stack.findString("contentCharSet");
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/result/StrutsResultSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/result/StrutsResultSupport.java b/core/src/main/java/org/apache/struts2/result/StrutsResultSupport.java
new file mode 100644
index 0000000..bdb1b93
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/result/StrutsResultSupport.java
@@ -0,0 +1,266 @@
+/*
+ * $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.result;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.Result;
+import com.opensymphony.xwork2.util.TextParseUtil;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts2.StrutsStatics;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Collection;
+
+
+/**
+ * <!-- START SNIPPET: javadoc -->
+ *
+ * A base class for all Struts action execution results.
+ * The "location" param is the default parameter, meaning the most common usage of this result would be:
+ * <p/>
+ * This class provides two common parameters for any subclass:
+ * <ul>
+ * <li>location - the location to go to after execution (could be a jsp page or another action).
+ * It can be parsed as per the rules definied in the
+ * {@link TextParseUtil#translateVariables(java.lang.String, com.opensymphony.xwork2.util.ValueStack) translateVariables}
+ * method</li>
+ * <li>parse - true by default. If set to false, the location param will not be parsed for expressions</li>
+ * <li>encode - false by default. If set to false, the location param will not be url encoded. This only have effect when parse is true</li>
+ * </ul>
+ *
+ * <b>NOTE:</b>
+ * The encode param will only have effect when parse is true
+ *
+ * <!-- END SNIPPET: javadoc -->
+ *
+ * <p/>
+ *
+ * <!-- START SNIPPET: example -->
+ *
+ * <p/>
+ * In the struts.xml configuration file, these would be included as:
+ * <p/>
+ * <pre>
+ *  &lt;result name="success" type="redirect"&gt;
+ *      &lt;param name="<b>location</b>"&gt;foo.jsp&lt;/param&gt;
+ *  &lt;/result&gt;</pre>
+ * <p/>
+ * or
+ * <p/>
+ * <pre>
+ *  &lt;result name="success" type="redirect" &gt;
+ *      &lt;param name="<b>location</b>"&gt;foo.jsp?url=${myUrl}&lt;/param&gt;
+ *      &lt;param name="<b>parse</b>"&gt;true&lt;/param&gt;
+ *      &lt;param name="<b>encode</b>"&gt;true&lt;/param&gt;
+ *  &lt;/result&gt;</pre>
+ * <p/>
+ * In the above case, myUrl will be parsed against Ognl Value Stack and then
+ * URL encoded.
+ * <p/>
+ * or when using the default parameter feature
+ * <p/>
+ * <pre>
+ *  &lt;result name="success" type="redirect"&gt;<b>foo.jsp</b>&lt;/result&gt;</pre>
+ * <p/>
+ * You should subclass this class if you're interested in adding more parameters or functionality
+ * to your Result. If you do subclass this class you will need to
+ * override {@link #doExecute(String, ActionInvocation)}.<p>
+ * <p/>
+ * Any custom result can be defined in struts.xml as:
+ * <p/>
+ * <pre>
+ *  &lt;result-types&gt;
+ *      ...
+ *      &lt;result-type name="myresult" class="com.foo.MyResult" /&gt;
+ *  &lt;/result-types&gt;</pre>
+ * <p/>
+ * Please see the {@link com.opensymphony.xwork2.Result} class for more info on Results in general.
+ *
+ * <!-- END SNIPPET: example -->
+ *
+ * @see com.opensymphony.xwork2.Result
+ */
+public abstract class StrutsResultSupport implements Result, StrutsStatics {
+
+    private static final Logger LOG = LogManager.getLogger(StrutsResultSupport.class);
+
+    /** The default parameter */
+    public static final String DEFAULT_PARAM = "location";
+
+    /** use UTF-8 as this is the recommended encoding by W3C to avoid incompatibilities. */
+    public static final String DEFAULT_URL_ENCODING = "UTF-8";
+
+    private boolean parse;
+    private boolean encode;
+    private String location;
+    private String lastFinalLocation;
+
+    public StrutsResultSupport() {
+        this(null, true, false);
+    }
+
+    public StrutsResultSupport(String location) {
+        this(location, true, false);
+    }
+
+    public StrutsResultSupport(String location, boolean parse, boolean encode) {
+        this.location = location;
+        this.parse = parse;
+        this.encode = encode;
+    }
+
+    /**
+     * The location to go to after action execution. This could be a JSP page or another action.
+     * The location can contain OGNL expressions which will be evaulated if the <tt>parse</tt>
+     * parameter is set to <tt>true</tt>.
+     *
+     * @param location the location to go to after action execution.
+     * @see #setParse(boolean)
+     */
+    public void setLocation(String location) {
+        this.location = location;
+    }
+    
+    /**
+     * Gets the location it was created with, mainly for testing
+     */
+    public String getLocation() {
+        return location;
+    }
+
+    /**
+     * Returns the last parsed and encoded location value
+     */
+    public String getLastFinalLocation() {
+        return lastFinalLocation;
+    }
+
+    /**
+     * Set parse to <tt>true</tt> to indicate that the location should be parsed as an OGNL expression. This
+     * is set to <tt>true</tt> by default.
+     *
+     * @param parse <tt>true</tt> if the location parameter is an OGNL expression, <tt>false</tt> otherwise.
+     */
+    public void setParse(boolean parse) {
+        this.parse = parse;
+    }
+
+    /**
+     * Set encode to <tt>true</tt> to indicate that the location should be url encoded. This is set to
+     * <tt>true</tt> by default
+     *
+     * @param encode <tt>true</tt> if the location parameter should be url encode, <tt>false</tt> otherwise.
+     */
+    public void setEncode(boolean encode) {
+        this.encode = encode;
+    }
+
+    /**
+     * Implementation of the <tt>execute</tt> method from the <tt>Result</tt> interface. This will call
+     * the abstract method {@link #doExecute(String, ActionInvocation)} after optionally evaluating the
+     * location as an OGNL evaluation.
+     *
+     * @param invocation the execution state of the action.
+     * @throws Exception if an error occurs while executing the result.
+     */
+    public void execute(ActionInvocation invocation) throws Exception {
+        lastFinalLocation = conditionalParse(location, invocation);
+        doExecute(lastFinalLocation, invocation);
+    }
+
+    /**
+     * Parses the parameter for OGNL expressions against the valuestack
+     *
+     * @param param The parameter value
+     * @param invocation The action invocation instance
+     * @return The resulting string
+     */
+    protected String conditionalParse(String param, ActionInvocation invocation) {
+        if (parse && param != null && invocation != null) {
+            return TextParseUtil.translateVariables(
+                param, 
+                invocation.getStack(),
+                new EncodingParsedValueEvaluator());
+        } else {
+            return param;
+        }
+    }
+
+    /**
+     * As {@link #conditionalParse(String, ActionInvocation)} but does not
+     * convert found object into String. If found object is a collection it is
+     * returned if found object is not a collection it is wrapped in one.
+     * 
+     * @param param
+     * @param invocation
+     * @param excludeEmptyElements
+     * @return
+     */
+    protected Collection<String> conditionalParseCollection(String param, ActionInvocation invocation, boolean excludeEmptyElements) {
+        if (parse && param != null && invocation != null) {
+            return TextParseUtil.translateVariablesCollection(
+                param, 
+                invocation.getStack(),
+                excludeEmptyElements,
+                new EncodingParsedValueEvaluator());
+        } else {
+            Collection<String> collection = new ArrayList<>(1);
+            collection.add(param);
+            return collection;
+        }
+    }
+
+    /**
+     * {@link com.opensymphony.xwork2.util.TextParseUtil.ParsedValueEvaluator} to do URL encoding for found values. To be
+     * used for single strings or collections.
+     * 
+     */
+    private final class EncodingParsedValueEvaluator implements TextParseUtil.ParsedValueEvaluator {
+        public Object evaluate(String parsedValue) {
+            if (encode) {
+                if (parsedValue != null) {
+                    try {
+                        return URLEncoder.encode(parsedValue, DEFAULT_URL_ENCODING);
+                    }
+                    catch(UnsupportedEncodingException e) {
+                        LOG.warn("error while trying to encode [{}]", parsedValue, e);
+                    }
+                }
+            }
+            return parsedValue;
+        }
+    }
+
+    /**
+     * Executes the result given a final location (jsp page, action, etc) and the action invocation
+     * (the state in which the action was executed). Subclasses must implement this class to handle
+     * custom logic for result handling.
+     *
+     * @param finalLocation the location (jsp page, action, etc) to go to.
+     * @param invocation    the execution state of the action.
+     * @throws Exception if an error occurs while executing the result.
+     */
+    protected abstract void doExecute(String finalLocation, ActionInvocation invocation) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/result/VelocityResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/result/VelocityResult.java b/core/src/main/java/org/apache/struts2/result/VelocityResult.java
new file mode 100644
index 0000000..810d191
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/result/VelocityResult.java
@@ -0,0 +1,233 @@
+/*
+ * $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.result;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.ValueStack;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsConstants;
+import org.apache.struts2.views.JspSupportServlet;
+import org.apache.struts2.views.velocity.VelocityManager;
+import org.apache.velocity.Template;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.context.Context;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.JspFactory;
+import javax.servlet.jsp.PageContext;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+
+/**
+ * <!-- START SNIPPET: description -->
+ *
+ * Using the Servlet container's {@link JspFactory}, this result mocks a JSP
+ * execution environment and then displays a Velocity template that will be
+ * streamed directly to the servlet output.
+ *
+ * <!-- END SNIPPET: description -->
+ * <p/>
+ * <b>This result type takes the following parameters:</b>
+ *
+ * <!-- START SNIPPET: params -->
+ *
+ * <ul>
+ *
+ * <li><b>location (default)</b> - the location of the template to process.</li>
+ *
+ * <li><b>parse</b> - true by default. If set to false, the location param will
+ * not be parsed for Ognl expressions.</li>
+ *
+ * </ul>
+ * <p>
+ * This result follows the same rules from {@link StrutsResultSupport}.
+ * </p>
+ *
+ * <!-- END SNIPPET: params -->
+ *
+ * <b>Example:</b>
+ *
+ * <pre><!-- START SNIPPET: example -->
+ * &lt;result name="success" type="velocity"&gt;
+ *   &lt;param name="location"&gt;foo.vm&lt;/param&gt;
+ * &lt;/result&gt;
+ * <!-- END SNIPPET: example --></pre>
+ *
+ */
+public class VelocityResult extends StrutsResultSupport {
+
+    private static final long serialVersionUID = 7268830767762559424L;
+
+    private static final Logger LOG = LogManager.getLogger(VelocityResult.class);
+    
+    private String defaultEncoding;
+    private VelocityManager velocityManager;
+    private JspFactory jspFactory = JspFactory.getDefaultFactory();
+
+    public VelocityResult() {
+        super();
+    }
+
+    public VelocityResult(String location) {
+        super(location);
+    }
+    
+    @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
+    public void setDefaultEncoding(String val) {
+        defaultEncoding = val;
+    }
+    
+    @Inject
+    public void setVelocityManager(VelocityManager mgr) {
+        this.velocityManager = mgr;
+    }
+
+    /**
+     * Creates a Velocity context from the action, loads a Velocity template and executes the
+     * template. Output is written to the servlet output stream.
+     *
+     * @param finalLocation the location of the Velocity template
+     * @param invocation    an encapsulation of the action execution state.
+     * @throws Exception if an error occurs when creating the Velocity context, loading or executing
+     *                   the template or writing output to the servlet response stream.
+     */
+    public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
+        ValueStack stack = ActionContext.getContext().getValueStack();
+
+        HttpServletRequest request = ServletActionContext.getRequest();
+        HttpServletResponse response = ServletActionContext.getResponse();
+        ServletContext servletContext = ServletActionContext.getServletContext();
+        Servlet servlet = JspSupportServlet.jspSupportServlet;
+
+        velocityManager.init(servletContext);
+
+        boolean usedJspFactory = false;
+        PageContext pageContext = (PageContext) ActionContext.getContext().get(ServletActionContext.PAGE_CONTEXT);
+
+        if (pageContext == null && servlet != null) {
+            pageContext = jspFactory.getPageContext(servlet, request, response, null, true, 8192, true);
+            ActionContext.getContext().put(ServletActionContext.PAGE_CONTEXT, pageContext);
+            usedJspFactory = true;
+        }
+
+        try {
+            String encoding = getEncoding(finalLocation);
+            String contentType = getContentType(finalLocation);
+
+            if (encoding != null) {
+                contentType = contentType + ";charset=" + encoding;
+            }
+
+            Template t = getTemplate(stack, velocityManager.getVelocityEngine(), invocation, finalLocation, encoding);
+
+            Context context = createContext(velocityManager, stack, request, response, finalLocation);
+            Writer writer = new OutputStreamWriter(response.getOutputStream(), encoding);
+
+
+            response.setContentType(contentType);
+
+            t.merge(context, writer);
+
+            // always flush the writer (we used to only flush it if this was a jspWriter, but someone asked
+            // to do it all the time (WW-829). Since Velocity support is being deprecated, we'll oblige :)
+            writer.flush();
+        } catch (Exception e) {
+            LOG.error("Unable to render velocity template: '{}'", finalLocation, e);
+            throw e;
+        } finally {
+            if (usedJspFactory) {
+                jspFactory.releasePageContext(pageContext);
+            }
+        }
+    }
+
+    /**
+     * Retrieve the content type for this template.
+     * <p/>
+     * People can override this method if they want to provide specific content types for specific templates (eg text/xml).
+     *
+     * @return The content type associated with this template (default "text/html")
+     */
+    protected String getContentType(String templateLocation) {
+        return "text/html";
+    }
+
+    /**
+     * Retrieve the encoding for this template.
+     * <p/>
+     * People can override this method if they want to provide specific encodings for specific templates.
+     *
+     * @return The encoding associated with this template (defaults to the value of 'struts.i18n.encoding' property)
+     */
+    protected String getEncoding(String templateLocation) {
+        String encoding = defaultEncoding;
+        if (encoding == null) {
+            encoding = System.getProperty("file.encoding");
+        }
+        if (encoding == null) {
+            encoding = "UTF-8";
+        }
+        return encoding;
+    }
+
+    /**
+     * Given a value stack, a Velocity engine, and an action invocation, this method returns the appropriate
+     * Velocity template to render.
+     *
+     * @param stack      the value stack to resolve the location again (when parse equals true)
+     * @param velocity   the velocity engine to process the request against
+     * @param invocation an encapsulation of the action execution state.
+     * @param location   the location of the template
+     * @param encoding   the charset encoding of the template
+     * @return the template to render
+     * @throws Exception when the requested template could not be found
+     */
+    protected Template getTemplate(ValueStack stack, VelocityEngine velocity, ActionInvocation invocation, String location, String encoding) throws Exception {
+        if (!location.startsWith("/")) {
+            location = invocation.getProxy().getNamespace() + "/" + location;
+        }
+
+        Template template = velocity.getTemplate(location, encoding);
+
+        return template;
+    }
+
+    /**
+     * Creates the VelocityContext that we'll use to render this page.
+     *
+     * @param velocityManager a reference to the velocityManager to use
+     * @param stack           the value stack to resolve the location against (when parse equals true)
+     * @param location        the name of the template that is being used
+     * @return the a minted Velocity context.
+     */
+    protected Context createContext(VelocityManager velocityManager, ValueStack stack, HttpServletRequest request, HttpServletResponse response, String location) {
+        return velocityManager.createContext(stack, request, response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerResult.java b/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerResult.java
index e5258e6..0775f55 100644
--- a/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerResult.java
+++ b/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerResult.java
@@ -38,7 +38,7 @@ import freemarker.template.TemplateModelException;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.struts2.ServletActionContext;
 import org.apache.struts2.StrutsStatics;
-import org.apache.struts2.dispatcher.StrutsResultSupport;
+import org.apache.struts2.result.StrutsResultSupport;
 
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/main/resources/struts-default.xml
----------------------------------------------------------------------
diff --git a/core/src/main/resources/struts-default.xml b/core/src/main/resources/struts-default.xml
index 5b82fe0..33057cb 100644
--- a/core/src/main/resources/struts-default.xml
+++ b/core/src/main/resources/struts-default.xml
@@ -168,16 +168,16 @@
     <package name="struts-default" abstract="true">
         <result-types>
             <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
-            <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
+            <result-type name="dispatcher" class="org.apache.struts2.result.ServletDispatcherResult" default="true"/>
             <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
-            <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
-            <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
-            <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
-            <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
-            <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
+            <result-type name="httpheader" class="org.apache.struts2.result.HttpHeaderResult"/>
+            <result-type name="redirect" class="org.apache.struts2.result.ServletRedirectResult"/>
+            <result-type name="redirectAction" class="org.apache.struts2.result.ServletActionRedirectResult"/>
+            <result-type name="stream" class="org.apache.struts2.result.StreamResult"/>
+            <result-type name="velocity" class="org.apache.struts2.result.VelocityResult"/>
             <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
-            <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
-            <result-type name="postback" class="org.apache.struts2.dispatcher.PostbackResult" />
+            <result-type name="plainText" class="org.apache.struts2.result.PlainTextResult" />
+            <result-type name="postback" class="org.apache.struts2.result.PostbackResult" />
         </result-types>
 
         <interceptors>

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/TestConfigurationProvider.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/TestConfigurationProvider.java b/core/src/test/java/org/apache/struts2/TestConfigurationProvider.java
index 1806573..aee8473 100644
--- a/core/src/test/java/org/apache/struts2/TestConfigurationProvider.java
+++ b/core/src/test/java/org/apache/struts2/TestConfigurationProvider.java
@@ -39,7 +39,7 @@ import com.opensymphony.xwork2.security.DefaultExcludedPatternsChecker;
 import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
 import com.opensymphony.xwork2.util.location.LocatableProperties;
 import com.opensymphony.xwork2.validator.ValidationInterceptor;
-import org.apache.struts2.dispatcher.ServletDispatcherResult;
+import org.apache.struts2.result.ServletDispatcherResult;
 import org.apache.struts2.interceptor.TokenInterceptor;
 import org.apache.struts2.interceptor.TokenSessionStoreInterceptor;
 import org.apache.struts2.views.jsp.ui.DoubleValidationAction;


[2/4] struts git commit: WW-4518 Moves results to dedicated package

Posted by lu...@apache.org.
http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/dispatcher/HttpHeaderResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/dispatcher/HttpHeaderResultTest.java b/core/src/test/java/org/apache/struts2/dispatcher/HttpHeaderResultTest.java
deleted file mode 100644
index f4287d0..0000000
--- a/core/src/test/java/org/apache/struts2/dispatcher/HttpHeaderResultTest.java
+++ /dev/null
@@ -1,133 +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.dispatcher;
-
-import com.mockobjects.dynamic.C;
-import com.mockobjects.dynamic.Mock;
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
-import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.StrutsInternalTestCase;
-
-import javax.servlet.http.HttpServletResponse;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * HttpHeaderResultTest
- */
-public class HttpHeaderResultTest extends StrutsInternalTestCase {
-
-    ActionInvocation invocation;
-    HttpHeaderResult result;
-    HttpServletResponse response;
-    Mock responseMock;
-    ReflectionProvider reflectionProvider;
-
-    public void testHeaderValuesAreNotParsedWhenParseIsFalse() throws Exception {
-        Map<String, String> params = new HashMap<String, String>();
-        params.put("headers.foo", "${bar}");
-        params.put("headers.baz", "baz");
-
-        Map<String, String> values = new HashMap<String, String>();
-        values.put("bar", "abc");
-        ActionContext.getContext().getValueStack().push(values);
-
-        reflectionProvider.setProperties(params, result);
-
-        responseMock.expect("addHeader", C.args(C.eq("foo"), C.eq("${bar}")));
-        responseMock.expect("addHeader", C.args(C.eq("baz"), C.eq("baz")));
-        result.setParse(false);
-        result.execute(invocation);
-        responseMock.verify();
-    }
-
-    public void testHeaderValuesAreParsedAndSet() throws Exception {
-        Map<String, String> params = new HashMap<String, String>();
-        params.put("headers.foo", "${bar}");
-        params.put("headers.baz", "baz");
-
-        Map<String, String> values = new HashMap<String, String>();
-        values.put("bar", "abc");
-        ActionContext.getContext().getValueStack().push(values);
-
-        reflectionProvider.setProperties(params, result);
-
-        responseMock.expect("addHeader", C.args(C.eq("foo"), C.eq("abc")));
-        responseMock.expect("addHeader", C.args(C.eq("baz"), C.eq("baz")));
-        result.execute(invocation);
-        responseMock.verify();
-    }
-    
-    public void testErrorMessageIsParsedAndSet() throws Exception {
-        ActionContext.getContext().getValueStack().set("errMsg", "abc");
-        ActionContext.getContext().getValueStack().set("errCode", "404");
-        result.setError("${errCode}");
-        result.setErrorMessage("${errMsg}");
-        
-        responseMock.expect("sendError", C.args(C.eq(404), C.eq("abc")));
-        result.execute(invocation);
-        responseMock.verify();
-    }
-    
-    public void testErrorMessageIsNotParsedAndSet() throws Exception {
-        ActionContext.getContext().getValueStack().set("errMsg", "abc");
-        result.setError("404");
-        result.setParse(false);
-        result.setErrorMessage("${errMsg}");
-        
-        responseMock.expect("sendError", C.args(C.eq(404), C.eq("${errMsg}")));
-        result.execute(invocation);
-        responseMock.verify();
-    }
-
-    public void testStatusIsSet() throws Exception {
-        responseMock.expect("setStatus", C.eq(123));
-        result.setStatus(123);
-        result.execute(invocation);
-        responseMock.verify();
-    }
-    
-    public void testErrorIsSet() throws Exception {
-        responseMock.expect("sendError", C.eq(404));
-        result.setError("404");
-        result.execute(invocation);
-        responseMock.verify();
-    }
-
-    protected void setUp() throws Exception {
-        super.setUp();
-        result = new HttpHeaderResult();
-        responseMock = new Mock(HttpServletResponse.class);
-        response = (HttpServletResponse) responseMock.proxy();
-        invocation = (ActionInvocation) new Mock(ActionInvocation.class).proxy();
-        reflectionProvider = container.getInstance(ReflectionProvider.class);
-        ServletActionContext.setResponse(response);
-    }
-
-    protected void tearDown() throws Exception {
-        super.tearDown();
-        ActionContext.setContext(null);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/dispatcher/PlainTextResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/dispatcher/PlainTextResultTest.java b/core/src/test/java/org/apache/struts2/dispatcher/PlainTextResultTest.java
deleted file mode 100644
index 959458a..0000000
--- a/core/src/test/java/org/apache/struts2/dispatcher/PlainTextResultTest.java
+++ /dev/null
@@ -1,156 +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.dispatcher;
-
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.mock.MockActionInvocation;
-import com.opensymphony.xwork2.util.ClassLoaderUtil;
-import com.opensymphony.xwork2.util.ValueStack;
-import org.apache.struts2.StrutsStatics;
-import org.apache.struts2.StrutsInternalTestCase;
-import org.apache.struts2.views.jsp.AbstractUITagTest;
-import org.apache.struts2.views.jsp.StrutsMockHttpServletResponse;
-import org.apache.struts2.views.jsp.StrutsMockServletContext;
-
-import java.io.InputStream;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-/**
- * Test case for PlainTextResult.
- *
- */
-public class PlainTextResultTest extends StrutsInternalTestCase {
-
-    ValueStack stack;
-    MockActionInvocation invocation;
-    ActionContext context;
-    StrutsMockHttpServletResponse response;
-    PrintWriter writer;
-    StringWriter stringWriter;
-    StrutsMockServletContext servletContext;
-
-
-    public void testPlainText() throws Exception {
-        PlainTextResult result = new PlainTextResult();
-        result.setLocation("/someJspFile.jsp");
-
-        response.setExpectedContentType("text/plain");
-        response.setExpectedHeader("Content-Disposition", "inline");
-
-        try (InputStream jspResourceInputStream =
-            ClassLoaderUtil.getResourceAsStream(
-                "org/apache/struts2/dispatcher/someJspFile.jsp",
-                PlainTextResultTest.class)) {
-            servletContext.setResourceAsStream(jspResourceInputStream);
-            result.execute(invocation);
-
-            String r = AbstractUITagTest.normalize(stringWriter.getBuffer().toString(), true);
-            String e = AbstractUITagTest.normalize(
-                    readAsString("org/apache/struts2/dispatcher/someJspFile.jsp"), true);
-            assertEquals(r, e);
-        }
-    }
-
-    public void testPlainTextWithoutSlash() throws Exception {
-        PlainTextResult result = new PlainTextResult();
-        result.setLocation("someJspFile.jsp");
-
-        response.setExpectedContentType("text/plain");
-        response.setExpectedHeader("Content-Disposition", "inline");
-
-        try (InputStream jspResourceInputStream =
-            ClassLoaderUtil.getResourceAsStream("org/apache/struts2/dispatcher/someJspFile.jsp", PlainTextResultTest.class)) {
-            servletContext.setResourceAsStream(jspResourceInputStream);
-            result.execute(invocation);
-
-            String r = AbstractUITagTest.normalize(stringWriter.getBuffer().toString(), true);
-            String e = AbstractUITagTest.normalize(readAsString("org/apache/struts2/dispatcher/someJspFile.jsp"), true);
-            assertEquals(r, e);
-        }
-    }
-
-    public void testPlainTextWithEncoding() throws Exception {
-        PlainTextResult result = new PlainTextResult();
-        result.setLocation("/someJspFile.jsp");
-        result.setCharSet("UTF-8");
-
-        response.setExpectedContentType("text/plain; charset=UTF-8");
-        response.setExpectedHeader("Content-Disposition", "inline");
-
-        try (InputStream jspResourceInputStream =
-            ClassLoaderUtil.getResourceAsStream(
-                "org/apache/struts2/dispatcher/someJspFile.jsp",
-                PlainTextResultTest.class)) {
-            servletContext.setResourceAsStream(jspResourceInputStream);
-            result.execute(invocation);
-
-            String r = AbstractUITagTest.normalize(stringWriter.getBuffer().toString(), true);
-            String e = AbstractUITagTest.normalize(
-                    readAsString("org/apache/struts2/dispatcher/someJspFile.jsp"), true);
-            assertEquals(r, e);
-        }
-    }
-
-    protected String readAsString(String resource) throws Exception {
-        try (InputStream is = ClassLoaderUtil.getResourceAsStream(resource, PlainTextResultTest.class)) {
-            int sizeRead = 0;
-            byte[] buffer = new byte[1024];
-            StringBuilder stringBuilder = new StringBuilder();
-            while((sizeRead = is.read(buffer)) != -1) {
-                stringBuilder.append(new String(buffer, 0, sizeRead));
-            }
-            return stringBuilder.toString();
-        }
-    }
-
-
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        stringWriter = new StringWriter();
-        writer = new PrintWriter(stringWriter);
-        response = new StrutsMockHttpServletResponse();
-        response.setWriter(writer);
-        servletContext = new StrutsMockServletContext();
-        stack = ActionContext.getContext().getValueStack();
-        context = new ActionContext(stack.getContext());
-        context.put(StrutsStatics.HTTP_RESPONSE, response);
-        context.put(StrutsStatics.SERVLET_CONTEXT, servletContext);
-        invocation = new MockActionInvocation();
-        invocation.setStack(stack);
-        invocation.setInvocationContext(context);
-    }
-
-
-    protected void tearDown() throws Exception {
-        stack = null;
-        invocation = null;
-        context = null;
-        response = null;
-        writer = null;
-        stringWriter = null;
-        servletContext = null;
-
-        super.tearDown();
-    }
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/dispatcher/ServletActionRedirectResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/dispatcher/ServletActionRedirectResultTest.java b/core/src/test/java/org/apache/struts2/dispatcher/ServletActionRedirectResultTest.java
deleted file mode 100644
index 168ea04..0000000
--- a/core/src/test/java/org/apache/struts2/dispatcher/ServletActionRedirectResultTest.java
+++ /dev/null
@@ -1,188 +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.dispatcher;
-
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.ActionProxy;
-import com.opensymphony.xwork2.ObjectFactory;
-import com.opensymphony.xwork2.config.entities.ActionConfig;
-import com.opensymphony.xwork2.config.entities.ResultConfig;
-import com.opensymphony.xwork2.util.ValueStack;
-import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.StrutsInternalTestCase;
-import org.apache.struts2.dispatcher.mapper.ActionMapper;
-import org.apache.struts2.views.util.DefaultUrlHelper;
-import org.easymock.IMocksControl;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.easymock.EasyMock.createControl;
-import static org.easymock.EasyMock.expect;
-
-
-/**
- * @version $Date$ $Id$
- */
-public class ServletActionRedirectResultTest extends StrutsInternalTestCase {
-
-    public void testIncludeParameterInResultWithConditionParseOn() throws Exception {
-
-        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("statusCode", "333")
-			.addParam("param1", "${#value1}")
-            .addParam("param2", "${#value2}")
-            .addParam("param3", "${#value3}")
-            .addParam("anchor", "${#fragment}")
-            .build();
-
-
-
-        ActionContext context = ActionContext.getContext();
-        ValueStack stack = context.getValueStack();
-        context.getContextMap().put("value1", "value 1");
-        context.getContextMap().put("value2", "value 2");
-        context.getContextMap().put("value3", "value 3");
-        MockHttpServletRequest req = new MockHttpServletRequest();
-        MockHttpServletResponse res = new MockHttpServletResponse();
-        context.put(ServletActionContext.HTTP_REQUEST, req);
-        context.put(ServletActionContext.HTTP_RESPONSE, res);
-
-
-        Map<String, ResultConfig> results=  new HashMap<String, ResultConfig>();
-        results.put("myResult", resultConfig);
-
-        ActionConfig actionConfig = new ActionConfig.Builder("", "", "")
-                .addResultConfigs(results).build();
-
-        ServletActionRedirectResult result = new ServletActionRedirectResult();
-        result.setActionName("myAction");
-        result.setNamespace("/myNamespace");
-        result.setParse(true);
-        result.setEncode(false);
-        result.setPrependServletContext(false);
-        result.setAnchor("fragment");
-        result.setUrlHelper(new DefaultUrlHelper());
-
-        IMocksControl control = createControl();
-        ActionProxy mockActionProxy = control.createMock(ActionProxy.class);
-        ActionInvocation mockInvocation = control.createMock(ActionInvocation.class);
-        expect(mockInvocation.getProxy()).andReturn(mockActionProxy);
-        expect(mockInvocation.getResultCode()).andReturn("myResult");
-        expect(mockActionProxy.getConfig()).andReturn(actionConfig);
-        expect(mockInvocation.getInvocationContext()).andReturn(context);
-        expect(mockInvocation.getStack()).andReturn(stack).anyTimes();
-
-        control.replay();
-        result.setActionMapper(container.getInstance(ActionMapper.class));
-        result.execute(mockInvocation);
-        assertEquals("/myNamespace/myAction.action?param1=value+1&param2=value+2&param3=value+3#fragment", res.getRedirectedUrl());
-
-        control.verify();
-    }
-
-    public void testIncludeParameterInResult() throws Exception {
-
-        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")
-            .addParam("anchor", "fragment")
-            .build();
-
-        ActionContext context = ActionContext.getContext();
-        MockHttpServletRequest req = new MockHttpServletRequest();
-        MockHttpServletResponse res = new MockHttpServletResponse();
-        context.put(ServletActionContext.HTTP_REQUEST, req);
-        context.put(ServletActionContext.HTTP_RESPONSE, res);
-
-
-        Map<String, ResultConfig> results=  new HashMap<String, ResultConfig>();
-        results.put("myResult", resultConfig);
-
-        ActionConfig actionConfig = new ActionConfig.Builder("", "", "")
-                .addResultConfigs(results).build();
-
-        ServletActionRedirectResult result = new ServletActionRedirectResult();
-        result.setActionName("myAction");
-        result.setNamespace("/myNamespace");
-        result.setParse(false);
-        result.setEncode(false);
-        result.setPrependServletContext(false);
-        result.setAnchor("fragment");
-        result.setUrlHelper(new DefaultUrlHelper());
-
-        IMocksControl control = createControl();
-        ActionProxy mockActionProxy = control.createMock(ActionProxy.class);
-        ActionInvocation mockInvocation = control.createMock(ActionInvocation.class);
-        expect(mockInvocation.getProxy()).andReturn(mockActionProxy);
-        expect(mockInvocation.getResultCode()).andReturn("myResult");
-        expect(mockActionProxy.getConfig()).andReturn(actionConfig);
-        expect(mockInvocation.getInvocationContext()).andReturn(context);
-
-        control.replay();
-        result.setActionMapper(container.getInstance(ActionMapper.class));
-        result.execute(mockInvocation);
-        assertEquals("/myNamespace/myAction.action?param1=value+1&param2=value+2&param3=value+3#fragment", res.getRedirectedUrl());
-
-        control.verify();
-    }
-
-    public void testBuildResultWithParameter() throws Exception {
-
-        ResultConfig resultConfig = new ResultConfig.Builder("", ServletActionRedirectResult.class.getName())
-            .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")
-            .addParam("anchor", "fragment")
-            .build();
-
-        ObjectFactory factory = container.getInstance(ObjectFactory.class);
-        ServletActionRedirectResult result = (ServletActionRedirectResult) factory.buildResult(resultConfig, new HashMap<String, Object>());
-        assertNotNull(result);
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/dispatcher/ServletDispatcherResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/dispatcher/ServletDispatcherResultTest.java b/core/src/test/java/org/apache/struts2/dispatcher/ServletDispatcherResultTest.java
deleted file mode 100644
index 2d93b8c..0000000
--- a/core/src/test/java/org/apache/struts2/dispatcher/ServletDispatcherResultTest.java
+++ /dev/null
@@ -1,109 +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.dispatcher;
-
-import javax.servlet.RequestDispatcher;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import ognl.Ognl;
-
-import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.StrutsInternalTestCase;
-import org.apache.struts2.StrutsStatics;
-
-import com.mockobjects.dynamic.C;
-import com.mockobjects.dynamic.Mock;
-import com.opensymphony.xwork2.ActionContext;
-
-
-/**
- *
- */
-public class ServletDispatcherResultTest extends StrutsInternalTestCase implements StrutsStatics {
-
-    public void testInclude() {
-        ServletDispatcherResult view = new ServletDispatcherResult();
-        view.setLocation("foo.jsp");
-
-        Mock dispatcherMock = new Mock(RequestDispatcher.class);
-        dispatcherMock.expect("include", C.ANY_ARGS);
-
-        Mock requestMock = new Mock(HttpServletRequest.class);
-        requestMock.expectAndReturn("getAttribute", "struts.actiontag.invocation", null);
-        requestMock.expectAndReturn("getRequestDispatcher", C.args(C.eq("foo.jsp")), dispatcherMock.proxy());
-
-        Mock responseMock = new Mock(HttpServletResponse.class);
-        responseMock.expectAndReturn("isCommitted", Boolean.TRUE);
-
-        ActionContext ac = new ActionContext(Ognl.createDefaultContext(null));
-        ActionContext.setContext(ac);
-        ServletActionContext.setRequest((HttpServletRequest) requestMock.proxy());
-        ServletActionContext.setResponse((HttpServletResponse) responseMock.proxy());
-
-        try {
-            view.execute(null);
-        } catch (Exception e) {
-            e.printStackTrace();
-            fail();
-        }
-
-        dispatcherMock.verify();
-        requestMock.verify();
-        dispatcherMock.verify();
-    }
-
-    public void testSimple() {
-        ServletDispatcherResult view = new ServletDispatcherResult();
-        view.setLocation("foo.jsp");
-
-        Mock dispatcherMock = new Mock(RequestDispatcher.class);
-        dispatcherMock.expect("forward", C.ANY_ARGS);
-
-        Mock requestMock = new Mock(HttpServletRequest.class);
-        requestMock.expectAndReturn("getAttribute", "struts.actiontag.invocation", null);
-        requestMock.expectAndReturn("getAttribute", "javax.servlet.include.servlet_path", null);
-        requestMock.expectAndReturn("getRequestDispatcher", C.args(C.eq("foo.jsp")), dispatcherMock.proxy());
-        requestMock.expect("setAttribute", C.ANY_ARGS); // this is a bad mock, but it works
-        requestMock.expect("setAttribute", C.ANY_ARGS); // this is a bad mock, but it works
-        requestMock.matchAndReturn("getRequestURI", "foo.jsp");
-
-        Mock responseMock = new Mock(HttpServletResponse.class);
-        responseMock.expectAndReturn("isCommitted", Boolean.FALSE);
-
-        ActionContext ac = new ActionContext(Ognl.createDefaultContext(null));
-        ActionContext.setContext(ac);
-        ServletActionContext.setRequest((HttpServletRequest) requestMock.proxy());
-        ServletActionContext.setResponse((HttpServletResponse) responseMock.proxy());
-
-        try {
-            view.execute(null);
-        } catch (Exception e) {
-            e.printStackTrace();
-            fail();
-        }
-
-        dispatcherMock.verify();
-        requestMock.verify();
-        dispatcherMock.verify();
-    }
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/dispatcher/ServletRedirectResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/dispatcher/ServletRedirectResultTest.java b/core/src/test/java/org/apache/struts2/dispatcher/ServletRedirectResultTest.java
deleted file mode 100644
index ab40dfc..0000000
--- a/core/src/test/java/org/apache/struts2/dispatcher/ServletRedirectResultTest.java
+++ /dev/null
@@ -1,360 +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.dispatcher;
-
-import static javax.servlet.http.HttpServletResponse.SC_SEE_OTHER;
-import static org.easymock.EasyMock.createControl;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import ognl.Ognl;
-
-import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.StrutsInternalTestCase;
-import org.apache.struts2.StrutsStatics;
-import org.apache.struts2.dispatcher.mapper.ActionMapper;
-import org.apache.struts2.views.util.DefaultUrlHelper;
-import org.easymock.IMocksControl;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
-
-import com.mockobjects.dynamic.C;
-import com.mockobjects.dynamic.Mock;
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.ActionProxy;
-import com.opensymphony.xwork2.config.entities.ActionConfig;
-import com.opensymphony.xwork2.config.entities.PackageConfig;
-import com.opensymphony.xwork2.config.entities.ResultConfig;
-import com.opensymphony.xwork2.mock.MockActionInvocation;
-import com.opensymphony.xwork2.util.ValueStack;
-
-
-/**
- */
-public class ServletRedirectResultTest extends StrutsInternalTestCase implements StrutsStatics {
-
-    protected ServletRedirectResult view;
-    private Mock requestMock;
-    private Mock responseMock;
-    protected ActionInvocation ai;
-
-
-    public void testAbsoluteRedirect() {
-        view.setLocation("/bar/foo.jsp");
-        responseMock.expectAndReturn("encodeRedirectURL", "/context/bar/foo.jsp", "/context/bar/foo.jsp");
-        responseMock.expect("sendRedirect", C.args(C.eq("/context/bar/foo.jsp")));
-
-        try {
-            view.execute(ai);
-            requestMock.verify();
-            responseMock.verify();
-        } catch (Exception e) {
-            e.printStackTrace();
-            fail();
-        }
-    }
-
-    public void testFullUrlRedirect() {
-        view.setLocation("http://localhost/bar/foo.jsp");
-        responseMock.expectAndReturn("encodeRedirectURL", C.args(C.eq("http://localhost/bar/foo.jsp")), "http://localhost/bar/foo.jsp");
-        responseMock.expect("sendRedirect", C.args(C.eq("http://localhost/bar/foo.jsp")));
-
-        try {
-            view.execute(ai);
-            requestMock.verify();
-            responseMock.verify();
-        } catch (Exception e) {
-            e.printStackTrace();
-            fail();
-        }
-    }
-
-    public void testFullUrlRedirectWithSpaces() {
-        view.setLocation("http://localhost/bar/foo some.pdf");
-        responseMock.expectAndReturn("encodeRedirectURL", C.args(C.eq("http://localhost/bar/foo some.pdf")), "http://localhost/bar/foo some.pdf");
-        responseMock.expect("sendRedirect", C.args(C.eq("http://localhost/bar/foo some.pdf")));
-
-        try {
-            view.execute(ai);
-            requestMock.verify();
-            responseMock.verify();
-        } catch (Exception e) {
-            e.printStackTrace();
-            fail();
-        }
-    }
-
-    public void testFullUrlRedirectWithParams() {
-        view.setLocation("http://localhost/bar/foo.action?param=1&param 2=3");
-        responseMock.expectAndReturn("encodeRedirectURL", C.args(C.eq("http://localhost/bar/foo.action?param=1&param 2=3")), "http://localhost/bar/foo.action?param=1&param 2=3");
-        responseMock.expect("sendRedirect", C.args(C.eq("http://localhost/bar/foo.action?param=1&param 2=3")));
-
-        try {
-            view.execute(ai);
-            requestMock.verify();
-            responseMock.verify();
-        } catch (Exception e) {
-            e.printStackTrace();
-            fail();
-        }
-    }
-
-    public void testAbsoluteRedirect303() {
-        view.setLocation("/bar/foo.jsp");
-        view.setStatusCode(303);
-        responseMock.expectAndReturn("encodeRedirectURL", "/context/bar/foo.jsp", "/context/bar/foo.jsp");
-        responseMock.expect("setStatus", C.args(C.eq(SC_SEE_OTHER)));
-        responseMock.expect("setHeader", C.args(C.eq("Location"), C.eq("/context/bar/foo.jsp")));
-        StringWriter writer = new StringWriter();
-        responseMock.matchAndReturn("getWriter", new PrintWriter(writer));
-
-        try {
-            view.execute(ai);
-            requestMock.verify();
-            responseMock.verify();
-        } catch (Exception e) {
-            e.printStackTrace();
-            fail();
-        }
-        assertEquals("/context/bar/foo.jsp", writer.toString());
-    }
-
-    public void testAbsoluteRedirectAnchor() {
-        view.setLocation("/bar/foo.jsp");
-        view.setAnchor("fragment");
-        responseMock.expectAndReturn("encodeRedirectURL", "/context/bar/foo.jsp#fragment", "/context/bar/foo.jsp#fragment");
-        responseMock.expect("sendRedirect", C.args(C.eq("/context/bar/foo.jsp#fragment")));
-
-        try {
-            view.execute(ai);
-            requestMock.verify();
-            responseMock.verify();
-        } catch (Exception e) {
-            e.printStackTrace();
-            fail();
-        }
-    }
-    public void testPrependServletContextFalse() {
-        view.setLocation("/bar/foo.jsp");
-        view.setPrependServletContext(false);
-        responseMock.expectAndReturn("encodeRedirectURL", "/bar/foo.jsp", "/bar/foo.jsp");
-        responseMock.expect("sendRedirect", C.args(C.eq("/bar/foo.jsp")));
-
-        try {
-            view.execute(ai);
-            requestMock.verify();
-            responseMock.verify();
-        } catch (Exception e) {
-            e.printStackTrace();
-            fail();
-        }
-    }
-
-    public void testRelativeRedirect() throws Exception {
-        view.setLocation("foo.jsp");
-        requestMock.expectAndReturn("getParameterMap", new HashMap());
-        requestMock.expectAndReturn("getServletPath", "/namespace/some.action");
-        requestMock.expectAndReturn("getRequestURI", "/namespace/some.action");
-        requestMock.expectAndReturn("getAttribute", C.ANY_ARGS, null);
-        responseMock.expectAndReturn("encodeRedirectURL", "/context/namespace/foo.jsp", "/context/namespace/foo.jsp");
-        responseMock.expect("sendRedirect", C.args(C.eq("/context/namespace/foo.jsp")));
-
-        view.execute(ai);
-
-        requestMock.verify();
-        responseMock.verify();
-    }
-    
-    public void testMultipleParametersRedirect() throws Exception {
-        view.setLocation("foo.jsp?foo=bar&amp;baz=jim");
-        requestMock.expectAndReturn("getParameterMap", new HashMap());
-        requestMock.expectAndReturn("getServletPath", "/namespace/some.action");
-        requestMock.expectAndReturn("getRequestURI", "/namespace/some.action");
-        requestMock.expectAndReturn("getAttribute", C.ANY_ARGS, null);
-        responseMock.expectAndReturn("encodeRedirectURL", "/context/namespace/foo.jsp?foo=bar&amp;baz=jim", "/context/namespace/foo.jsp?foo=bar&baz=jim");
-        responseMock.expect("sendRedirect", C.args(C.eq("/context/namespace/foo.jsp?foo=bar&baz=jim")));
-
-        view.execute(ai);
-
-        requestMock.verify();
-        responseMock.verify();
-    }
-
-    public void testIncludeParameterInResult() throws Exception {
-
-        ResultConfig resultConfig = new ResultConfig.Builder("", "")
-            .addParam("namespace", "someNamespace")
-            .addParam("encode", "true")
-            .addParam("parse", "true")
-            .addParam("location", "someLocation")
-            .addParam("prependServletContext", "true")
-            .addParam("method", "someMethod")
-            .addParam("statusCode", "333")
-            .addParam("param1", "value 1")
-            .addParam("param2", "value 2")
-            .addParam("param3", "value 3")
-            .build();
-
-        ActionContext context = ActionContext.getContext();
-        MockHttpServletRequest req = new MockHttpServletRequest();
-        MockHttpServletResponse res = new MockHttpServletResponse();
-        context.put(ServletActionContext.HTTP_REQUEST, req);
-        context.put(ServletActionContext.HTTP_RESPONSE, res);
-
-
-        Map<String, ResultConfig> results=  new HashMap<String, ResultConfig>();
-        results.put("myResult", resultConfig);
-
-        ActionConfig actionConfig = new ActionConfig.Builder("", "", "")
-                .addResultConfigs(results).build();
-
-        ServletRedirectResult result = new ServletRedirectResult();
-        result.setLocation("/myNamespace/myAction.action");
-        result.setParse(false);
-        result.setEncode(false);
-        result.setPrependServletContext(false);
-        result.setAnchor("fragment");
-        result.setUrlHelper(new DefaultUrlHelper());
-
-        IMocksControl control = createControl();
-        ActionProxy mockActionProxy = control.createMock(ActionProxy.class);
-        ActionInvocation mockInvocation = control.createMock(ActionInvocation.class);
-        expect(mockInvocation.getProxy()).andReturn(mockActionProxy);
-        expect(mockInvocation.getResultCode()).andReturn("myResult");
-        expect(mockActionProxy.getConfig()).andReturn(actionConfig);
-        expect(mockInvocation.getInvocationContext()).andReturn(context);
-
-        control.replay();
-        result.setActionMapper(container.getInstance(ActionMapper.class));
-        result.execute(mockInvocation);
-        assertEquals("/myNamespace/myAction.action?param1=value+1&param2=value+2&param3=value+3#fragment", res.getRedirectedUrl());
-        control.verify();
-    }
-
-    public void testIncludeCollectionParameterInResult() throws Exception {
-        List<String> paramValues = new ArrayList<String>();
-        paramValues.add("value 1");
-        paramValues.add("");
-        paramValues.add("value 2");
-        paramValues.add(null);
-
-        ResultConfig resultConfig = new ResultConfig.Builder("", "")
-            .addParam("namespace", "someNamespace")
-            .addParam("param", "${list}")
-            .build();
-
-        ActionContext context = ActionContext.getContext();
-        MockHttpServletRequest req = new MockHttpServletRequest();
-        MockHttpServletResponse res = new MockHttpServletResponse();
-        context.put(ServletActionContext.HTTP_REQUEST, req);
-        context.put(ServletActionContext.HTTP_RESPONSE, res);
-
-        Map<String, ResultConfig> results=  new HashMap<String, ResultConfig>();
-        results.put("myResult", resultConfig);
-
-        ActionConfig actionConfig = new ActionConfig.Builder("", "", "")
-                .addResultConfigs(results).build();
-
-        ServletRedirectResult result = new ServletRedirectResult();
-        result.setLocation("/myNamespace/myAction.action");
-        result.setParse(true);
-        result.setEncode(false);
-        result.setPrependServletContext(false);
-        result.setUrlHelper(new DefaultUrlHelper());
-        result.setSuppressEmptyParameters(true);
-
-        IMocksControl control = createControl();
-        ActionProxy mockActionProxy = control.createMock(ActionProxy.class);
-        ActionInvocation mockInvocation = control.createMock(ActionInvocation.class);
-
-        ValueStack mockValueStack = control.createMock(ValueStack.class);
-        Map<String, Object> mockContext = new HashMap<String, Object>();
-        mockContext.put(ActionContext.CONTAINER, container);
-
-        expect(mockInvocation.getStack()).andReturn(mockValueStack);
-        expect(mockValueStack.getContext()).andReturn(mockContext);
-
-        expect(mockInvocation.getStack()).andReturn(mockValueStack);
-
-        expect(mockValueStack.findValue("list")).andReturn(paramValues); // no asType !!!
-
-        expect(mockInvocation.getProxy()).andReturn(mockActionProxy);
-        expect(mockInvocation.getResultCode()).andReturn("myResult");
-        expect(mockActionProxy.getConfig()).andReturn(actionConfig);
-        expect(mockInvocation.getInvocationContext()).andReturn(context);
-
-        expect(mockValueStack.getContext()).andReturn(mockContext);
-
-        control.replay();
-        result.setActionMapper(container.getInstance(ActionMapper.class));
-        result.execute(mockInvocation);
-        assertEquals("/myNamespace/myAction.action?param=value+1&param=value+2", res.getRedirectedUrl());
-        control.verify();
-    }
-
-    protected void setUp() throws Exception {
-        super.setUp();
-        configurationManager.getConfiguration().
-            addPackageConfig("foo", new PackageConfig.Builder("foo").namespace("/namespace").build());
-
-        view = new ServletRedirectResult();
-        container.inject(view);
-
-        responseMock = new Mock(HttpServletResponse.class);
-
-        requestMock = new Mock(HttpServletRequest.class);
-        requestMock.matchAndReturn("getContextPath", "/context");
-
-         ResultConfig resultConfig = new ResultConfig.Builder("", "").build();
-
-        Map<String, ResultConfig> results=  new HashMap<String, ResultConfig>();
-        results.put("myResult", resultConfig);
-
-        ActionConfig actionConfig = new ActionConfig.Builder("", "", "")
-                .addResultConfigs(results).build();
-
-        ActionContext ac = new ActionContext(Ognl.createDefaultContext(null));
-        ac.put(ServletActionContext.HTTP_REQUEST, requestMock.proxy());
-        ac.put(ServletActionContext.HTTP_RESPONSE, responseMock.proxy());
-        MockActionInvocation ai = new MockActionInvocation();
-        ai.setInvocationContext(ac);
-        ai.setResultCode("myResult");
-        ActionProxy mockActionProxy = createNiceMock(ActionProxy.class);
-        ai.setProxy(mockActionProxy);
-        expect(mockActionProxy.getConfig()).andReturn(actionConfig).anyTimes();
-        replay(mockActionProxy);
-        this.ai = ai;
-        ai.setStack(ActionContext.getContext().getValueStack());
-    }
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/dispatcher/StreamResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/dispatcher/StreamResultTest.java b/core/src/test/java/org/apache/struts2/dispatcher/StreamResultTest.java
deleted file mode 100644
index 147823d..0000000
--- a/core/src/test/java/org/apache/struts2/dispatcher/StreamResultTest.java
+++ /dev/null
@@ -1,277 +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.dispatcher;
-
-import com.opensymphony.xwork2.Action;
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.mock.MockActionInvocation;
-import com.opensymphony.xwork2.util.ClassLoaderUtil;
-import com.opensymphony.xwork2.util.ValueStack;
-import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.StrutsInternalTestCase;
-import org.springframework.mock.web.MockHttpServletResponse;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URL;
-
-/**
- * Unit test for {@link StreamResult}.
- *
- */
-public class StreamResultTest extends StrutsInternalTestCase {
-
-    private StreamResult result;
-    private MockHttpServletResponse response;
-
-    private MockActionInvocation mai;
-    private ValueStack stack;
-    private int contentLength = 0;
-
-    public void testStreamResultNoInputName() throws Exception {
-        result.setParse(false);
-        result.setInputName(null);
-
-        try {
-            result.doExecute("helloworld", mai);
-            fail("Should have thrown an IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-            // success
-        }
-    }
-
-    public void testStreamResultParseNoInputName() throws Exception {
-        result.setParse(true);
-        result.setInputName("${top}");
-
-        try {
-            result.doExecute("helloworld", mai);
-            fail("Should have thrown an IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-            // success
-        }
-    }
-
-    public void testStreamResultDefault() throws Exception {
-        result.setInputName("streamForImage");
-
-        result.doExecute("helloworld", mai);
-
-        assertEquals(String.valueOf(contentLength), result.getContentLength());
-        assertEquals("text/plain", result.getContentType());
-        assertEquals("streamForImage", result.getInputName());
-        assertEquals(1024, result.getBufferSize()); // 1024 is default
-        assertEquals("inline", result.getContentDisposition());
-
-        assertEquals("text/plain", response.getContentType());
-        assertEquals(contentLength, response.getContentLength());
-        assertEquals("inline", response.getHeader("Content-disposition"));
-    }
-
-    public void testStreamResultWithCharSet() throws Exception {
-        result.setInputName("streamForImage");
-        result.setContentCharSet("ISO-8859-1");
-        result.doExecute("helloworld", mai);
-
-        assertEquals(String.valueOf(contentLength), result.getContentLength());
-        assertEquals("text/plain", result.getContentType());
-        assertEquals("streamForImage", result.getInputName());
-        assertEquals(1024, result.getBufferSize()); // 1024 is default
-        assertEquals("inline", result.getContentDisposition());
-        assertEquals("text/plain;charset=ISO-8859-1", response.getContentType());
-        assertEquals(contentLength, response.getContentLength());
-        assertEquals("inline", response.getHeader("Content-disposition"));
-    }
-
-    public void testStreamResultWithCharSet2() throws Exception {
-        result.setParse(true);
-        result.setInputName("streamForImage");
-        result.setContentCharSet("${contentCharSetMethod}");
-
-        result.doExecute("helloworld", mai);
-
-        assertEquals(String.valueOf(contentLength), result.getContentLength());
-        assertEquals("text/plain", result.getContentType());
-        assertEquals("streamForImage", result.getInputName());
-        assertEquals(1024, result.getBufferSize()); // 1024 is default
-        assertEquals("inline", result.getContentDisposition());
-        assertEquals("text/plain;charset=UTF-8", response.getContentType());
-        assertEquals(contentLength, response.getContentLength());
-        assertEquals("inline", response.getHeader("Content-disposition"));
-    }
-
-    public void testAllowCacheDefault() throws Exception {
-        result.setInputName("streamForImage");
-
-        result.doExecute("helloworld", mai);
-
-        //check that that headers are not set by default        
-        assertNull(response.getHeader("Pragma"));
-        assertNull(response.getHeader("Cache-Control"));
-    }
-
-     public void testAllowCacheFalse() throws Exception {
-        result.setInputName("streamForImage");
-        result.setAllowCaching(false);
-        result.doExecute("helloworld", mai);
-
-        //check that that headers are not set by default
-        assertEquals("no-cache", response.getHeader("Pragma"));
-        assertEquals("no-cache", response.getHeader("Cache-Control"));
-    }
-
-    public void testStreamResultNoDefault() throws Exception {
-        // it's not easy to test using easymock as we use getOutputStream on HttpServletResponse.
-        result.setParse(false);
-        result.setInputName("streamForImage");
-        result.setBufferSize(128);
-        result.setContentLength(String.valueOf(contentLength));
-        result.setContentDisposition("filename=\"logo.png\"");
-        result.setContentType("image/jpeg");
-
-        result.doExecute("helloworld", mai);
-
-        assertEquals(String.valueOf(contentLength), result.getContentLength());
-        assertEquals("image/jpeg", result.getContentType());
-        assertEquals("streamForImage", result.getInputName());
-        assertEquals(128, result.getBufferSize());
-        assertEquals("filename=\"logo.png\"", result.getContentDisposition());
-
-        assertEquals("image/jpeg", response.getContentType());
-        assertEquals(contentLength, response.getContentLength());
-        assertEquals("filename=\"logo.png\"", response.getHeader("Content-disposition"));
-    }
-
-    public void testStreamResultParse1() throws Exception {
-        ///////////////////
-        result.setParse(true);
-        // ${...} conditionalParse of Result, returns String,
-        // which gets evaluated to the stack, that's how it works.
-        // We use ${streamForImageAsString} that returns "streamForImage"
-        // which is a property that returns an InputStream object.
-        result.setInputName("${streamForImageAsString}");
-        result.setBufferSize(128);
-        result.setContentLength(String.valueOf(contentLength));
-        result.setContentDisposition("filename=\"logo.png\"");
-        result.setContentType("image/jpeg");
-
-        result.doExecute("helloworld", mai);
-
-        assertEquals(String.valueOf(contentLength), result.getContentLength());
-        assertEquals("image/jpeg", result.getContentType());
-        assertEquals("${streamForImageAsString}", result.getInputName());
-        assertEquals(128, result.getBufferSize());
-        assertEquals("filename=\"logo.png\"", result.getContentDisposition());
-
-        assertEquals("image/jpeg", response.getContentType());
-        assertEquals(contentLength, response.getContentLength());
-        assertEquals("filename=\"logo.png\"", response.getHeader("Content-disposition"));
-    }
-
-    public void testStreamResultParse2() throws Exception {
-        ///////////////////
-        result.setParse(true);
-        // This time we dun use ${...}, so streamForImage will
-        // be evaluated to the stack, which should reaturn an
-        // InputStream object, cause there's such a property in
-        // the action object itself.
-        result.setInputName("streamForImage");
-        result.setBufferSize(128);
-        result.setContentLength(String.valueOf(contentLength));
-        result.setContentDisposition("filename=\"logo.png\"");
-        result.setContentType("image/jpeg");
-
-        result.doExecute("helloworld", mai);
-
-        assertEquals(String.valueOf(contentLength), result.getContentLength());
-        assertEquals("image/jpeg", result.getContentType());
-        assertEquals("streamForImage", result.getInputName());
-        assertEquals(128, result.getBufferSize());
-        assertEquals("filename=\"logo.png\"", result.getContentDisposition());
-
-        assertEquals("image/jpeg", response.getContentType());
-        assertEquals(contentLength, response.getContentLength());
-        assertEquals("filename=\"logo.png\"", response.getHeader("Content-disposition"));
-    }
-
-    protected void setUp() throws Exception {
-        super.setUp();
-        response = new MockHttpServletResponse();
-
-        result = new StreamResult();
-        stack = ActionContext.getContext().getValueStack();
-
-        MyImageAction action = new MyImageAction();
-        contentLength = (int) action.getContentLength();
-
-        mai = new com.opensymphony.xwork2.mock.MockActionInvocation();
-        mai.setAction(action);
-        mai.setStack(stack);
-        mai.setInvocationContext(ActionContext.getContext());
-        stack.push(action);
-
-        ActionContext.getContext().put(ServletActionContext.HTTP_RESPONSE, response);
-    }
-
-
-
-    protected void tearDown() throws Exception {
-        super.tearDown();
-        response = null;
-        result = null;
-        stack = null;
-        contentLength = 0;
-        mai = null;
-    }
-
-    public class MyImageAction implements Action {
-
-        public InputStream getStreamForImage() throws Exception {
-            // just use src/test/log4j2.xml as test file
-            URL url = ClassLoaderUtil.getResource("log4j2.xml", StreamResultTest.class);
-            File file = new File(new URI(url.toString()));
-            FileInputStream fis = new FileInputStream(file);
-            return fis;
-        }
-
-        public String execute() throws Exception {
-            return SUCCESS;
-        }
-
-        public long getContentLength() throws Exception {
-            URL url = ClassLoaderUtil.getResource("log4j2.xml", StreamResultTest.class);
-            File file = new File(new URI(url.toString()));
-            return file.length();
-        }
-
-        public String getStreamForImageAsString() {
-            return "streamForImage";
-        }
-
-        public String getContentCharSetMethod() {
-            return "UTF-8";
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/dispatcher/StrutsResultSupportTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/dispatcher/StrutsResultSupportTest.java b/core/src/test/java/org/apache/struts2/dispatcher/StrutsResultSupportTest.java
deleted file mode 100644
index cc4bf6c..0000000
--- a/core/src/test/java/org/apache/struts2/dispatcher/StrutsResultSupportTest.java
+++ /dev/null
@@ -1,155 +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.dispatcher;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.apache.struts2.StrutsInternalTestCase;
-import org.easymock.EasyMock;
-
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.ActionSupport;
-import com.opensymphony.xwork2.util.ValueStack;
-
-/**
- * Test case for StrutsResultSupport.
- */
-public class StrutsResultSupportTest extends StrutsInternalTestCase {
-
-
-    public void testParse() throws Exception {
-        ValueStack stack = ActionContext.getContext().getValueStack();
-        stack.push(new ActionSupport() {
-            public String getMyLocation() {
-                return "ThisIsMyLocation";
-            }
-        });
-
-        ActionInvocation mockActionInvocation = EasyMock.createNiceMock(ActionInvocation.class);
-        mockActionInvocation.getStack();
-        EasyMock.expectLastCall().andReturn(stack);
-        EasyMock.replay(mockActionInvocation);
-
-        InternalStrutsResultSupport result = new InternalStrutsResultSupport();
-        result.setParse(true);
-        result.setEncode(false);
-        result.setLocation("/pages/myJsp.jsp?location=${myLocation}");
-
-        result.execute(mockActionInvocation);
-
-        assertNotNull(result.getInternalLocation());
-        assertEquals("/pages/myJsp.jsp?location=ThisIsMyLocation", result.getInternalLocation());
-        EasyMock.verify(mockActionInvocation);
-    }
-
-    public void testParseAndEncode() throws Exception {
-        ValueStack stack = ActionContext.getContext().getValueStack();
-        stack.push(new ActionSupport() {
-            public String getMyLocation() {
-                return "/myPage?param=value&param1=value1";
-            }
-        });
-
-        ActionInvocation mockActionInvocation = EasyMock.createNiceMock(ActionInvocation.class);
-        mockActionInvocation.getStack();
-        EasyMock.expectLastCall().andReturn(stack);
-        EasyMock.replay(mockActionInvocation);
-
-        InternalStrutsResultSupport result = new InternalStrutsResultSupport();
-        result.setParse(true);
-        result.setEncode(true);
-        result.setLocation("/pages/myJsp.jsp?location=${myLocation}");
-
-        result.execute(mockActionInvocation);
-
-        assertNotNull(result.getInternalLocation());
-        assertEquals("/pages/myJsp.jsp?location=%2FmyPage%3Fparam%3Dvalue%26param1%3Dvalue1", result.getInternalLocation());
-        EasyMock.verify(mockActionInvocation);
-    }
-
-
-    public void testNoParseAndEncode() throws Exception {
-        ValueStack stack = ActionContext.getContext().getValueStack();
-        stack.push(new ActionSupport() {
-            public String getMyLocation() {
-                return "myLocation.jsp";
-            }
-        });
-
-        ActionInvocation mockActionInvocation = EasyMock.createNiceMock(ActionInvocation.class);
-        EasyMock.replay(mockActionInvocation);
-
-        InternalStrutsResultSupport result = new InternalStrutsResultSupport();
-        result.setParse(false);
-        result.setEncode(false); // don't really need this, as encode is only valid when parse is true.
-        result.setLocation("/pages/myJsp.jsp?location=${myLocation}");
-
-        result.execute(mockActionInvocation);
-
-        assertNotNull(result.getInternalLocation());
-        assertEquals("/pages/myJsp.jsp?location=${myLocation}", result.getInternalLocation());
-        EasyMock.verify(mockActionInvocation);
-    }
-
-    public void testConditionalParseCollection() throws Exception {
-        ValueStack stack = ActionContext.getContext().getValueStack();
-        stack.push(new ActionSupport() {
-            public List<String> getList() {
-                return new ArrayList<String>(){{
-                    add("val 1");
-                    add("val 2");
-                }};
-            }
-        });
-
-        ActionInvocation mockActionInvocation = EasyMock.createNiceMock(ActionInvocation.class);
-        mockActionInvocation.getStack();
-        EasyMock.expectLastCall().andReturn(stack);
-        EasyMock.replay(mockActionInvocation);
-
-        InternalStrutsResultSupport result = new InternalStrutsResultSupport();
-        result.setParse(true);
-        result.setEncode(true);
-
-        Collection<String> collection = result.conditionalParseCollection("${list}", mockActionInvocation, true);
-
-        assertNotNull(collection);
-        assertEquals(2, collection.size());
-        assertTrue(collection.contains("val+1"));
-        assertTrue(collection.contains("val+2"));
-        EasyMock.verify(mockActionInvocation);
-    }
-
-    public static class InternalStrutsResultSupport extends StrutsResultSupport {
-        private String _internalLocation = null;
-
-        protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
-            _internalLocation = finalLocation;
-        }
-
-        public String getInternalLocation() {
-            return _internalLocation;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/dispatcher/VelocityResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/dispatcher/VelocityResultTest.java b/core/src/test/java/org/apache/struts2/dispatcher/VelocityResultTest.java
deleted file mode 100644
index 383e2c7..0000000
--- a/core/src/test/java/org/apache/struts2/dispatcher/VelocityResultTest.java
+++ /dev/null
@@ -1,147 +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.dispatcher;
-
-import org.apache.struts2.StrutsInternalTestCase;
-import org.apache.velocity.Template;
-import org.apache.velocity.app.VelocityEngine;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-
-import com.mockobjects.dynamic.Mock;
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.ActionProxy;
-import com.opensymphony.xwork2.util.ValueStack;
-
-
-/**
- *
- */
-public class VelocityResultTest extends StrutsInternalTestCase {
-
-    ActionInvocation actionInvocation;
-    Mock mockActionProxy;
-    ValueStack stack;
-    String namespace;
-    TestVelocityEngine velocity;
-    VelocityResult result;
-
-
-    public void testCanResolveLocationUsingOgnl() throws Exception {
-        TestResult result = new TestResult();
-
-        String location = "/myaction.action";
-        Bean bean = new Bean();
-        bean.setLocation(location);
-
-        ValueStack stack = ActionContext.getContext().getValueStack();
-        stack.push(bean);
-
-        assertEquals(location, stack.findValue("location"));
-
-        result.setLocation("${location}");
-        result.execute(actionInvocation);
-        assertEquals(location, result.finalLocation);
-    }
-
-    public void testCanResolveLocationUsingStaticExpression() throws Exception {
-        TestResult result = new TestResult();
-        String location = "/any.action";
-        result.setLocation("${'" + location + "'}");
-        result.execute(actionInvocation);
-        assertEquals(location, result.finalLocation);
-    }
-
-    public void testResourcesFoundUsingAbsolutePath() throws Exception {
-        String location = "/WEB-INF/views/registration.vm";
-
-        Template template = result.getTemplate(stack, velocity, actionInvocation, location, "UTF-8");
-        assertNotNull(template);
-        assertEquals("expect absolute locations to be handled as is", location, velocity.templateName);
-    }
-
-    public void testResourcesFoundUsingNames() throws Exception {
-        String location = "Registration.vm";
-        String expectedTemplateName = namespace + "/" + location;
-
-        Template template = result.getTemplate(stack, velocity, actionInvocation, location, "UTF-8");
-        assertNotNull(template);
-        assertEquals("expect the prefix to be appended to the path when the location is not absolute", expectedTemplateName, velocity.templateName);
-    }
-
-    protected void setUp() throws Exception {
-        super.setUp();
-        namespace = "/html";
-        result = new VelocityResult();
-        stack = ActionContext.getContext().getValueStack();
-        ActionContext.getContext().setValueStack(stack);
-        velocity = new TestVelocityEngine();
-        mockActionProxy = new Mock(ActionProxy.class);
-        mockActionProxy.expectAndReturn("getNamespace", "/html");
-
-        Mock mockActionInvocation = new Mock(ActionInvocation.class);
-        mockActionInvocation.expectAndReturn("getProxy", mockActionProxy.proxy());
-        mockActionInvocation.expectAndReturn("getStack", stack);
-        actionInvocation = (ActionInvocation) mockActionInvocation.proxy();
-    }
-
-
-    class Bean {
-        private String location;
-
-        public void setLocation(String location) {
-            this.location = location;
-        }
-
-        public String getLocation() {
-            return location;
-        }
-    }
-
-    class TestResult extends StrutsResultSupport {
-
-        private static final long serialVersionUID = -1512206785088317315L;
-
-        public String finalLocation;
-
-        protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
-            this.finalLocation = finalLocation;
-        }
-    }
-
-    class TestVelocityEngine extends VelocityEngine {
-        public String templateName;
-
-        public Template getTemplate(String templateName) throws ResourceNotFoundException, ParseErrorException, Exception {
-            this.templateName = templateName;
-
-            return new Template();
-        }
-
-        public Template getTemplate(String templateName, String charSet) throws ResourceNotFoundException, ParseErrorException, Exception {
-            this.templateName = templateName;
-
-            return new Template();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java
----------------------------------------------------------------------
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 29bf8ad..4314672 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
@@ -31,7 +31,7 @@ import com.opensymphony.xwork2.config.entities.PackageConfig;
 import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
 import org.apache.struts2.ServletActionContext;
 import org.apache.struts2.StrutsInternalTestCase;
-import org.apache.struts2.dispatcher.StrutsResultSupport;
+import org.apache.struts2.result.StrutsResultSupport;
 import org.apache.struts2.views.jsp.StrutsMockHttpServletRequest;
 
 import java.util.Arrays;

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/interceptor/MessageStoreInterceptorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/interceptor/MessageStoreInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/MessageStoreInterceptorTest.java
index 3ba76c2..a419a18 100644
--- a/core/src/test/java/org/apache/struts2/interceptor/MessageStoreInterceptorTest.java
+++ b/core/src/test/java/org/apache/struts2/interceptor/MessageStoreInterceptorTest.java
@@ -28,7 +28,7 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.struts2.StrutsInternalTestCase;
-import org.apache.struts2.dispatcher.ServletActionRedirectResult;
+import org.apache.struts2.result.ServletActionRedirectResult;
 import org.easymock.EasyMock;
 
 import com.opensymphony.xwork2.Action;

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/result/HttpHeaderResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/result/HttpHeaderResultTest.java b/core/src/test/java/org/apache/struts2/result/HttpHeaderResultTest.java
new file mode 100644
index 0000000..85849f1
--- /dev/null
+++ b/core/src/test/java/org/apache/struts2/result/HttpHeaderResultTest.java
@@ -0,0 +1,134 @@
+/*
+ * $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.result;
+
+import com.mockobjects.dynamic.C;
+import com.mockobjects.dynamic.Mock;
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsInternalTestCase;
+import org.apache.struts2.result.HttpHeaderResult;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * HttpHeaderResultTest
+ */
+public class HttpHeaderResultTest extends StrutsInternalTestCase {
+
+    ActionInvocation invocation;
+    HttpHeaderResult result;
+    HttpServletResponse response;
+    Mock responseMock;
+    ReflectionProvider reflectionProvider;
+
+    public void testHeaderValuesAreNotParsedWhenParseIsFalse() throws Exception {
+        Map<String, String> params = new HashMap<String, String>();
+        params.put("headers.foo", "${bar}");
+        params.put("headers.baz", "baz");
+
+        Map<String, String> values = new HashMap<String, String>();
+        values.put("bar", "abc");
+        ActionContext.getContext().getValueStack().push(values);
+
+        reflectionProvider.setProperties(params, result);
+
+        responseMock.expect("addHeader", C.args(C.eq("foo"), C.eq("${bar}")));
+        responseMock.expect("addHeader", C.args(C.eq("baz"), C.eq("baz")));
+        result.setParse(false);
+        result.execute(invocation);
+        responseMock.verify();
+    }
+
+    public void testHeaderValuesAreParsedAndSet() throws Exception {
+        Map<String, String> params = new HashMap<String, String>();
+        params.put("headers.foo", "${bar}");
+        params.put("headers.baz", "baz");
+
+        Map<String, String> values = new HashMap<String, String>();
+        values.put("bar", "abc");
+        ActionContext.getContext().getValueStack().push(values);
+
+        reflectionProvider.setProperties(params, result);
+
+        responseMock.expect("addHeader", C.args(C.eq("foo"), C.eq("abc")));
+        responseMock.expect("addHeader", C.args(C.eq("baz"), C.eq("baz")));
+        result.execute(invocation);
+        responseMock.verify();
+    }
+    
+    public void testErrorMessageIsParsedAndSet() throws Exception {
+        ActionContext.getContext().getValueStack().set("errMsg", "abc");
+        ActionContext.getContext().getValueStack().set("errCode", "404");
+        result.setError("${errCode}");
+        result.setErrorMessage("${errMsg}");
+        
+        responseMock.expect("sendError", C.args(C.eq(404), C.eq("abc")));
+        result.execute(invocation);
+        responseMock.verify();
+    }
+    
+    public void testErrorMessageIsNotParsedAndSet() throws Exception {
+        ActionContext.getContext().getValueStack().set("errMsg", "abc");
+        result.setError("404");
+        result.setParse(false);
+        result.setErrorMessage("${errMsg}");
+        
+        responseMock.expect("sendError", C.args(C.eq(404), C.eq("${errMsg}")));
+        result.execute(invocation);
+        responseMock.verify();
+    }
+
+    public void testStatusIsSet() throws Exception {
+        responseMock.expect("setStatus", C.eq(123));
+        result.setStatus(123);
+        result.execute(invocation);
+        responseMock.verify();
+    }
+    
+    public void testErrorIsSet() throws Exception {
+        responseMock.expect("sendError", C.eq(404));
+        result.setError("404");
+        result.execute(invocation);
+        responseMock.verify();
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        result = new HttpHeaderResult();
+        responseMock = new Mock(HttpServletResponse.class);
+        response = (HttpServletResponse) responseMock.proxy();
+        invocation = (ActionInvocation) new Mock(ActionInvocation.class).proxy();
+        reflectionProvider = container.getInstance(ReflectionProvider.class);
+        ServletActionContext.setResponse(response);
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        ActionContext.setContext(null);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/result/PlainTextResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/result/PlainTextResultTest.java b/core/src/test/java/org/apache/struts2/result/PlainTextResultTest.java
new file mode 100644
index 0000000..faa631f
--- /dev/null
+++ b/core/src/test/java/org/apache/struts2/result/PlainTextResultTest.java
@@ -0,0 +1,156 @@
+/*
+ * $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.result;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.mock.MockActionInvocation;
+import com.opensymphony.xwork2.util.ClassLoaderUtil;
+import com.opensymphony.xwork2.util.ValueStack;
+import org.apache.struts2.StrutsStatics;
+import org.apache.struts2.StrutsInternalTestCase;
+import org.apache.struts2.views.jsp.AbstractUITagTest;
+import org.apache.struts2.views.jsp.StrutsMockHttpServletResponse;
+import org.apache.struts2.views.jsp.StrutsMockServletContext;
+
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * Test case for PlainTextResult.
+ *
+ */
+public class PlainTextResultTest extends StrutsInternalTestCase {
+
+    ValueStack stack;
+    MockActionInvocation invocation;
+    ActionContext context;
+    StrutsMockHttpServletResponse response;
+    PrintWriter writer;
+    StringWriter stringWriter;
+    StrutsMockServletContext servletContext;
+
+
+    public void testPlainText() throws Exception {
+        PlainTextResult result = new PlainTextResult();
+        result.setLocation("/someJspFile.jsp");
+
+        response.setExpectedContentType("text/plain");
+        response.setExpectedHeader("Content-Disposition", "inline");
+
+        try (InputStream jspResourceInputStream =
+            ClassLoaderUtil.getResourceAsStream(
+                "org/apache/struts2/dispatcher/someJspFile.jsp",
+                PlainTextResultTest.class)) {
+            servletContext.setResourceAsStream(jspResourceInputStream);
+            result.execute(invocation);
+
+            String r = AbstractUITagTest.normalize(stringWriter.getBuffer().toString(), true);
+            String e = AbstractUITagTest.normalize(
+                    readAsString("org/apache/struts2/dispatcher/someJspFile.jsp"), true);
+            assertEquals(r, e);
+        }
+    }
+
+    public void testPlainTextWithoutSlash() throws Exception {
+        PlainTextResult result = new PlainTextResult();
+        result.setLocation("someJspFile.jsp");
+
+        response.setExpectedContentType("text/plain");
+        response.setExpectedHeader("Content-Disposition", "inline");
+
+        try (InputStream jspResourceInputStream =
+            ClassLoaderUtil.getResourceAsStream("org/apache/struts2/dispatcher/someJspFile.jsp", PlainTextResultTest.class)) {
+            servletContext.setResourceAsStream(jspResourceInputStream);
+            result.execute(invocation);
+
+            String r = AbstractUITagTest.normalize(stringWriter.getBuffer().toString(), true);
+            String e = AbstractUITagTest.normalize(readAsString("org/apache/struts2/dispatcher/someJspFile.jsp"), true);
+            assertEquals(r, e);
+        }
+    }
+
+    public void testPlainTextWithEncoding() throws Exception {
+        PlainTextResult result = new PlainTextResult();
+        result.setLocation("/someJspFile.jsp");
+        result.setCharSet("UTF-8");
+
+        response.setExpectedContentType("text/plain; charset=UTF-8");
+        response.setExpectedHeader("Content-Disposition", "inline");
+
+        try (InputStream jspResourceInputStream =
+            ClassLoaderUtil.getResourceAsStream(
+                "org/apache/struts2/dispatcher/someJspFile.jsp",
+                PlainTextResultTest.class)) {
+            servletContext.setResourceAsStream(jspResourceInputStream);
+            result.execute(invocation);
+
+            String r = AbstractUITagTest.normalize(stringWriter.getBuffer().toString(), true);
+            String e = AbstractUITagTest.normalize(
+                    readAsString("org/apache/struts2/dispatcher/someJspFile.jsp"), true);
+            assertEquals(r, e);
+        }
+    }
+
+    protected String readAsString(String resource) throws Exception {
+        try (InputStream is = ClassLoaderUtil.getResourceAsStream(resource, PlainTextResultTest.class)) {
+            int sizeRead = 0;
+            byte[] buffer = new byte[1024];
+            StringBuilder stringBuilder = new StringBuilder();
+            while((sizeRead = is.read(buffer)) != -1) {
+                stringBuilder.append(new String(buffer, 0, sizeRead));
+            }
+            return stringBuilder.toString();
+        }
+    }
+
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        stringWriter = new StringWriter();
+        writer = new PrintWriter(stringWriter);
+        response = new StrutsMockHttpServletResponse();
+        response.setWriter(writer);
+        servletContext = new StrutsMockServletContext();
+        stack = ActionContext.getContext().getValueStack();
+        context = new ActionContext(stack.getContext());
+        context.put(StrutsStatics.HTTP_RESPONSE, response);
+        context.put(StrutsStatics.SERVLET_CONTEXT, servletContext);
+        invocation = new MockActionInvocation();
+        invocation.setStack(stack);
+        invocation.setInvocationContext(context);
+    }
+
+
+    protected void tearDown() throws Exception {
+        stack = null;
+        invocation = null;
+        context = null;
+        response = null;
+        writer = null;
+        stringWriter = null;
+        servletContext = null;
+
+        super.tearDown();
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/6bc99ab9/core/src/test/java/org/apache/struts2/result/ServletActionRedirectResultTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/struts2/result/ServletActionRedirectResultTest.java b/core/src/test/java/org/apache/struts2/result/ServletActionRedirectResultTest.java
new file mode 100644
index 0000000..2bea0a1
--- /dev/null
+++ b/core/src/test/java/org/apache/struts2/result/ServletActionRedirectResultTest.java
@@ -0,0 +1,189 @@
+/*
+ * $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.result;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.ActionProxy;
+import com.opensymphony.xwork2.ObjectFactory;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.config.entities.ResultConfig;
+import com.opensymphony.xwork2.util.ValueStack;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsInternalTestCase;
+import org.apache.struts2.dispatcher.mapper.ActionMapper;
+import org.apache.struts2.result.ServletActionRedirectResult;
+import org.apache.struts2.views.util.DefaultUrlHelper;
+import org.easymock.IMocksControl;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.easymock.EasyMock.createControl;
+import static org.easymock.EasyMock.expect;
+
+
+/**
+ * @version $Date$ $Id$
+ */
+public class ServletActionRedirectResultTest extends StrutsInternalTestCase {
+
+    public void testIncludeParameterInResultWithConditionParseOn() throws Exception {
+
+        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("statusCode", "333")
+			.addParam("param1", "${#value1}")
+            .addParam("param2", "${#value2}")
+            .addParam("param3", "${#value3}")
+            .addParam("anchor", "${#fragment}")
+            .build();
+
+
+
+        ActionContext context = ActionContext.getContext();
+        ValueStack stack = context.getValueStack();
+        context.getContextMap().put("value1", "value 1");
+        context.getContextMap().put("value2", "value 2");
+        context.getContextMap().put("value3", "value 3");
+        MockHttpServletRequest req = new MockHttpServletRequest();
+        MockHttpServletResponse res = new MockHttpServletResponse();
+        context.put(ServletActionContext.HTTP_REQUEST, req);
+        context.put(ServletActionContext.HTTP_RESPONSE, res);
+
+
+        Map<String, ResultConfig> results=  new HashMap<String, ResultConfig>();
+        results.put("myResult", resultConfig);
+
+        ActionConfig actionConfig = new ActionConfig.Builder("", "", "")
+                .addResultConfigs(results).build();
+
+        ServletActionRedirectResult result = new ServletActionRedirectResult();
+        result.setActionName("myAction");
+        result.setNamespace("/myNamespace");
+        result.setParse(true);
+        result.setEncode(false);
+        result.setPrependServletContext(false);
+        result.setAnchor("fragment");
+        result.setUrlHelper(new DefaultUrlHelper());
+
+        IMocksControl control = createControl();
+        ActionProxy mockActionProxy = control.createMock(ActionProxy.class);
+        ActionInvocation mockInvocation = control.createMock(ActionInvocation.class);
+        expect(mockInvocation.getProxy()).andReturn(mockActionProxy);
+        expect(mockInvocation.getResultCode()).andReturn("myResult");
+        expect(mockActionProxy.getConfig()).andReturn(actionConfig);
+        expect(mockInvocation.getInvocationContext()).andReturn(context);
+        expect(mockInvocation.getStack()).andReturn(stack).anyTimes();
+
+        control.replay();
+        result.setActionMapper(container.getInstance(ActionMapper.class));
+        result.execute(mockInvocation);
+        assertEquals("/myNamespace/myAction.action?param1=value+1&param2=value+2&param3=value+3#fragment", res.getRedirectedUrl());
+
+        control.verify();
+    }
+
+    public void testIncludeParameterInResult() throws Exception {
+
+        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")
+            .addParam("anchor", "fragment")
+            .build();
+
+        ActionContext context = ActionContext.getContext();
+        MockHttpServletRequest req = new MockHttpServletRequest();
+        MockHttpServletResponse res = new MockHttpServletResponse();
+        context.put(ServletActionContext.HTTP_REQUEST, req);
+        context.put(ServletActionContext.HTTP_RESPONSE, res);
+
+
+        Map<String, ResultConfig> results=  new HashMap<String, ResultConfig>();
+        results.put("myResult", resultConfig);
+
+        ActionConfig actionConfig = new ActionConfig.Builder("", "", "")
+                .addResultConfigs(results).build();
+
+        ServletActionRedirectResult result = new ServletActionRedirectResult();
+        result.setActionName("myAction");
+        result.setNamespace("/myNamespace");
+        result.setParse(false);
+        result.setEncode(false);
+        result.setPrependServletContext(false);
+        result.setAnchor("fragment");
+        result.setUrlHelper(new DefaultUrlHelper());
+
+        IMocksControl control = createControl();
+        ActionProxy mockActionProxy = control.createMock(ActionProxy.class);
+        ActionInvocation mockInvocation = control.createMock(ActionInvocation.class);
+        expect(mockInvocation.getProxy()).andReturn(mockActionProxy);
+        expect(mockInvocation.getResultCode()).andReturn("myResult");
+        expect(mockActionProxy.getConfig()).andReturn(actionConfig);
+        expect(mockInvocation.getInvocationContext()).andReturn(context);
+
+        control.replay();
+        result.setActionMapper(container.getInstance(ActionMapper.class));
+        result.execute(mockInvocation);
+        assertEquals("/myNamespace/myAction.action?param1=value+1&param2=value+2&param3=value+3#fragment", res.getRedirectedUrl());
+
+        control.verify();
+    }
+
+    public void testBuildResultWithParameter() throws Exception {
+
+        ResultConfig resultConfig = new ResultConfig.Builder("", ServletActionRedirectResult.class.getName())
+            .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")
+            .addParam("anchor", "fragment")
+            .build();
+
+        ObjectFactory factory = container.getInstance(ObjectFactory.class);
+        ServletActionRedirectResult result = (ServletActionRedirectResult) factory.buildResult(resultConfig, new HashMap<String, Object>());
+        assertNotNull(result);
+    }
+    
+}