Author: musachy Date: Tue Oct 27 17:03:50 2009 New Revision: 830250 URL: http://svn.apache.org/viewvc?rev=830250&view=rev Log: WW-3195 When FreemarkerResult isn't writing directly to Response, s.action tag is broken
Added: struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker.ftl struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker2.ftl struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/nested.ftl Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerResult.java struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/freemarker/FreeMarkerResultTest.java struts/struts2/trunk/core/src/test/resources/struts.xml Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerResult.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerResult.java?rev=830250&r1=830249&r2=830250&view=diff ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerResult.java (original) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerResult.java Tue Oct 27 17:03:50 2009 @@ -117,6 +117,7 @@ */ 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 @@ 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 @@ // 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); Modified: struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/freemarker/FreeMarkerResultTest.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/freemarker/FreeMarkerResultTest.java?rev=830250&r1=830249&r2=830250&view=diff ============================================================================== --- struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/freemarker/FreeMarkerResultTest.java (original) +++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/freemarker/FreeMarkerResultTest.java Tue Oct 27 17:03:50 2009 @@ -30,15 +30,26 @@ 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 @@ 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"); Added: struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker.ftl URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker.ftl?rev=830250&view=auto ============================================================================== --- struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker.ftl (added) +++ struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker.ftl Tue Oct 27 17:03:50 2009 @@ -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 \ No newline at end of file Added: struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker2.ftl URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker2.ftl?rev=830250&view=auto ============================================================================== --- struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker2.ftl (added) +++ struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker2.ftl Tue Oct 27 17:03:50 2009 @@ -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 \ No newline at end of file Added: struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/nested.ftl URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/nested.ftl?rev=830250&view=auto ============================================================================== --- struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/nested.ftl (added) +++ struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/nested.ftl Tue Oct 27 17:03:50 2009 @@ -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 \ No newline at end of file Modified: struts/struts2/trunk/core/src/test/resources/struts.xml URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/resources/struts.xml?rev=830250&r1=830249&r2=830250&view=diff ============================================================================== --- struts/struts2/trunk/core/src/test/resources/struts.xml (original) +++ struts/struts2/trunk/core/src/test/resources/struts.xml Tue Oct 27 17:03:50 2009 @@ -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">