You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2008/12/22 20:50:28 UTC

svn commit: r728754 [1/3] - in /tapestry/tapestry5/trunk: ./ src/site/apt/ src/site/apt/guide/ tapestry-core/ tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/ tapestry-core/src/main/java/org/apache/tapestry5/dom/ tapestry-core/src/m...

Author: hlship
Date: Mon Dec 22 11:50:26 2008
New Revision: 728754

URL: http://svn.apache.org/viewvc?rev=728754&view=rev
Log:
TAP5-417: Merge performance changes into trunk (5.1)

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/MapHolder.java
      - copied unchanged from r728733, tapestry/tapestry5/branches/5.0/tapestry-core/src/main/java/org/apache/tapestry5/dom/MapHolder.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/ParameterAccess.java
      - copied unchanged from r728733, tapestry/tapestry5/branches/5.0/tapestry-core/src/main/java/org/apache/tapestry5/internal/ParameterAccess.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/
      - copied from r728733, tapestry/tapestry5/branches/5.0/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/CompositeRenderCommand.java
      - copied unchanged from r728733, tapestry/tapestry5/branches/5.0/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/CompositeRenderCommand.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EnvironmentalAccessImpl.java
      - copied unchanged from r728733, tapestry/tapestry5/branches/5.0/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EnvironmentalAccessImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/RenderPhaseEventHandler.java
      - copied unchanged from r728733, tapestry/tapestry5/branches/5.0/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/RenderPhaseEventHandler.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/EnvironmentalAccess.java
      - copied unchanged from r728733, tapestry/tapestry5/branches/5.0/tapestry-core/src/main/java/org/apache/tapestry5/services/EnvironmentalAccess.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/pageload/
      - copied from r728733, tapestry/tapestry5/branches/5.0/tapestry-core/src/test/java/org/apache/tapestry5/internal/pageload/
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/pageload/CompositeRenderCommandTest.java
      - copied unchanged from r728733, tapestry/tapestry5/branches/5.0/tapestry-core/src/test/java/org/apache/tapestry5/internal/pageload/CompositeRenderCommandTest.java
Removed:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/PageElement.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/ParameterWorkerTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/components/DefaultParameterBindingMethodComponent.java
Modified:
    tapestry/tapestry5/trunk/   (props changed)
    tapestry/tapestry5/trunk/pom.xml
    tapestry/tapestry5/trunk/src/site/apt/guide/parameters.apt
    tapestry/tapestry5/trunk/src/site/apt/upgrade.apt
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Loop.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/AbstractMarkupModel.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalComponentResources.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/model/MutableComponentModelImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassTransformerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EnvironmentImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EventImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactory.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactoryImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageLoaderProcessor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageResponseRendererImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RenderQueueImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResponseImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/BlockImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/BodyPageElement.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/CommentPageElement.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElement.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElementImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/DTDPageElement.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ExpansionPageElement.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/InternalComponentResourcesImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/StartElementPageElement.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/TextPageElement.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/AbstractIncludeAssetWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/EnvironmentalWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/RenderPhaseMethodWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ComponentModel.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableComponentModel.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/Environment.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformConstants.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/test/TapestryTestCase.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/LoopTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/model/MutableComponentModelImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ComponentEventImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PageElementFactoryImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/BlockImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/ComponentPageElementImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/structure/ExpansionPageElementImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/RenderPhaseMethodWorkerTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/log4j.properties
    tapestry/tapestry5/trunk/tapestry-core/tapestry-core.iml
    tapestry/tapestry5/trunk/tapestry-hibernate-core/pom.xml
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/TypeCoercerImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/CollectionFactory.java

Propchange: tapestry/tapestry5/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Dec 22 11:50:26 2008
@@ -1,2 +1,4 @@
-/tapestry/tapestry5/branches/5.0:717929-719744
+/tapestry/tapestry5/branches/5.0:717929-719744,723395-728733
+/tapestry/tapestry5/branches/hlship-5.0-perf:726734-728728
 /tapestry/tapestry5/tags/releases/5.0.17:719745
+/tapestry/tapestry5/tags/releases/hlship-5.0-perf:726733

Modified: tapestry/tapestry5/trunk/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/pom.xml?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/pom.xml (original)
+++ tapestry/tapestry5/trunk/pom.xml Mon Dec 22 11:50:26 2008
@@ -11,7 +11,7 @@
     <url>http://tapestry.apache.org/tapestry5.1/</url>
     <issueManagement>
         <system>Jira</system>
-        <url>https://issues.apache.org/jira/browse/TAPESTRY</url>
+        <url>https://issues.apache.org/jira/browse/TAP5</url>
     </issueManagement>
     <licenses>
         <license>

Modified: tapestry/tapestry5/trunk/src/site/apt/guide/parameters.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/apt/guide/parameters.apt?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/src/site/apt/guide/parameters.apt (original)
+++ tapestry/tapestry5/trunk/src/site/apt/guide/parameters.apt Mon Dec 22 11:50:26 2008
@@ -356,16 +356,16 @@
   
   Binding defaultMessage()
   {
-    return bindingSource.newBinding("default value", resources, "defaultMessage");
+    return bindingSource.newBinding("default value", resources, "basicMessage");
   }
   
-  public String getDefaultMessage()
+  public String getBasicMessage()
   {
     return String.format("Maximum field length is %d.", maxLength);
   }
 +---+  
   
-  In this example, a property expression, "defaultMessage", is used to access the message dynamically.
+  In this example, a property expression, "basicMessage", is used to access the message dynamically.
   
   Alternately, the previous example may be written even more succinctly as:
   
@@ -381,11 +381,12 @@
   
   String defaultMessage()
   {
-    return String.format("Maximum field length is %d.", _maxLength);
+    return String.format("Maximum field length is %d.", maxLength);
   }  
 +---+  
   
-  This form is more like using the "literal:" binding prefix, except that the literal value is computed by the defaultMessage() method.
+  This form is more like using the "literal:" binding prefix, except that the
+  literal value is computed by the defaultMessage() method.
   
   Obviously, this is a lot more work than simply specifying a default value as part of the Parameter annotation. In the few
   real cases where this is approach is used, the default binding method will usually deduce a proper binding, typically in terms of

