WW-3195 When FreemarkerResult isn't writing directly to Response, s.action tag is broken

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@830250 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Musachy Barroso
2009-10-27 17:03:50 +00:00
parent a0e3a4950e
commit 6adf71480a
6 changed files with 178 additions and 8 deletions
@@ -117,6 +117,7 @@ public class FreemarkerResult extends StrutsResultSupport {
*/
protected String location;
private String pContentType = "text/html";
private static final String PARENT_TEMPLATE_WRITER = FreemarkerResult.class.getName() + ".parentWriter";
public FreemarkerResult() {
super();
@@ -158,9 +159,10 @@ public class FreemarkerResult extends StrutsResultSupport {
this.configuration = getConfiguration();
this.wrapper = getObjectWrapper();
ActionContext ctx = invocation.getInvocationContext();
HttpServletRequest req = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
if (!locationArg.startsWith("/")) {
ActionContext ctx = invocation.getInvocationContext();
HttpServletRequest req = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
String base = ResourceUtil.getResourceBase(req);
locationArg = base + "/" + locationArg;
}
@@ -174,14 +176,27 @@ public class FreemarkerResult extends StrutsResultSupport {
// Process the template
Writer writer = getWriter();
if (isWriteIfCompleted() || configuration.getTemplateExceptionHandler() == TemplateExceptionHandler.RETHROW_HANDLER) {
CharArrayWriter charArrayWriter = new CharArrayWriter();
CharArrayWriter parentCharArrayWriter = (CharArrayWriter) req.getAttribute(PARENT_TEMPLATE_WRITER);
boolean isTopTemplate = false;
if (isTopTemplate = (parentCharArrayWriter == null)) {
//this is the top template
parentCharArrayWriter = new CharArrayWriter();
//set it in the request because when the "action" tag is used a new VS and ActionContext is created
req.setAttribute(PARENT_TEMPLATE_WRITER, parentCharArrayWriter);
}
try {
template.process(model, charArrayWriter);
charArrayWriter.flush();
charArrayWriter.writeTo(writer);
template.process(model, parentCharArrayWriter);
if (isTopTemplate) {
parentCharArrayWriter.flush();
parentCharArrayWriter.writeTo(writer);
}
} finally {
if (charArrayWriter != null)
charArrayWriter.close();
if (isTopTemplate && parentCharArrayWriter != null) {
req.removeAttribute(PARENT_TEMPLATE_WRITER);
parentCharArrayWriter.close();
}
}
} else {
template.process(model, writer);
@@ -30,15 +30,26 @@ import junit.framework.TestCase;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.StrutsTestCase;
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.jsp.StrutsMockHttpServletResponse;
import org.apache.struts2.views.jsp.StrutsMockServletContext;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockServletContext;
import org.springframework.core.io.DefaultResourceLoader;
import org.easymock.EasyMock;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.mock.MockActionInvocation;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
import javax.servlet.ServletContext;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.Configuration;
/**
* Test case for FreeMarkerResult.
*
@@ -55,6 +66,58 @@ public class FreeMarkerResultTest extends StrutsTestCase {
private FreemarkerManager mgr;
private MockHttpServletRequest request;
public void testActionThatThrowsExceptionTag() throws Exception {
//get fm config to use it in mock servlet context
FreemarkerManager freemarkerManager = container.getInstance(FreemarkerManager.class);
Configuration freemarkerConfig = freemarkerManager.getConfiguration(ServletActionContext.getServletContext());
freemarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
ServletContext servletContext = EasyMock.createNiceMock(ServletContext.class);
File file = new File(FreeMarkerResultTest.class.getResource("callActionFreeMarker2.ftl").toURI());
EasyMock.expect(servletContext.getRealPath("/tutorial/org/apache/struts2/views/freemarker/callActionFreeMarker.ftl")).andReturn(file.getAbsolutePath());
file = new File(FreeMarkerResultTest.class.getResource("nested.ftl").toURI());
EasyMock.expect(servletContext.getRealPath("/tutorial/org/apache/struts2/views/freemarker/nested.ftl")).andReturn(file.getAbsolutePath());
EasyMock.expect(servletContext.getAttribute(FreemarkerManager.CONFIG_SERVLET_CONTEXT_KEY)).andReturn(freemarkerConfig).anyTimes();
EasyMock.replay(servletContext);
freemarkerConfig.setServletContextForTemplateLoading(servletContext, null);
ServletActionContext.setServletContext(servletContext);
request.setRequestURI("/tutorial/test2.action");
Dispatcher dispatcher = Dispatcher.getInstance();
ActionMapping mapping = dispatcher.getContainer().getInstance(ActionMapper.class).getMapping(
request, dispatcher.getConfigurationManager());
dispatcher.serviceAction(request, response, servletContext, mapping);
assertEquals("beforenestedafter", stringWriter.toString());
}
public void testActionThatSucceedsTag() throws Exception {
//get fm config to use it in mock servlet context
FreemarkerManager freemarkerManager = container.getInstance(FreemarkerManager.class);
Configuration freemarkerConfig = freemarkerManager.getConfiguration(ServletActionContext.getServletContext());
freemarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
ServletContext servletContext = EasyMock.createNiceMock(ServletContext.class);
File file = new File(FreeMarkerResultTest.class.getResource("callActionFreeMarker2.ftl").toURI());
EasyMock.expect(servletContext.getRealPath("/tutorial/org/apache/struts2/views/freemarker/callActionFreeMarker2.ftl")).andReturn(file.getAbsolutePath());
file = new File(FreeMarkerResultTest.class.getResource("nested.ftl").toURI());
EasyMock.expect(servletContext.getRealPath("/tutorial/org/apache/struts2/views/freemarker/nested.ftl")).andReturn(file.getAbsolutePath());
EasyMock.expect(servletContext.getAttribute(FreemarkerManager.CONFIG_SERVLET_CONTEXT_KEY)).andReturn(freemarkerConfig).anyTimes();
EasyMock.replay(servletContext);
freemarkerConfig.setServletContextForTemplateLoading(servletContext, null);
ServletActionContext.setServletContext(servletContext);
request.setRequestURI("/tutorial/test5.action");
Dispatcher dispatcher = Dispatcher.getInstance();
ActionMapping mapping = dispatcher.getContainer().getInstance(ActionMapper.class).getMapping(
request, dispatcher.getConfigurationManager());
dispatcher.serviceAction(request, response, servletContext, mapping);
assertEquals("beforenestedafter", stringWriter.toString());
}
public void testWriteIfCompleted() throws Exception {
FreemarkerResult result = new FreemarkerResult();
result.setLocation("someFreeMarkerFile.ftl");
@@ -0,0 +1,23 @@
<#--
/*
* $Id: someFreeMarkerFile.ftl 590812 2007-10-31 20:32:54Z apetrelli $
*
* 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.
*/
-->
before<@s.action namespace="/tutorial" name="test4" executeResult="true" rethrowException="true"/>after
@@ -0,0 +1,23 @@
<#--
/*
* $Id: someFreeMarkerFile.ftl 590812 2007-10-31 20:32:54Z apetrelli $
*
* 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.
*/
-->
before<@s.action namespace="/tutorial" name="test3" executeResult="true" rethrowException="true"/>after
@@ -0,0 +1,23 @@
<#--
/*
* $Id: someFreeMarkerFile.ftl 590812 2007-10-31 20:32:54Z apetrelli $
*
* 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.
*/
-->
nested
+23
View File
@@ -40,6 +40,29 @@
<action name="test" class="com.opensymphony.xwork2.ActionSupport">
<result name="input">sitegraph/guess-input.ftl</result>
</action>
<action name="test2" class="com.opensymphony.xwork2.ActionSupport">
<result type="freemarker">
<param name="location">org/apache/struts2/views/freemarker/callActionFreeMarker.ftl</param>
</result>
</action>
<action name="test3" class="com.opensymphony.xwork2.ActionSupport">
<result type="freemarker">org/apache/struts2/views/freemarker/nested.ftl</result>
</action>
<action name="test4" class="org.apache.struts2.TestAction" method="executeThrowsException">
<result type="freemarker">
<param name="location">org/apache/struts2/views/freemarker/nested.ftl</param>
</result>
</action>
<action name="test5" class="com.opensymphony.xwork2.ActionSupport">
<result type="freemarker">
<param name="location">org/apache/struts2/views/freemarker/callActionFreeMarker2.ftl</param>
</result>
</action>
</package>
<package name="sitegraph" namespace="/tutorial/sitegraph" extends="struts-default">