Revision: 1246
          http://stripes.svn.sourceforge.net/stripes/?rev=1246&view=rev
Author:   bengunter
Date:     2010-05-23 00:32:12 +0000 (Sun, 23 May 2010)

Log Message:
-----------
STS-391: Added openBuffer and closeBuffer methods to the layout writer. The 
component renderer will rely on these two methods to buffer its output. This 
has at least two additional advantages: no reliance on the BodyContent 
implementations that have caused memory leaks in some containers and ability to 
silence output when using the decorator pattern.

Modified Paths:
--------------
    
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentRenderer.java
    
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutWriter.java

Modified: 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentRenderer.java
===================================================================
--- 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentRenderer.java
  2010-05-22 20:17:09 UTC (rev 1245)
+++ 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentRenderer.java
  2010-05-23 00:32:12 UTC (rev 1246)
@@ -18,7 +18,6 @@
 import java.util.LinkedList;
 
 import javax.servlet.jsp.PageContext;
-import javax.servlet.jsp.tagext.BodyContent;
 
 import net.sourceforge.stripes.controller.StripesConstants;
 import net.sourceforge.stripes.exception.StripesJspException;
@@ -90,6 +89,7 @@
         final LayoutContext context = LayoutContext.lookup(pageContext);
         final boolean phaseFlag = context.isComponentRenderPhase();
         final String component = context.getComponent();
+        final boolean silent = context.getOut().isSilent();
 
         // Descend the layout context stack, trying each context where the 
component is registered
         log.debug("Stringify component \"", componentName, "\" in ", 
currentPage);
@@ -113,14 +113,12 @@
                 log.debug("Start stringify \"", componentName, "\" in ", 
context.getRenderPage(),
                         " -> ", context.getDefinitionPage(), " from ", 
source.getRenderPage(),
                         " -> ", source.getDefinitionPage());
-                BodyContent body = pageContext.pushBody();
+                context.getOut().openBuffer(pageContext);
+                context.getOut().setSilent(true, pageContext);
                 pageContext.include(source.getRenderPage(), false);
-                pageContext.popBody();
                 log.debug("End stringify \"", componentName, "\" in ", 
context.getRenderPage(),
                         " -> ", context.getDefinitionPage(), " from ", 
source.getRenderPage(),
                         " -> ", source.getDefinitionPage());
-                if (context.getComponent() == null)
-                    return body.getString();
             }
             catch (Exception e) {
                 log.error(e, "Unhandled exception trying to render component 
\"", componentName,
@@ -129,8 +127,18 @@
                 return "[Failed to render \"" + componentName + "\". See log 
for details.]";
             }
             finally {
+                // Determine if the component rendered before resetting the 
context properties
+                boolean rendered = context.getComponent() == null;
+
+                // Reset the context properties
                 context.setComponentRenderPhase(phaseFlag);
                 context.setComponent(component);
+                context.getOut().setSilent(silent, pageContext);
+
+                // Pop the buffer contents and return them if the component 
did render
+                String value = context.getOut().closeBuffer(pageContext);
+                if (rendered)
+                    return value;
             }
         }
 

Modified: 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutWriter.java
===================================================================
--- 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutWriter.java 
    2010-05-22 20:17:09 UTC (rev 1245)
+++ 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutWriter.java 
    2010-05-23 00:32:12 UTC (rev 1246)
@@ -15,11 +15,14 @@
 package net.sourceforge.stripes.tag.layout;
 
 import java.io.IOException;
+import java.io.StringWriter;
 import java.io.Writer;
+import java.util.LinkedList;
 
 import javax.servlet.jsp.JspWriter;
 import javax.servlet.jsp.PageContext;
 
