Revision: 1253
http://stripes.svn.sourceforge.net/stripes/?rev=1253&view=rev
Author: bengunter
Date: 2010-06-08 20:03:28 +0000 (Tue, 08 Jun 2010)
Log Message:
-----------
STS-391: Enable streaming even using the decorator pattern by allowing
layout-component within a layout-component even when the two tags have the same
name. This is accomplished by changing LayoutComponentTag to use
LayoutComponentRenderer to do the heavy lifting via a new write() method that
renders the component directly to the JSP writer. LayoutComponentRenderer's
toString() method now uses the write() method but sets up a buffer in the
LayoutWriter beforehand and closes the buffer afterward. To use these new
capabilities, one need only replace component references like ${body} with
<s:layout-component name="body" />.
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/LayoutComponentTag.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-06-07 20:51:40 UTC (rev 1252)
+++
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentRenderer.java
2010-06-08 20:03:28 UTC (rev 1253)
@@ -14,9 +14,11 @@
*/
package net.sourceforge.stripes.tag.layout;
+import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
+import javax.servlet.ServletException;
import javax.servlet.jsp.PageContext;
import net.sourceforge.stripes.controller.StripesConstants;
@@ -89,12 +91,19 @@
return sourceContext;
}
- @Override
- public String toString() {
+ /**
+ * Write the component to the page context's writer, optionally buffering
the output.
+ *
+ * @return True if the named component was found and it indicated that it
successfully rendered;
+ * otherwise, false.
+ * @throws IOException If thrown by {...@link PageContext#include(String)}
+ * @throws ServletException If thrown by {...@link
PageContext#include(String)}
+ */
+ public boolean write() throws ServletException, IOException {
final PageContext pageContext = getPageContext();
if (pageContext == null) {
log.error("Failed to render component \"", componentName, "\"
without a page context!");
- return "[Failed to render component \"" + componentName + "\"
without a page context!]";
+ return false;
}
// Get the current page so we can be sure not to invoke it again (see
below)
@@ -138,38 +147,63 @@
log.debug("Start stringify \"", componentName, "\" in ",
context.getRenderPage(),
" -> ", context.getDefinitionPage(), " from ",
source.getRenderPage(),
" -> ", source.getDefinitionPage());
- context.getOut().openBuffer(pageContext);
context.getOut().setSilent(true, pageContext);
pageContext.include(source.getRenderPage(), false);
log.debug("End stringify \"", componentName, "\" in ",
context.getRenderPage(),
" -> ", context.getDefinitionPage(), " from ",
source.getRenderPage(),
" -> ", source.getDefinitionPage());
+
+ // If the component name has been cleared then the component
rendered
+ if (context.getComponent() == null)
+ return true;
}
- catch (Exception e) {
- log.error(e, "Unhandled exception trying to render component
\"", componentName,
- "\" to a string in context ", source.getRenderPage(),
" -> ", source
- .getDefinitionPage());
- 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);
sourceContext = currentSource;
-
- // Pop the buffer contents and return them if the component
did render
- String value = context.getOut().closeBuffer(pageContext);
- if (rendered)
- return value;
}
}
log.debug("Component \"", componentName, "\" evaluated to empty string
in context ",
context.getRenderPage(), " -> ", context.getDefinitionPage());
- return "";
+ return false;
}
+
+ /**
+ * Open a buffer in {...@link LayoutWriter}, call {...@link #write()} to
render the component and then
+ * return the buffer contents.
+ */
+ @Override
+ public String toString() {
+ final PageContext pageContext = getPageContext();
+ if (pageContext == null) {
+ log.error("Failed to render component \"", componentName, "\"
without a page context!");
+ return "[Failed to render component \"" + componentName + "\"
without a page context!]";
+ }
+
+ final LayoutContext context = LayoutContext.lookup(pageContext);
+ String contents;
+ context.getOut().openBuffer(pageContext);
+ try {
+ write();
+ }
+ catch (Exception e) {
+ log.error(e, "Unhandled exception trying to render component \"",
componentName,
+ "\" to a string in context ", context.getRenderPage(), //
+ " -> ", context.getDefinitionPage());
+ return "[Failed to render \"" + componentName + "\". See log for
details.]";
+ }
+ finally {
+ contents = context.getOut().closeBuffer(pageContext);
+ if ("".equals(contents)) {
+ log.debug("Component \"", componentName,
+ "\" evaluated to empty string in context ",
context.getRenderPage(),
+ " -> ", context.getDefinitionPage());
+ }
+ }
+
+ return contents;
+ }
}
Modified:
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentTag.java
===================================================================
---
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentTag.java
2010-06-07 20:51:40 UTC (rev 1252)
+++
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentTag.java
2010-06-08 20:03:28 UTC (rev 1253)
@@ -14,11 +14,8 @@
*/
package net.sourceforge.stripes.tag.layout;
-import java.io.IOException;
-import java.util.Iterator;
import java.util.regex.Pattern;
-import javax.servlet.ServletException;
import javax.servlet.jsp.JspException;
import net.sourceforge.stripes.exception.StripesJspException;
@@ -130,37 +127,19 @@
}
else if (isChildOfDefinition()) {
if (!context.isComponentRenderPhase()) {
- // Set render phase flag and the name of the component to
render. Iterate down
- // the stack of layout contexts, executing each render
page that contains a
- // component with the same name as this one until the
component has rendered or
- // we run out of contexts.
- context.setComponentRenderPhase(true);
- context.setComponent(getName());
- Iterator<LayoutContext> iterator =
LayoutContext.getStack(pageContext, true)
- .descendingIterator();
- while (iterator.hasNext() && context.getComponent() !=
null) {
- LayoutContext renderer = iterator.next();
- if (renderer.getComponents().containsKey(getName())) {
- String renderPage = renderer.getRenderPage();
- log.debug("Execute component ", getName(), " in ",
context
- .getDefinitionPage(), " with include of ",
renderPage);
- boolean silent = context.getOut().isSilent();
- context.getOut().setSilent(true, pageContext);
- pageContext.include(renderPage, false);
- context.getOut().setSilent(silent, pageContext);
- }
- }
- context.setComponentRenderPhase(false);
+ // Use a layout component renderer to do the heavy lifting
+ log.debug("Invoke layout component renderer for recursive
render");
+ LayoutComponentRenderer renderer = new
LayoutComponentRenderer(getName());
+ renderer.pushPageContext(pageContext);
+ boolean rendered = renderer.write();
- // The current component name should be cleared after the
component has
- // rendered. If it is not cleared then the component did
not render so we need
- // to output the default content from the layout
definition.
- if (context.getComponent() != null) {
+ // If the component did not render then we need to output
the default contents
+ // from the layout definition.
+ if (!rendered) {
log.debug("Component was not present in ",
context.getRenderPage(),
" so using default content from ",
context.getDefinitionPage());
context.getOut().setSilent(false, pageContext);
- context.setComponent(null);
return EVAL_BODY_INCLUDE;
}
}
@@ -168,16 +147,30 @@
log.debug("No-op for ", getName(), " in ",
context.getDefinitionPage());
}
}
+ else if (isChildOfComponent() && isCurrentComponent()
+ && context.isComponentRenderPhase()) {
+ LayoutComponentTag parent = getLayoutAncestor();
+ if (getName().equals(parent.getName())) {
+ log.debug("Invoke layout component renderer for recursive
render");
+ LayoutComponentRenderer renderer =
(LayoutComponentRenderer) pageContext
+ .getAttribute(getName());
+ renderer.write();
+ }
+ }
context.getOut().setSilent(true, pageContext);
return SKIP_BODY;
}
- catch (ServletException e) {
- throw new StripesJspException(e);
+ catch (Exception e) {
+ log.error(e, "Unhandled exception trying to render component \"",
getName(),
+ "\" to a string in context ", context.getRenderPage(), "
-> ", context
+ .getDefinitionPage());
+
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ else
+ throw new StripesJspException(e);
}
- catch (IOException e) {
- throw new StripesJspException(e);
- }
}
/**
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-06-07 20:51:40 UTC (rev 1252)
+++
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutWriter.java
2010-06-08 20:03:28 UTC (rev 1253)
@@ -78,6 +78,7 @@
* closed and its contents retrieved by calling {...@link
#closeBuffer(PageContext)}.
*/
public void openBuffer(PageContext pageContext) {
+ log.trace("Open buffer");
tryFlush(pageContext);
writers.add(new StringWriter(1024));
}
@@ -90,7 +91,9 @@
*/
public String closeBuffer(PageContext pageContext) {
if (getOut() instanceof StringWriter) {
- return ((StringWriter) writers.removeLast()).toString();
+ String contents = ((StringWriter) writers.removeLast()).toString();
+ log.trace("Closed buffer: \"", contents, "\"");
+ return contents;
}
else {
throw new StripesRuntimeException(
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
ThinkGeek and WIRED's GeekDad team up for the Ultimate
GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the
lucky parental unit. See the prize list and enter to win:
http://p.sf.net/sfu/thinkgeek-promo
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development