Modified: tapestry/tapestry5/trunk/src/site/apt/upgrade.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/apt/upgrade.apt?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/src/site/apt/upgrade.apt (original)
+++ tapestry/tapestry5/trunk/src/site/apt/upgrade.apt Mon Dec 22 11:50:26 2008
@@ -12,6 +12,16 @@
   You should also check the {{{release-notes.html}project-wide release notes}} for information
   about bugs fixes and other improvements.
 
+Release 5.0.19
+
+  As part of the changes related to
+  {{{https://issues.apache.org/jira/browse/TAP5-417}TAP5-417: Tapestry 5.0 Performance Improvements}},
+  you should be aware that Tapestry will now optimize the render phase state machine.
+  This is only relevant to advanced users who have written a ComponentClassTransformWorker
+  that adds logic to a render phase: it is necessary to
+  {{{apidocs/org/apache/tapestry5/model/MutableComponentModel.html#addRenderPhase(Class)}inform
+  Tapestry that the render phase should be invoked}}.
+
 Release 5.0.16
 
   The client-side class Tapestry.Zone has been renamed to Tapestry.ZoneManager.

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Loop.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Loop.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Loop.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Loop.java Mon Dec 22 11:50:26 2008
@@ -332,7 +332,7 @@
      * Begins a new heartbeat.
      */
     @BeginRender
-    void begin()
+    void begin(MarkupWriter writer)
     {
         value = iterator.next();
 
@@ -352,15 +352,7 @@
         if (formSupport != null && volatileState) formSupport.store(this, ADVANCE_VOLATILE);
 
         startHeartbeat();
-    }
-
-    private void startHeartbeat()
-    {
-        heartbeat.begin();
-    }
 
-    void beforeRenderBody(MarkupWriter writer)
-    {
         if (element != null)
         {
             writer.element(element);
@@ -368,17 +360,19 @@
         }
     }
 
-    void afterRenderBody(MarkupWriter writer)
+    private void startHeartbeat()
     {
-        if (element != null) writer.end();
+        heartbeat.begin();
     }
 
     /**
      * Ends the current heartbeat.
      */
     @AfterRender
-    boolean after()
+    boolean after(MarkupWriter writer)
     {
+        if (element != null) writer.end();
+
         endHeartbeat();
 
         if (formSupport != null) formSupport.store(this, END_HEARTBEAT);

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/AbstractMarkupModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/AbstractMarkupModel.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/AbstractMarkupModel.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/AbstractMarkupModel.java Mon Dec 22 11:50:26 2008
@@ -19,54 +19,97 @@
     /**
      * Passes all characters but '&lt;', '&gt;' and '&amp;' through unchanged.
      */
-    public void encode(String content, StringBuilder buffer)
-    {
-        encode(content, false, buffer);
-    }
-
     public String encode(String content)
     {
-        StringBuilder buffer = new StringBuilder(content.length() * 2);
+        int length = content.length();
 
-        encode(content, false, buffer);
+        StringBuilder builder = null;
 
-        return buffer.toString();
-    }
+        for (int i = 0; i < length; i++)
+        {
+            char ch = content.charAt(i);
 
-    public void encodeQuoted(String content, StringBuilder buffer)
-    {
-        encode(content, true, buffer);
+            switch (ch)
+            {
+                case '<':
+
+                    if (builder == null)
+                    {
+                        builder = new StringBuilder(2 * length);
+
+                        builder.append(content.substring(0, i));
+                    }
+
+                    builder.append("&lt;");
+                    continue;
+
+                case '>':
+
+                    if (builder == null)
+                    {
+                        builder = new StringBuilder(2 * length);
+
+                        builder.append(content.substring(0, i));
+                    }
+
+                    builder.append("&gt;");
+                    continue;
+
+                case '&':
+
+                    if (builder == null)
+                    {
+                        builder = new StringBuilder(2 * length);
+
+                        builder.append(content.substring(0, i));
+                    }
+
+                    builder.append("&amp;");
+                    continue;
+
+                default:
+
+                    if (builder != null)
+                        builder.append(ch);
+            }
+        }
+
+        return builder == null ? content : builder.toString();
     }
 
-    private void encode(String content, boolean encodeQuotes, StringBuilder buffer)
+    public void encodeQuoted(String content, StringBuilder builder)
     {
-        char[] array = content.toCharArray();
+        int length = content.length();
 
-        for (char ch : array)
+        for (int i = 0; i < length; i++)
         {
+            char ch = content.charAt(i);
+
             switch (ch)
             {
                 case '<':
-                    buffer.append("&lt;");
+
+                    builder.append("&lt;");
                     continue;
 
                 case '>':
-                    buffer.append("&gt;");
+
+                    builder.append("&gt;");
                     continue;
 
                 case '&':
-                    buffer.append("&amp;");
+
+                    builder.append("&amp;");
                     continue;
 
                 case '"':
-                    if (encodeQuotes)
-                    {
-                        buffer.append("&quot;");
-                        continue;
-                    }
+
+                    builder.append("&quot;");
+                    continue;
 
                 default:
-                    buffer.append(ch);
+
+                    builder.append(ch);
             }
         }
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java Mon Dec 22 11:50:26 2008
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.dom;
 
 import java.io.PrintWriter;
+import java.util.Map;
 
 /**
  * A node that stores parsed character content (CDATA).  For XML documents (as per {@link MarkupModel#isXML()}, this
@@ -32,7 +33,7 @@
     }
 
     @Override
-    void toMarkup(Document document, PrintWriter writer)
+    void toMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
     {
         MarkupModel model = document.getMarkupModel();
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java Mon Dec 22 11:50:26 2008
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.dom;
 
 import java.io.PrintWriter;
+import java.util.Map;
 
 /**
  * A node that represents a comment within the DOM.
@@ -31,7 +32,7 @@
     }
 
     @Override
-    void toMarkup(Document document, PrintWriter writer)
+    void toMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
     {
         writer.print("<!-- ");
         writer.print(comment);

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java Mon Dec 22 11:50:26 2008
@@ -17,6 +17,8 @@
 import org.apache.tapestry5.ioc.internal.util.Defense;
 
 import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.Map;
 
 /**
  * The root node of a DOM.
@@ -112,7 +114,7 @@
     }
 
     @Override
-    public void toMarkup(Document document, PrintWriter writer)
+    public void toMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
     {
         if (rootElement == null) throw new IllegalStateException(DomMessages.noRootElement());
 
@@ -132,7 +134,9 @@
             dtd.toMarkup(writer);
         }
 
-        rootElement.toMarkup(document, writer);
+        Map<String, String> initialNamespaceMap = Collections.emptyMap();
+
+        rootElement.toMarkup(document, writer, initialNamespaceMap);
     }
 
     @Override
@@ -163,4 +167,12 @@
     {
         dtd = new DTD(name, publicId, systemId);
     }
+
+    @Override
+    protected Map<String, String> getNamespaceURIToPrefix()
+    {
+        if (rootElement == null) return Collections.emptyMap();
+
+        return rootElement.getNamespaceURIToPrefix();
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java Mon Dec 22 11:50:26 2008
@@ -16,10 +16,7 @@
 
 import org.apache.tapestry5.internal.TapestryInternalUtils;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
-import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newLinkedList;
-import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newMap;
 import org.apache.tapestry5.ioc.internal.util.Defense;
-import static org.apache.tapestry5.ioc.internal.util.Defense.notBlank;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 
 import java.io.PrintWriter;
@@ -138,11 +135,11 @@
      */
     public Element attribute(String namespace, String name, String value)
     {
-        notBlank(name, "name");
+        Defense.notBlank(name, "name");
 
         if (value == null) return this;
 
-        if (attributes == null) attributes = newMap();
+        if (attributes == null) attributes = CollectionFactory.newMap();
 
         if (!attributes.containsKey(name)) attributes.put(name, new Attribute(namespace, name, value));
 
@@ -174,7 +171,7 @@
      */
     public Element forceAttributes(String... namesAndValues)
     {
-        if (attributes == null) attributes = newMap();
+        if (attributes == null) attributes = CollectionFactory.newMap();
 
         int i = 0;
 
@@ -203,7 +200,7 @@
      */
     public Element element(String name, String... namesAndValues)
     {
-        notBlank(name, "name");
+        Defense.notBlank(name, "name");
 
         Element child = newChild(new Element(this, null, name));
 
@@ -221,14 +218,14 @@
      */
     public Element elementNS(String namespace, String name)
     {
-        notBlank(name, "name");
+        Defense.notBlank(name, "name");
 
         return newChild(new Element(this, namespace, name));
     }
 
     public Element elementAt(int index, String name, String... namesAndValues)
     {
-        notBlank(name, "name");
+        Defense.notBlank(name, "name");
 
         Element child = new Element(this, null, name);
         child.attributes(namesAndValues);
@@ -290,15 +287,15 @@
     }
 
     @Override
-    void toMarkup(Document document, PrintWriter writer)
+    void toMarkup(Document document, PrintWriter writer, Map<String, String> containerNamespacePrefixToURI)
     {
-        Map<String, String> namespaceToPrefixMap = createNamespaceURIToNamespaceMap();
+        Map<String, String> localNamespacePrefixToURI = createNamespaceURIToPrefix(containerNamespacePrefixToURI);
 
         MarkupModel markupModel = document.getMarkupModel();
 
         StringBuilder builder = new StringBuilder();
 
-        String prefixedElementName = toPrefixedName(namespaceToPrefixMap, namespace, name);
+        String prefixedElementName = toPrefixedName(localNamespacePrefixToURI, namespace, name);
 
         builder.append("<").append(prefixedElementName);
 
@@ -308,7 +305,7 @@
         {
             Attribute attribute = attributes.get(key);
 
-            attribute.render(markupModel, builder, namespaceToPrefixMap);
+            attribute.render(markupModel, builder, localNamespacePrefixToURI);
         }
 
         // Next, emit namespace declarations for each namespace.
@@ -343,14 +340,20 @@
 
         writer.print(builder.toString());
 
-        if (hasChildren) writeChildMarkup(document, writer);
+        if (hasChildren) writeChildMarkup(document, writer, localNamespacePrefixToURI);
 
         // Dangerous -- perhaps it should be an error for a tag of type OMIT to even have children!
         // We'll certainly be writing out unbalanced markup in that case.
 
         if (style == EndTagStyle.OMIT) return;
 
-        if (hasChildren || style == EndTagStyle.REQUIRE) writer.printf("</%s>", prefixedElementName);
+        if (hasChildren || style == EndTagStyle.REQUIRE)
+        {
+            // TAP5-471: Avoid use of printf().
+            writer.print("</");
+            writer.print(prefixedElementName);
+            writer.print(">");
+        }
     }
 
     private String toPrefixedName(Map<String, String> namespaceURIToPrefix, String namespace, String name)
@@ -383,7 +386,7 @@
     {
         Defense.notNull(id, "id");
 
-        LinkedList<Element> queue = newLinkedList();
+        LinkedList<Element> queue = CollectionFactory.newLinkedList();
 
         queue.add(this);
 
@@ -418,7 +421,7 @@
      */
     public Element find(String path)
     {
-        notBlank(path, "path");
+        Defense.notBlank(path, "path");
 
         Element search = this;
 
@@ -555,28 +558,18 @@
     }
 
     /**
-     * Creates the URI to namespace map for this element, which reflects namespace mappings from containing elements. In
-     * addition, automatic namespaces are defined for any URIs that are not explicitly mapped (this occurs sometimes in
-     * Ajax partial render scenarios).
+     * Creates the URI to namespace prefix map for this element, which reflects namespace mappings from containing
+     * elements. In addition, automatic namespaces are defined for any URIs that are not explicitly mapped (this occurs
+     * sometimes in Ajax partial render scenarios).
      *
      * @return a mapping from namespace URI to namespace prefix
      */
-    private Map<String, String> createNamespaceURIToNamespaceMap()
+    private Map<String, String> createNamespaceURIToPrefix(Map<String, String> containerNamespaceURIToPrefix)
     {
-        Map<String, String> result = CollectionFactory.newMap();
-
-        List<Element> elements = gatherParentElements();
+        MapHolder holder = new MapHolder(containerNamespaceURIToPrefix);
 
-        elements.add(this);
+        holder.putAll(namespaceToPrefix);
 
-        for (Element e : elements)
-        {
-            // Put each namespace map, when present, overwriting child element's mappings
-            // over parent elements (by virtue of order in the list).
-
-            if (e.namespaceToPrefix != null)
-                result.putAll(e.namespaceToPrefix);
-        }
 
         // result now contains all the mappings, including this element's.
 
@@ -587,10 +580,10 @@
 
             // Add the namespace for the element as the default namespace.
 
-            if (!result.containsKey(namespace))
+            if (!holder.getResult().containsKey(namespace))
             {
                 defineNamespace(namespace, "");
-                result.put(namespace, "");
+                holder.put(namespace, "");
             }
         }
 
@@ -599,21 +592,23 @@
         if (attributes != null)
         {
             for (Attribute a : attributes.values())
-                addMappingIfNeeded(result, a.namespace);
+                addMappingIfNeeded(holder, a.namespace);
         }
 
-        return result;
+        return holder.getResult();
     }
 
-    private void addMappingIfNeeded(Map<String, String> masterURItoPrefixMap, String namespace)
+    private void addMappingIfNeeded(MapHolder holder, String namespace)
     {
         if (InternalUtils.isBlank(namespace)) return;
 
-        if (masterURItoPrefixMap.containsKey(namespace)) return;
+        Map<String, String> current = holder.getResult();
+
+        if (current.containsKey(namespace)) return;
 
         // A missing namespace.
 
-        Set<String> prefixes = CollectionFactory.newSet(masterURItoPrefixMap.values());
+        Set<String> prefixes = CollectionFactory.newSet(holder.getResult().values());
 
         // A clumsy way to find a unique id for the new namespace.
 
@@ -624,9 +619,8 @@
 
             if (!prefixes.contains(prefix))
             {
-
                 defineNamespace(namespace, prefix);
-                masterURItoPrefixMap.put(namespace, prefix);
+                holder.put(namespace, prefix);
                 return;
             }
 
@@ -634,26 +628,28 @@
         }
     }
 
-    /**
-     * Returns the parent elements containing this element, ordered by depth (the root element is first, the current
-     * element's parent is last).
-     *
-     * @return list of elements
-     */
-    private List<Element> gatherParentElements()
+    @Override
+    protected Map<String, String> getNamespaceURIToPrefix()
     {
-        List<Element> result = CollectionFactory.newList();
+        MapHolder holder = new MapHolder();
+
+        List<Element> elements = CollectionFactory.newList(this);
 
         Element cursor = parent;
 
         while (cursor != null)
         {
-            result.add(cursor);
+            elements.add(cursor);
             cursor = cursor.parent;
         }
 
-        Collections.reverse(result);
+        // Reverse the list, so that later elements will overwrite earlier ones.
+
+        Collections.reverse(elements);
+
+        for (Element e : elements)
+            holder.putAll(e.namespaceToPrefix);
 
-        return result;
+        return holder.getResult();
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java Mon Dec 22 11:50:26 2008
@@ -21,6 +21,7 @@
 import java.io.PrintWriter;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 /**
  * A node within the DOM.
@@ -95,12 +96,12 @@
         return children != null && !children.isEmpty();
     }
 
-    void writeChildMarkup(Document document, PrintWriter writer)
+    void writeChildMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
     {
         if (children == null) return;
 
         for (Node child : children)
-            child.toMarkup(writer);
+            child.toMarkup(document, writer, namespaceURIToPrefix);
     }
 
     /**
@@ -110,7 +111,7 @@
     {
         PrintOutCollector collector = new PrintOutCollector();
 
-        writeChildMarkup(getDocument(), collector.getPrintWriter());
+        writeChildMarkup(getDocument(), collector.getPrintWriter(), null);
 
         return collector.getPrintOut();
     }
@@ -146,13 +147,20 @@
      */
     public void toMarkup(PrintWriter writer)
     {
-        toMarkup(getDocument(), writer);
+        toMarkup(getDocument(), writer, getNamespaceURIToPrefix());
+    }
+
+    protected Map<String, String> getNamespaceURIToPrefix()
+    {
+        // For non-Elements, the container (which should be an Element) will provide the mapping.
+
+        return container.getNamespaceURIToPrefix();
     }
 
     /**
      * Implemented by each subclass, with the document passed in for efficiency.
      */
-    abstract void toMarkup(Document document, PrintWriter writer);
+    abstract void toMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix);
 
     /**
      * Moves this node so that it becomes a sibling of the element, ordered just before the element.

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java Mon Dec 22 11:50:26 2008
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.dom;
 
 import java.io.PrintWriter;
+import java.util.Map;
 
 /**
  * A specialized node in the document tree that contains raw markup to be printed to the client exactly as-is.
@@ -34,7 +35,7 @@
      * Prints the text exactly as is, no translations, filtering, etc.
      */
     @Override
-    void toMarkup(Document document, PrintWriter writer)
+    void toMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
     {
         writer.print(text);
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java Mon Dec 22 11:50:26 2008
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.dom;
 
 import java.io.PrintWriter;
+import java.util.Map;
 
 /**
  * A type of node that contains text.
@@ -46,7 +47,7 @@
     }
 
     @Override
-    void toMarkup(Document document, PrintWriter writer)
+    void toMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
     {
         String encoded = document.getMarkupModel().encode(buffer.toString());
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalComponentResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalComponentResources.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalComponentResources.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalComponentResources.java Mon Dec 22 11:50:26 2008
@@ -46,45 +46,6 @@
     void persistFieldChange(String fieldName, Object newValue);
 
     /**
-     * Reads the value of a parameter, via the parameter's {@link org.apache.tapestry5.Binding}.
-     *
-     * @param <T>
-     * @param parameterName the name of the parameter to read
-     * @param expectedType  the expected type of parameter
-     * @return the value for the parameter, or null if the parameter is not bound.
-     */
-    <T> T readParameter(String parameterName, Class<T> expectedType);
-
-    /**
-     * Used by generated component code to read a parameter value.
-     *
-     * @param parameterName   the name of the parameter to read
-     * @param desiredTypeName the class name of the desired value (classes will be resolved in the component class
-     *                        loader)
-     * @return the value coerced to the correct type
-     */
-    Object readParameter(String parameterName, String desiredTypeName);
-
-    /**
-     * Updates a parameter. It is an error to update a parameter which is not bound. The parameter {@link
-     * org.apache.tapestry5.Binding binding} may also not support updates.
-     *
-     * @param <T>
-     * @param parameterName  of parameter to update
-     * @param parameterValue new value (which may be null)
-     */
-    <T> void writeParameter(String parameterName, T parameterValue);
-
-    /**
-     * Returns true if the named parameter's {@link org.apache.tapestry5.Binding} is invariant, false if otherwise, or
-     * if the parameter is not bound. Invariant bindings are cached more aggressively than variant bindings.
-     *
-     * @param parameterName the name of parameter to check for invariance
-     * @return true if the binding is an invariant, false if the binding has no fixed value
-     */
-    boolean isInvariant(String parameterName);
-
-    /**
      * Allows the resources to cleanup any render-time only data.
      */
     void postRenderCleanup();
@@ -93,4 +54,12 @@
      * Invoked to make the receiver queue itself to be rendered.
      */
     void queueRender(RenderQueue queue);
+
+    /**
+     * Gets access object for the parameter.
+     *
+     * @param parameterName
+     * @return object used to read and update the parameter
+     */
+    ParameterAccess getParameterAccess(String parameterName);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/model/MutableComponentModelImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/model/MutableComponentModelImpl.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/model/MutableComponentModelImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/model/MutableComponentModelImpl.java Mon Dec 22 11:50:26 2008
@@ -26,6 +26,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Internal implementation of {@link org.apache.tapestry5.model.MutableComponentModel}.
@@ -59,6 +60,8 @@
 
     private Map<String, String> metaData;
 
+    private Set<Class> handledRenderPhases;
+
     public MutableComponentModelImpl(String componentClassName, Logger logger, Resource baseResource,
                                      ComponentModel parentModel)
     {
@@ -272,6 +275,15 @@
         metaData.put(key, value);
     }
 
+    public void addRenderPhase(Class renderPhase)
+    {
+        Defense.notNull(renderPhase, "renderPhase");
+
+        if (handledRenderPhases == null) handledRenderPhases = CollectionFactory.newSet();
+
+        handledRenderPhases.add(renderPhase);
+    }
+
     public String getMeta(String key)
     {
         String result = InternalUtils.get(metaData, key);
@@ -281,4 +293,16 @@
         return result;
     }
 
+    public Set<Class> getHandledRenderPhases()
+    {
+        Set<Class> result = CollectionFactory.newSet();
+
+        if (parentModel != null)
+            result.addAll(parentModel.getHandledRenderPhases());
+
+        if (handledRenderPhases != null)
+            result.addAll(handledRenderPhases);
+
+        return result;
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassTransformerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassTransformerImpl.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassTransformerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassTransformerImpl.java Mon Dec 22 11:50:26 2008
@@ -131,7 +131,7 @@
 
         String classname = ctClass.getName();
 
-        Logger transformLogger = loggerSource.getLogger("tapestry.transfomer." + classname);
+        Logger transformLogger = loggerSource.getLogger("tapestry.transformer." + classname);
         Logger logger = loggerSource.getLogger(classname);
 
         // If the parent class is in a controlled package, it will already have been loaded and

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EnvironmentImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EnvironmentImpl.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EnvironmentImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EnvironmentImpl.java Mon Dec 22 11:50:26 2008
@@ -14,11 +14,11 @@
 
 package org.apache.tapestry5.internal.services;
 
-import org.apache.tapestry5.ioc.ScopeConstants;
-import org.apache.tapestry5.ioc.annotations.Scope;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
-import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newLinkedList;
+import org.apache.tapestry5.ioc.internal.util.OneShotLock;
+import org.apache.tapestry5.ioc.services.ThreadCleanupListener;
 import org.apache.tapestry5.services.Environment;
+import org.apache.tapestry5.services.EnvironmentalAccess;
 
 import java.util.LinkedList;
 import java.util.List;
@@ -27,23 +27,29 @@
 /**
  * A non-threadsafe implementation (expects to use the "perthread" service lifecyle).
  */
-@Scope(ScopeConstants.PERTHREAD)
-public class EnvironmentImpl implements Environment
+public class EnvironmentImpl implements Environment, ThreadCleanupListener
 {
+
     // My generics mojo breaks down when we talk about the key and the value being related
     // types.
 
-    private final Map<Class, LinkedList> stacks = CollectionFactory.newMap();
+    private final Map<Class, LinkedList> typeToStack = CollectionFactory.newMap();
+
+    private final Map<Class, EnvironmentalAccessImpl> typeToAccess = CollectionFactory.newMap();
+
+    private final OneShotLock lock = new OneShotLock();
 
     @SuppressWarnings("unchecked")
     private <T> LinkedList<T> stackFor(Class<T> type)
     {
-        LinkedList<T> result = stacks.get(type);
+        lock.check();
+
+        LinkedList<T> result = typeToStack.get(type);
 
         if (result == null)
         {
-            result = newLinkedList();
-            stacks.put(type, result);
+            result = CollectionFactory.newLinkedList();
+            typeToStack.put(type, result);
         }
 
         return result;
@@ -63,7 +69,7 @@
         if (result == null)
         {
             List<Class> types = CollectionFactory.newList();
-            for (Map.Entry<Class, LinkedList> e : stacks.entrySet())
+            for (Map.Entry<Class, LinkedList> e : typeToStack.entrySet())
             {
                 LinkedList list = e.getValue();
 
@@ -80,6 +86,8 @@
     {
         LinkedList<T> stack = stackFor(type);
 
+        invalidate(type);
+
         return stack.removeFirst();
     }
 
@@ -91,11 +99,47 @@
 
         stack.addFirst(instance);
 
+        invalidate(type);
+
         return result;
     }
 
     public void clear()
     {
-        stacks.clear();
+        lock.check();
+
+        typeToStack.clear();
+
+        for (EnvironmentalAccessImpl closure : typeToAccess.values())
+        {
+            closure.invalidate();
+        }
+    }
+
+    public <T> EnvironmentalAccess<T> getAccess(Class<T> type)
+    {
+        lock.check();
+
+        EnvironmentalAccessImpl access = typeToAccess.get(type);
+
+        if (access == null)
+        {
+            access = new EnvironmentalAccessImpl(this, type);
+            typeToAccess.put(type, access);
+        }
+
+        return access;
+    }
+
+    public void threadDidCleanup()
+    {
+        lock.lock();
+    }
+
+    void invalidate(Class type)
+    {
+        EnvironmentalAccessImpl access = typeToAccess.get(type);
+
+        if (access != null) access.invalidate();
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EventImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EventImpl.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EventImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EventImpl.java Mon Dec 22 11:50:26 2008
@@ -30,6 +30,8 @@
 
     private final Logger logger;
 
+    private final boolean debugEnabled;
+
     /**
      * @param handler informed of return values from methods, deems when the event is aborted
      * @param logger  used to log method invocations
@@ -38,6 +40,9 @@
     {
         this.handler = notNull(handler, "handler");
         this.logger = logger;
+
+        // TAP5-471: Thousands of calls to isDebugEnabled() do add up
+        debugEnabled = logger.isDebugEnabled();
     }
 
     public boolean isAborted()
@@ -47,7 +52,8 @@
 
     public void setMethodDescription(String methodDescription)
     {
-        logger.debug(TapestryMarkers.EVENT_HANDLER_METHOD, "Invoking: {}", methodDescription);
+        if (debugEnabled)
+            logger.debug(TapestryMarkers.EVENT_HANDLER_METHOD, "Invoking: " + methodDescription);
 
         this.methodDescription = methodDescription;
     }
@@ -60,11 +66,12 @@
         // this should never, ever happen. But what the hell,
         // let's check anyway.
 
-        if (aborted) throw new IllegalStateException(ServicesMessages
-                .componentEventIsAborted(methodDescription));
+        if (aborted)
+            throw new IllegalStateException(ServicesMessages.componentEventIsAborted(methodDescription));
 
 
-        if (result != null) aborted |= handler.handleResult(result);
+        if (result != null)
+            aborted |= handler.handleResult(result);
 
         return aborted;
     }
@@ -73,4 +80,10 @@
     {
         return methodDescription;
     }
+
+    public void reset()
+    {
+        aborted = false;
+        methodDescription = null;
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactory.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactory.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactory.java Mon Dec 22 11:50:26 2008
@@ -21,8 +21,8 @@
 import org.apache.tapestry5.internal.parser.ExpansionToken;
 import org.apache.tapestry5.internal.structure.ComponentPageElement;
 import org.apache.tapestry5.internal.structure.Page;
-import org.apache.tapestry5.internal.structure.PageElement;
 import org.apache.tapestry5.ioc.Location;
+import org.apache.tapestry5.runtime.RenderCommand;
 import org.apache.tapestry5.services.BindingSource;
 
 import java.util.Locale;
@@ -32,9 +32,9 @@
  */
 public interface PageElementFactory
 {
-    PageElement newAttributeElement(ComponentResources componentResources, AttributeToken token);
+    RenderCommand newAttributeElement(ComponentResources componentResources, AttributeToken token);
 
-    PageElement newExpansionElement(ComponentResources componentResources, ExpansionToken token);
+    RenderCommand newExpansionElement(ComponentResources componentResources, ExpansionToken token);
 
     /**
      * Creates a new binding as with {@link BindingSource#newBinding(String, ComponentResources, ComponentResources,

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactoryImpl.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactoryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageElementFactoryImpl.java Mon Dec 22 11:50:26 2008
@@ -27,6 +27,7 @@
 import org.apache.tapestry5.ioc.internal.util.TapestryException;
 import org.apache.tapestry5.ioc.services.TypeCoercer;
 import org.apache.tapestry5.model.ComponentModel;
+import org.apache.tapestry5.runtime.RenderCommand;
 import org.apache.tapestry5.runtime.RenderQueue;
 import org.apache.tapestry5.services.BindingSource;
 import org.apache.tapestry5.services.ComponentClassResolver;
@@ -74,7 +75,7 @@
         this.componentPageElementResourcesSource = componentPageElementResourcesSource;
     }
 
-    public PageElement newAttributeElement(ComponentResources componentResources, final AttributeToken token)
+    public RenderCommand newAttributeElement(ComponentResources componentResources, final AttributeToken token)
     {
         final StringProvider provider = parseAttributeExpansionExpression(token.getValue(), componentResources,
                                                                           token.getLocation());
@@ -82,14 +83,13 @@
         final String namespace = token.getNamespaceURI();
         final String name = token.getName();
 
-        return new PageElement()
+        return new RenderCommand()
         {
             public void render(MarkupWriter writer, RenderQueue queue)
             {
                 writer.attributeNS(namespace, name, provider.provideString());
             }
 
-            @Override
             public String toString()
             {
                 return String.format("AttributeNS[%s %s \"%s\"]", namespace, name, token.getValue());
@@ -176,7 +176,7 @@
         };
     }
 
-    public PageElement newExpansionElement(ComponentResources componentResources, ExpansionToken token)
+    public RenderCommand newExpansionElement(ComponentResources componentResources, ExpansionToken token)
     {
         Binding binding = bindingSource.newBinding("expansion", componentResources, componentResources,
                                                    BindingConstants.PROP, token.getExpression(), token.getLocation());

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageLoaderProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageLoaderProcessor.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageLoaderProcessor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageLoaderProcessor.java Mon Dec 22 11:50:26 2008
@@ -19,6 +19,7 @@
 import org.apache.tapestry5.ComponentResources;
 import org.apache.tapestry5.MarkupWriter;
 import org.apache.tapestry5.internal.bindings.LiteralBinding;
+import org.apache.tapestry5.internal.pageload.CompositeRenderCommand;
 import org.apache.tapestry5.internal.parser.*;
 import org.apache.tapestry5.internal.structure.*;
 import org.apache.tapestry5.ioc.Location;
@@ -26,6 +27,7 @@
 import org.apache.tapestry5.ioc.util.Stack;
 import org.apache.tapestry5.model.ComponentModel;
 import org.apache.tapestry5.model.EmbeddedComponentModel;
+import org.apache.tapestry5.runtime.RenderCommand;
 import org.apache.tapestry5.runtime.RenderQueue;
 import org.apache.tapestry5.services.BindingSource;
 
@@ -77,6 +79,8 @@
      */
     private final List<Runnable> finalization = CollectionFactory.newList();
 
+    private final List<RenderCommand> compositedRenderCommands = CollectionFactory.newList();
+
     private final IdAllocator idAllocator = new IdAllocator();
 
     private ComponentModel loadingComponentModel;
@@ -97,7 +101,7 @@
 
     private final ComponentTemplateSource templateSource;
 
-    private static final PageElement END_ELEMENT = new PageElement()
+    private static final RenderCommand END_ELEMENT = new RenderCommand()
     {
         public void render(MarkupWriter writer, RenderQueue queue)
         {
@@ -111,7 +115,7 @@
         }
     };
 
-    private static class RenderBodyElement implements PageElement
+    private static class RenderBodyElement implements RenderCommand
     {
         private final ComponentPageElement component;
 
@@ -271,7 +275,7 @@
     }
 
 
-    private void addToBody(PageElement element)
+    private void addToBody(RenderCommand element)
     {
         bodyPageElementStack.peek().addToBody(element);
     }
@@ -289,14 +293,16 @@
             return;
         }
 
-        PageElement element = pageElementFactory.newAttributeElement(loadingElement
+        RenderCommand element = pageElementFactory.newAttributeElement(loadingElement
                 .getComponentResources(), token);
 
-        addToBody(element);
+        addComposableCommand(element);
     }
 
     private void body()
     {
+        flushComposedCommands();
+
         addToBody(new RenderBodyElement(loadingElement));
 
         // BODY tokens are *not* matched by END_ELEMENT tokens. Nor will there be
@@ -305,9 +311,9 @@
 
     private void comment(CommentToken token)
     {
-        PageElement commentElement = new CommentPageElement(token.getComment());
+        RenderCommand commentElement = new CommentPageElement(token.getComment());
 
-        addToBody(commentElement);
+        addComposableCommand(commentElement);
     }
 
     /**
@@ -330,7 +336,7 @@
 
         boolean discard = discardEndTagStack.pop();
 
-        if (!discard) addToBody(END_ELEMENT);
+        if (!discard) addComposableCommand(END_ELEMENT);
 
         Runnable command = endElementCommandStack.pop();
 
@@ -341,10 +347,10 @@
 
     private void expansion(ExpansionToken token)
     {
-        PageElement element = pageElementFactory.newExpansionElement(loadingElement
+        RenderCommand element = pageElementFactory.newExpansionElement(loadingElement
                 .getComponentResources(), token);
 
-        addToBody(element);
+        addComposableCommand(element);
     }
 
     private String generateEmbeddedId(String embeddedType, IdAllocator idAllocator)
@@ -459,7 +465,7 @@
 
         BodyPageElement shunt = new BodyPageElement()
         {
-            public void addToBody(PageElement element)
+            public void addToBody(RenderCommand element)
             {
                 loadingElement.addToTemplate(element);
             }
@@ -528,6 +534,9 @@
             }
         }
 
+
+        flushComposedCommands();
+
         // For neatness / symmetry:
 
         bodyPageElementStack.pop(); // the shunt
@@ -553,36 +562,48 @@
         return result;
     }
 
-    private void cdata(CDATAToken token)
+    private void cdata(final CDATAToken token)
     {
-        final String content = token.getContent();
-
-        PageElement element = new PageElement()
+        RenderCommand element = new RenderCommand()
         {
             public void render(MarkupWriter writer, RenderQueue queue)
             {
-                writer.cdata(content);
+                writer.cdata(token.getContent());
+            }
+
+            @Override
+            public String toString()
+            {
+                return String.format("CDATA[%s]", token.getLocation());
             }
         };
 
-        addToBody(element);
+        addComposableCommand(element);
     }
 
     private void defineNamespacePrefix(final DefineNamespacePrefixToken token)
     {
-        PageElement element = new PageElement()
+        RenderCommand element = new RenderCommand()
         {
             public void render(MarkupWriter writer, RenderQueue queue)
             {
                 writer.defineNamespace(token.getNamespaceURI(), token.getNamespacePrefix());
             }
+
+            @Override
+            public String toString()
+            {
+                return String.format("DefineNamespace[%s %s]", token.getNamespacePrefix(), token.getNamespaceURI());
+            }
         };
 
-        addToBody(element);
+        addComposableCommand(element);
     }
 
     private void parameter(ParameterToken token)
     {
+        flushComposedCommands();
+
         ComponentPageElement element = activeElementStack.peek();
         String name = token.getName();
 
@@ -606,6 +627,8 @@
         {
             public void run()
             {
+                flushComposedCommands();
+
                 bodyPageElementStack.pop();
             }
         };
@@ -615,6 +638,7 @@
 
     private void block(BlockToken token)
     {
+        flushComposedCommands();
 
         String id = token.getId();
         // Don't use the page element factory here becauses we need something that is both Block and
@@ -686,6 +710,8 @@
         if (embeddedModel != null)
             bindParametersFromModel(embeddedModel, loadingElement, newComponent, newComponentBindings);
 
+        flushComposedCommands();
+
         addToBody(newComponent);
 
         // Remember to load the template for this new component
@@ -735,8 +761,7 @@
         {
             public void run()
             {
-                // May need a separate queue for this, to execute at the very end of page loading.
-
+                flushComposedCommands();
 
                 activeElementStack.pop();
                 bodyPageElementStack.pop();
@@ -778,9 +803,9 @@
 
     private void startElement(StartElementToken token)
     {
-        PageElement element = new StartElementPageElement(token.getNamespaceURI(), token.getName());
+        RenderCommand element = new StartElementPageElement(token.getNamespaceURI(), token.getName());
 
-        addToBody(element);
+        addComposableCommand(element);
 
         // Controls how attributes are interpretted.
         addAttributesAsComponentBindings = false;
@@ -794,9 +819,9 @@
 
     private void text(TextToken token)
     {
-        PageElement element = new TextPageElement(token.getText());
+        RenderCommand element = new TextPageElement(token.getText());
 
-        addToBody(element);
+        addComposableCommand(element);
     }
 
     private void dtd(DTDToken token)
@@ -804,7 +829,7 @@
         // first DTD encountered wins.
         if (dtdAdded) return;
 
-        PageElement element = new DTDPageElement(token.getName(), token.getPublicId(), token.getSystemId());
+        RenderCommand element = new DTDPageElement(token.getName(), token.getPublicId(), token.getSystemId());
         // since rendering via the markup writer is to the document tree,
         // we don't really care where this gets placed in the tree; the
         // DTDPageElement will set the dtd of the document directly, rather than
@@ -826,4 +851,37 @@
             loadTemplateForComponent(componentElement);
         }
     }
+
+    private void addComposableCommand(RenderCommand command)
+    {
+        compositedRenderCommands.add(command);
+    }
+
+    private void flushComposedCommands()
+    {
+        int count = compositedRenderCommands.size();
+
+        switch (count)
+        {
+            case 0:
+
+                return;
+
+            case 1:
+
+                addToBody(compositedRenderCommands.get(0));
+
+                break;
+
+            default:
+
+                RenderCommand[] commands = compositedRenderCommands.toArray(new RenderCommand[count]);
+
+                addToBody(new CompositeRenderCommand(commands));
+
+                break;
+        }
+
+        compositedRenderCommands.clear();
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageResponseRendererImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageResponseRendererImpl.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageResponseRendererImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageResponseRendererImpl.java Mon Dec 22 11:50:26 2008
@@ -20,6 +20,7 @@
 import org.apache.tapestry5.ioc.internal.util.Defense;
 import org.apache.tapestry5.services.MarkupWriterFactory;
 import org.apache.tapestry5.services.Response;
+import org.slf4j.Logger;
 
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -34,13 +35,16 @@
 
     private final Response response;
 
+    private final Logger logger;
+
     public PageResponseRendererImpl(MarkupWriterFactory markupWriterFactory, PageMarkupRenderer markupRenderer,
-                                    PageContentTypeAnalyzer pageContentTypeAnalyzer, Response response)
+                                    PageContentTypeAnalyzer pageContentTypeAnalyzer, Response response, Logger logger)
     {
         this.markupWriterFactory = markupWriterFactory;
         this.markupRenderer = markupRenderer;
         this.pageContentTypeAnalyzer = pageContentTypeAnalyzer;
         this.response = response;
+        this.logger = logger;
     }
 
     public void renderPageResponse(Page page) throws IOException
@@ -58,8 +62,21 @@
 
         PrintWriter pw = response.getPrintWriter(contentType.toString());
 
+        long startNanos = System.nanoTime();
+
         writer.toMarkup(pw);
 
+        long endNanos = System.nanoTime();
+
+        if (logger.isDebugEnabled())
+        {
+            long elapsedNanos = endNanos - startNanos;
+            double elapsedSeconds = ((float) elapsedNanos) / 1000000000F;
+
+            logger.debug(String.format("Response DOM streamed to markup in %.3f seconds",
+                                       elapsedSeconds));
+        }
+
         pw.flush();
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RenderQueueImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RenderQueueImpl.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RenderQueueImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RenderQueueImpl.java Mon Dec 22 11:50:26 2008
@@ -41,6 +41,8 @@
 
     public void push(RenderCommand command)
     {
+        Defense.notNull(command, "command");
+
         queue.push(command);
     }
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResponseImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResponseImpl.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResponseImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResponseImpl.java Mon Dec 22 11:50:26 2008
@@ -20,9 +20,7 @@
 import org.apache.tapestry5.services.Response;
 
 import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
+import java.io.*;
 
 /**
  * Implementation of {@link Response} that wraps around an underlying {@link HttpServletResponse}.
@@ -44,7 +42,11 @@
 
         response.setContentType(contentType);
 
-        return response.getWriter();
+        OutputStream os = response.getOutputStream();
+
+        Writer w = new OutputStreamWriter(os, response.getCharacterEncoding());
+
+        return new PrintWriter(new BufferedWriter(w));
     }
 
     public String encodeURL(String URL)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/BlockImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/BlockImpl.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/BlockImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/BlockImpl.java Mon Dec 22 11:50:26 2008
@@ -29,7 +29,7 @@
     // We could lazily create this, but for (parameter) block elements the case
     // for an empty block is extremely rare.
 
-    private final List<PageElement> elements = CollectionFactory.newList();
+    private final List<RenderCommand> elements = CollectionFactory.newList();
 
     private final String description;
 
@@ -40,7 +40,7 @@
         this.description = description;
     }
 
-    public void addToBody(PageElement element)
+    public void addToBody(RenderCommand element)
     {
         elements.add(element);
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/BodyPageElement.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/BodyPageElement.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/BodyPageElement.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/BodyPageElement.java Mon Dec 22 11:50:26 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -14,11 +14,11 @@
 
 package org.apache.tapestry5.internal.structure;
 
-import org.apache.tapestry5.internal.services.PageLoader;
+import org.apache.tapestry5.runtime.RenderCommand;
 
 /**
- * A type of {@link PageElement} that has a body that can be added to. This is part of the constuction phase that is
- * faciliated by the {@link PageLoader}.
+ * A type of page element that has a body that can be added to. This is part of the constuction phase that is faciliated
+ * by the {@link org.apache.tapestry5.internal.services.PageLoader}.
  */
 public interface BodyPageElement
 {
@@ -27,5 +27,5 @@
      * component is defined as the portion of the container's template directly enclosed by component's start and end
      * elements.
      */
-    void addToBody(PageElement element);
+    void addToBody(RenderCommand element);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/CommentPageElement.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/CommentPageElement.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/CommentPageElement.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/CommentPageElement.java Mon Dec 22 11:50:26 2008
@@ -16,6 +16,7 @@
 
 import org.apache.tapestry5.MarkupWriter;
 import org.apache.tapestry5.internal.parser.CommentToken;
+import org.apache.tapestry5.runtime.RenderCommand;
 import org.apache.tapestry5.runtime.RenderQueue;
 
 /**
@@ -23,7 +24,7 @@
  *
  * @see CommentToken
  */
-public class CommentPageElement implements PageElement
+public class CommentPageElement implements RenderCommand
 {
     private final String text;
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElement.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElement.java?rev=728754&r1=728753&r2=728754&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElement.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/ComponentPageElement.java Mon Dec 22 11:50:26 2008
@@ -22,17 +22,14 @@
 import org.apache.tapestry5.internal.services.Instantiator;
 import org.apache.tapestry5.ioc.Location;
 import org.apache.tapestry5.model.ParameterModel;
-import org.apache.tapestry5.runtime.Component;
-import org.apache.tapestry5.runtime.ComponentEvent;
-import org.apache.tapestry5.runtime.PageLifecycleListener;
-import org.apache.tapestry5.runtime.RenderQueue;
+import org.apache.tapestry5.runtime.*;
 import org.slf4j.Logger;
 
 /**
- * Extended version of {@link org.apache.tapestry5.internal.structure.PageElement} for elements that are, in fact,
- * components (rather than just static markup).
+ * Defines an element of a page that is a component elements that are, in fact, components (rather than just static
+ * markup).
  */
-public interface ComponentPageElement extends ComponentResourcesCommon, InternalComponentResourcesCommon, PageElement, BodyPageElement, PageLifecycleListener
+public interface ComponentPageElement extends ComponentResourcesCommon, InternalComponentResourcesCommon, RenderCommand, BodyPageElement, PageLifecycleListener
 {
     /**
      * Returns the core component associated with this page element (as opposed to any mixins attached to the
@@ -61,7 +58,7 @@
      * the outermost portions of the component's template ... where a template contains elements that are all
      * components, those components will receive portions of the template as their body.
      */
-    void addToTemplate(PageElement element);
+    void addToTemplate(RenderCommand element);
 
     /**
      * Used during the contruction of a page to add a non-anonymous Block to the component.