+import net.sourceforge.stripes.exception.StripesRuntimeException;
 import net.sourceforge.stripes.util.Log;
 
 /**
@@ -35,7 +38,7 @@
 public class LayoutWriter extends Writer {
     private static final Log log = Log.getInstance(LayoutWriter.class);
 
-    private JspWriter out;
+    private LinkedList<Writer> writers = new LinkedList<Writer>();
     private boolean silent;
 
     /**
@@ -45,9 +48,14 @@
      */
     public LayoutWriter(JspWriter out) {
         log.debug("Create layout writer wrapped around ", out);
-        this.out = out;
+        this.writers.add(out);
     }
 
+    /** Get the writer to which output is currently being written. */
+    protected Writer getOut() {
+        return writers.isEmpty() ? null : writers.getLast();
+    }
+
     /** If true, then discard all output. If false, then resume sending output 
to the JSP writer. */
     public boolean isSilent() {
         return silent;
@@ -57,31 +65,59 @@
      * Enable or disable silent mode. The output buffer for the given page 
context will be flushed
      * before silent mode is enabled to ensure all buffered data are written.
      */
-    public void setSilent(boolean silent, PageContext context) {
+    public void setSilent(boolean silent, PageContext pageContext) {
         if (silent != this.silent) {
-            try {
-                if (context != null)
-                    context.getOut().flush();
-            }
-            catch (IOException e) {
-                // This seems to happen once at the beginning and once at the 
end. Don't know why.
-                log.debug("Failed to flush buffer: ", e.getMessage());
-            }
-            finally {
-                this.silent = silent;
-                log.trace("Output is " + (silent ? "DISABLED" : "ENABLED"));
-            }
+            tryFlush(pageContext);
+            this.silent = silent;
+            log.trace("Output is " + (silent ? "DISABLED" : "ENABLED"));
         }
     }
 
+    /**
+     * Flush the page context's output buffer and redirect output into a 
buffer. The buffer can be
+     * closed and its contents retrieved by calling {...@link 
#closeBuffer(PageContext)}.
+     */
+    public void openBuffer(PageContext pageContext) {
+        tryFlush(pageContext);
+        writers.add(new StringWriter(1024));
+    }
+
+    /**
+     * Flush the page context's output buffer and resume sending output to the 
writer that was
+     * receiving output prior to calling {...@link #openBuffer(PageContext)}.
+     * 
+     * @return The buffer's contents.
+     */
+    public String closeBuffer(PageContext pageContext) {
+        if (getOut() instanceof StringWriter) {
+            return ((StringWriter) writers.removeLast()).toString();
+        }
+        else {
+            throw new StripesRuntimeException(
+                    "Attempt to close a buffer without having first called 
openBuffer(..)!");
+        }
+    }
+
+    /** Try to flush the page context's output buffer. If an exception is 
thrown, just log it. */
+    protected void tryFlush(PageContext pageContext) {
+        try {
+            if (pageContext != null)
+                pageContext.getOut().flush();
+        }
+        catch (IOException e) {
+            // This seems to happen once at the beginning and once at the end. 
Don't know why.
+            log.debug("Failed to flush buffer: ", e.getMessage());
+        }
+    }
+
     @Override
     public void close() throws IOException {
-        out.close();
+        getOut().close();
     }
 
     @Override
     public void flush() throws IOException {
-        out.flush();
+        getOut().flush();
     }
 
     /**
@@ -90,12 +126,22 @@
      * @throws IOException
      */
     public void clear() throws IOException {
-        out.clear();
+        Writer out = getOut();
+        if (out instanceof JspWriter) {
+            ((JspWriter) out).clear();
+        }
+        else if (out instanceof StringWriter) {
+            ((StringWriter) out).getBuffer().setLength(0);
+        }
+        else {
+            throw new StripesRuntimeException("How did I get a writer of type "
+                    + out.getClass().getName() + "??");
+        }
     }
 
     @Override
     public void write(char[] cbuf, int off, int len) throws IOException {
         if (!isSilent())
-            out.write(cbuf, off, len);
+            getOut().write(cbuf, off, len);
     }
 }


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------

_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development

Reply via email to