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">


Reply via email to