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