Revision: 1252
          http://stripes.svn.sourceforge.net/stripes/?rev=1252&view=rev
Author:   bengunter
Date:     2010-06-07 20:51:40 +0000 (Mon, 07 Jun 2010)

Log Message:
-----------
STS-391: Fix an infinite recursion that occurred when multiple nested layouts 
defined components that referenced components by the same name from a calling 
render tag. The problem was that the first renderer would execute in context A, 
which would call context B, which would call back to context A again because it 
started over at the top of the context stack looking for a context that 
contained a definition for the component. This fixes that issue by tracking the 
current source context with each invocation and only recursing into contexts 
further down the stack.

Modified Paths:
--------------
    
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentRenderer.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 18:36:19 UTC (rev 1251)
+++ 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentRenderer.java
  2010-06-07 20:51:40 UTC (rev 1252)
@@ -46,6 +46,7 @@
 
     private LinkedList<PageContext> pageContext;
     private String componentName;
+    private LayoutContext sourceContext;
 
     /**
      * Create a new instance to render the named component to a string.
@@ -78,6 +79,16 @@
         return pageContext == null || pageContext.isEmpty() ? null : 
pageContext.getLast();
     }
 
+    /**
+     * Indicates the context in the stack of layout contexts against which the 
component is being
+     * rendered. Any attempt to render a component with the same name as the 
component currently
+     * being rendered must execute against a context further down the stack to 
avoid infinite
+     * recursion.
+     */
+    public LayoutContext getSourceContext() {
+        return sourceContext;
+    }
+
     @Override
     public String toString() {
         final PageContext pageContext = getPageContext();
@@ -95,11 +106,19 @@
         final boolean phaseFlag = context.isComponentRenderPhase();
         final String component = context.getComponent();
         final boolean silent = context.getOut().isSilent();
+        final LayoutContext currentSource = getSourceContext();
 
-        // Descend the layout context stack, trying each context where the 
component is registered
+        // Never use a context that sits higher up the stack than the current 
source
         log.debug("Stringify component \"", componentName, "\" in ", 
currentPage);
         LinkedList<LayoutContext> stack = LayoutContext.getStack(pageContext, 
true);
-        for (Iterator<LayoutContext> iter = stack.descendingIterator(); 
iter.hasNext();) {
+        Iterator<LayoutContext> iter = stack.descendingIterator();
+        if (currentSource != null) {
+            while (iter.hasNext() && iter.next() != currentSource)
+                ;
+        }
+
+        // Descend the stack from here, trying each context where the 
component is registered
+        while (iter.hasNext()) {
             // Skip contexts where the desired component is not registered or 
which would invoke the
             // current page again.
             final LayoutContext source = iter.next();
@@ -111,6 +130,7 @@
             }
 
             // Turn on the render phase flag and set the component to render
+            sourceContext = source;
             context.setComponentRenderPhase(true);
             context.setComponent(componentName);
 
@@ -139,6 +159,7 @@
                 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);


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

Reply via email to