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 2007/11/25 20:28:32 UTC

svn commit: r598036 [1/2] - in /tapestry/tapestry5/trunk: src/site/resources/ tapestry-core/src/main/java/org/apache/tapestry/ tapestry-core/src/main/java/org/apache/tapestry/corelib/components/ tapestry-core/src/main/java/org/apache/tapestry/corelib/m...

Author: hlship
Date: Sun Nov 25 11:28:27 2007
New Revision: 598036

URL: http://svn.apache.org/viewvc?rev=598036&view=rev
Log:
TAPESTRY-1650: Ajax support (still in progress).
- Add basic support for Zones
- Strip out the ActionResponseGenerator interface and simplify a bunch of other interfaces
- Modify Scriptaculous to NOT automatically load all the scripts in the library
- Make it easier to modfy the class attribute of a DOM Element


Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Zone.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxComponentActionRequestHandler.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxResponseGenerator.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableResponse.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Ajax.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Traditional.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneDemo.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/ZoneDemo.java
Removed:
    tapestry/tapestry5/trunk/src/site/resources/tap5devwiki.html
    tapestry/tapestry5/trunk/src/site/resources/tap5devwiki.xml
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LinkActionResponseGenerator.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ActionResponseGenerator.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ClientElement.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/TapestryConstants.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Errors.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Form.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultValidationDecorator.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxFilter.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClassResultProcessor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionRequestHandlerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DocumentHeadBuilderImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LocationRenderer.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ObjectComponentEventResultProcessor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageMarkupRenderer.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageMarkupRendererImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ReflectiveInstantiator.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RequestImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResponseImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StreamResponseResultProcessor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StringResultProcessor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/ActionLinkInvoker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/PageTesterModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableResponseImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentActionRequestFilter.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentActionRequestHandler.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentEventResultProcessor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestFilter.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestHandler.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Response.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/scriptaculous_1_8/scriptaculous.js
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/dom/DOMTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessorTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ObjectComponentEventResultProcessorTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/RequestImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/add_script.txt

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ClientElement.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ClientElement.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ClientElement.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ClientElement.java Sun Nov 25 11:28:27 2007
@@ -17,13 +17,13 @@
 
 /**
  * Interface for any kind of object (typically, a component) that can provide a
- * {@link #getClientId() client-side id}, typically used in the generation of client-side
+ * {@linkplain #getClientId() client-side id}, typically used in the generation of client-side
  * (JavaScript) logic. For components, the client id will be null or innaccurate until after the
  * component has rendered itself. Inside of any kind of loop, the clientId property is only accurate
  * just after the component has rendered, and before it renders again.
  * <p/>
  * Some components must be configured to provide a client id. In many cases, the client id matches
- * the component's {@link ComponentResourcesCommon#getId() component id}, typically passed through
+ * the component's {@linkplain ComponentResourcesCommon#getId() component id}, typically passed through
  * {@link PageRenderSupport#allocateClientId(String)} to ensure uniqueness.
  */
 public interface ClientElement

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/TapestryConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/TapestryConstants.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/TapestryConstants.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/TapestryConstants.java Sun Nov 25 11:28:27 2007
@@ -66,6 +66,15 @@
      */
     public static final String RESPONSE_ENCODING = "tapestry.response-encoding";
 
+    /**
+     * CSS class name that causes a rendered element to be invisible on the client side.
+     */
+    public static final String INVISIBLE_CLASS = "t-invisible";
+    /**
+     * All purpose CSS class name for anything related to Tapestry errors.
+     */
+    public static final String ERROR_CLASS = "t-error";
+
     private TapestryConstants()
     {
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java Sun Nov 25 11:28:27 2007
@@ -52,6 +52,13 @@
 
     private String _clientId;
 
+    /**
+     * Binding zone turns the link into a an Ajax control that causes the
+     * related zone to be updated.
+     */
+    @Parameter(defaultPrefix = TapestryConstants.LITERAL_BINDING_PREFIX)
+    private String _zone;
+
     void beginRender(MarkupWriter writer)
     {
         if (_disabled) return;
@@ -65,6 +72,11 @@
         writer.element("a", "href", link, "id", _clientId);
 
         _resources.renderInformalParameters(writer);
+
+        // TODO: Extend PRS or add a new environmental, to collect the link/zone connections
+        // and execute them as a single block (to generate less JavaScript).
+
+        if (_zone != null) _support.addScript("Tapestry.linkZone('%s', '%s');", _clientId, _zone);
     }
 
     void afterRender(MarkupWriter writer)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Errors.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Errors.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Errors.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Errors.java Sun Nov 25 11:28:27 2007
@@ -15,11 +15,12 @@
 package org.apache.tapestry.corelib.components;
 
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.TapestryConstants;
 import org.apache.tapestry.ValidationTracker;
 import org.apache.tapestry.annotations.Environmental;
 import org.apache.tapestry.annotations.Parameter;
 import org.apache.tapestry.corelib.internal.InternalMessages;
-import org.apache.tapestry.internal.InternalConstants;
+import org.apache.tapestry.dom.Element;
 import org.apache.tapestry.services.FormSupport;
 
 import java.util.List;
@@ -42,7 +43,7 @@
      * The CSS class for the div element rendered by the component. The default value is "t-error".
      */
     @Parameter
-    private String _class = InternalConstants.TAPESTRY_ERROR_CLASS;
+    private String _class = TapestryConstants.ERROR_CLASS;
 
     // Allow null so we can generate a better error message if missing
     @Environmental(false)
@@ -58,9 +59,9 @@
 
         if (_tracker == null) throw new RuntimeException(InternalMessages.encloseErrorsInForm());
 
-        String cssClass = _tracker.getHasErrors() ? _class : _class + " t-invisible";
+        Element div = writer.element("div", "class", _class, "id", _formSupport.getClientId() + ":errors");
 
-        writer.element("div", "class", cssClass, "id", _formSupport.getClientId() + ":errors");
+        if (!_tracker.getHasErrors()) div.addClassName(TapestryConstants.INVISIBLE_CLASS);
 
         // Inner div for the banner text
         writer.element("div");

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Form.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Form.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Form.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Form.java Sun Nov 25 11:28:27 2007
@@ -210,7 +210,7 @@
 
         _resources.renderInformalParameters(writer);
 
-        _div = writer.element("div", "class", "t-invisible");
+        _div = writer.element("div", "class", TapestryConstants.INVISIBLE_CLASS);
 
         for (String parameterName : link.getParameterNames())
         {
@@ -289,7 +289,7 @@
 
         try
         {
-            final Holder<ActionResponseGenerator> holder = Holder.create();
+            final Holder<Object> holder = Holder.create();
 
             ComponentEventHandler handler = new ComponentEventHandler()
             {
@@ -297,7 +297,20 @@
                 {
                     if (result instanceof Boolean) return ((Boolean) result);
 
-                    holder.put(_eventResultProcessor.processComponentEvent(result, component, methodDescription));
+                    // We want to process the event here, so that the component and method description are
+                    // properly identified. But that's going to cause a headache aborting the
+                    // event.
+
+                    try
+                    {
+                        _eventResultProcessor.processComponentEvent(result, component, methodDescription);
+                    }
+                    catch (IOException e)
+                    {
+                        throw new RuntimeException(e);
+                    }
+
+                    holder.put(true);
 
                     return true; // Abort other event processing.
                 }
@@ -305,6 +318,7 @@
 
             _resources.triggerEvent(PREPARE, context, handler);
 
+            //
             if (holder.hasValue()) return holder.get();
 
             // TODO: Ajax stuff will eventually mean there are multiple values for this parameter

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Zone.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Zone.java?rev=598036&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Zone.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Zone.java Sun Nov 25 11:28:27 2007
@@ -0,0 +1,78 @@
+// Copyright 2007 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.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.corelib.components;
+
+import org.apache.tapestry.ClientElement;
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.PageRenderSupport;
+import org.apache.tapestry.annotations.Environmental;
+import org.apache.tapestry.annotations.Parameter;
+import org.apache.tapestry.annotations.SupportsInformalParameters;
+import org.apache.tapestry.dom.Element;
+import org.apache.tapestry.ioc.annotations.Inject;
+
+
+/**
+ * A Zone is portion of the output page designed for easy dynamic updating via Ajax or other
+ * client-side effects.  A Zone renders out as a &lt;div&gt; element a may have content initially,
+ * or may only get its content as a result of client side activity.
+ * <p/>
+ * <p/>
+ * Renders informal parameters, adding CSS class "t-zone" and possibly, "t-invisible".
+ */
+@SupportsInformalParameters
+public class Zone implements ClientElement
+{
+    private String _clientId;
+
+    @Environmental
+    private PageRenderSupport _pageRenderSupport;
+
+    /**
+     * If true (the default) then the zone will render normally.  If false, then the "t-invisible"
+     * CSS class is added, which will make the zone initially invisible.
+     */
+    @Parameter
+    private boolean _visible = true;
+
+    @Inject
+    private ComponentResources _resources;
+
+    void beginRender(MarkupWriter writer)
+    {
+        _clientId = _pageRenderSupport.allocateClientId(_resources.getId());
+
+        Element e = writer.element("div", "id", _clientId);
+
+        _resources.renderInformalParameters(writer);
+
+        e.addClassName("t-zone");
+
+        if (!_visible) e.addClassName("t-invisible");
+
+        // And continue on to render the body
+    }
+
+    void afterRender(MarkupWriter writer)
+    {
+        writer.end(); // div
+    }
+
+    public String getClientId()
+    {
+        return _clientId;
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java Sun Nov 25 11:28:27 2007
@@ -127,7 +127,7 @@
 
                        "src", _loader.toClientURL(),
 
-                       "class", "t-invisible",
+                       "class", TapestryConstants.INVISIBLE_CLASS,
 
                        "id", loaderId);
         writer.end();

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java Sun Nov 25 11:28:27 2007
@@ -38,6 +38,8 @@
 
     private final Document _document;
 
+    private static final String CLASS_ATTRIBUTE = "class";
+
     Element(Document container, String name)
     {
         super(container);
@@ -335,6 +337,34 @@
     @Override
     Element asElement()
     {
+        return this;
+    }
+
+    /**
+     * Adds one or more CSS class names to the "class" attribute. No check
+     * for duplicates is made. Note that CSS class names are case insensitive
+     * on the client.
+     *
+     * @param className one or more CSS class names
+     * @return the element for further configuration
+     */
+    public Element addClassName(String... className)
+    {
+        String classes = getAttribute(CLASS_ATTRIBUTE);
+
+        StringBuilder builder = new StringBuilder();
+
+        if (classes != null) builder.append(classes);
+
+        for (String name : className)
+        {
+            if (builder.length() > 0) builder.append(" ");
+
+            builder.append(name);
+        }
+
+        forceAttributes(CLASS_ATTRIBUTE, builder.toString());
+
         return this;
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultValidationDecorator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultValidationDecorator.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultValidationDecorator.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/DefaultValidationDecorator.java Sun Nov 25 11:28:27 2007
@@ -38,8 +38,7 @@
      * @param iconAsset          asset for an icon that will be displayed after each field (marked with the
      *                           "t-invisible" CSS class, if the field is not in error)
      */
-    public DefaultValidationDecorator(final Environment environment, Messages validationMessages,
-                                      Asset iconAsset)
+    public DefaultValidationDecorator(final Environment environment, Messages validationMessages, Asset iconAsset)
     {
         _environment = environment;
         _validationMessages = validationMessages;
@@ -49,18 +48,15 @@
     @Override
     public void insideField(Field field)
     {
-        if (inError(field))
-            addErrorClassToCurrentElement();
+        if (inError(field)) addErrorClassToCurrentElement();
     }
 
     @Override
     public void insideLabel(Field field, Element element)
     {
-        if (field == null)
-            return;
+        if (field == null) return;
 
-        if (inError(field))
-            addErrorClass(element);
+        if (inError(field)) element.addClassName(TapestryConstants.ERROR_CLASS);
     }
 
     @Override
@@ -88,19 +84,6 @@
     {
         MarkupWriter writer = _environment.peekRequired(MarkupWriter.class);
 
-        Element element = writer.getElement();
-
-        addErrorClass(element);
+        writer.getElement().addClassName(TapestryConstants.ERROR_CLASS);
     }
-
-    private void addErrorClass(Element element)
-    {
-        String current = element.getAttribute("class");
-
-        String newValue = current == null ? InternalConstants.TAPESTRY_ERROR_CLASS : current + " "
-                + InternalConstants.TAPESTRY_ERROR_CLASS;
-
-        element.forceAttributes("class", newValue);
-    }
-
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java Sun Nov 25 11:28:27 2007
@@ -43,11 +43,6 @@
     public static final String TEMPLATE_EXTENSION = "tml";
 
     /**
-     * All purpose CSS class name for anything related to Tapestry errors.
-     */
-    public static final String TAPESTRY_ERROR_CLASS = "t-error";
-
-    /**
      * The name of the query parameter that stores the page activation context inside an action
      * request.
      */

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxComponentActionRequestHandler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxComponentActionRequestHandler.java?rev=598036&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxComponentActionRequestHandler.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxComponentActionRequestHandler.java Sun Nov 25 11:28:27 2007
@@ -0,0 +1,112 @@
+// Copyright 2007 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.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.ComponentEventHandler;
+import org.apache.tapestry.TapestryConstants;
+import org.apache.tapestry.internal.structure.ComponentPageElement;
+import org.apache.tapestry.internal.structure.Page;
+import org.apache.tapestry.internal.util.Holder;
+import org.apache.tapestry.runtime.Component;
+import org.apache.tapestry.runtime.RenderCommand;
+import org.apache.tapestry.services.ComponentActionRequestHandler;
+import org.apache.tapestry.services.MarkupWriterFactory;
+import org.apache.tapestry.services.Response;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * Similar to {@link ComponentActionRequestHandlerImpl}, but built around the Ajax request cycle, where the action request
+ * sends back an immediate JSON response containing the new content.
+ */
+public class AjaxComponentActionRequestHandler implements ComponentActionRequestHandler
+{
+    private final RequestPageCache _cache;
+
+    private final MarkupWriterFactory _factory;
+
+    private final PageMarkupRenderer _renderer;
+
+    private final Response _response;
+
+    public AjaxComponentActionRequestHandler(RequestPageCache cache, MarkupWriterFactory factory,
+                                             PageMarkupRenderer renderer, Response response)
+    {
+        _cache = cache;
+        _factory = factory;
+        _renderer = renderer;
+        _response = response;
+    }
+
+    public boolean handle(String logicalPageName, String nestedComponentId, String eventType, String[] context,
+                          String[] activationContext) throws IOException
+    {
+        final Page page = _cache.get(logicalPageName);
+
+        ComponentPageElement element = page.getComponentElementByNestedId(nestedComponentId);
+
+        final Holder<Boolean> holder = Holder.create();
+        final Holder<IOException> exceptionHolder = Holder.create();
+
+        ComponentEventHandler handler = new ComponentEventHandler()
+        {
+            @SuppressWarnings("unchecked")
+            public boolean handleResult(Object result, Component component, String methodDescription)
+            {
+                // TODO: Very limiting; event handler should be able to return a component or a StreamResponse
+                // as well.  Perhaps others.  The problem is the page. Maybe we need to store the
+                // page in a global?
+
+                if (!(result instanceof RenderCommand)) throw new IllegalArgumentException(
+                        String.format("Return type %s is not supported.", result.getClass().getName()));
+
+
+                try
+                {
+                    new AjaxResponseGenerator(page, (RenderCommand) result, _factory, _renderer).sendClientResponse(
+                            _response);
+                }
+                catch (IOException ex)
+                {
+                    exceptionHolder.put(ex);
+                }
+
+
+                holder.put(true);
+
+                return true;
+            }
+        };
+
+        page.getRootElement().triggerEvent(TapestryConstants.ACTIVATE_EVENT, activationContext, handler);
+
+        if (exceptionHolder.hasValue()) throw exceptionHolder.get();
+
+        if (holder.hasValue()) return holder.get();
+
+        element.triggerEvent(eventType, context, handler);
+
+        if (holder.hasValue()) return true;
+
+        PrintWriter pw = _response.getPrintWriter("text/javascript");
+
+        pw.print("{ }");
+
+        pw.flush();
+
+        return true;
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxFilter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxFilter.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxFilter.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxFilter.java Sun Nov 25 11:28:27 2007
@@ -14,9 +14,12 @@
 
 package org.apache.tapestry.internal.services;
 
-import org.apache.tapestry.services.ActionResponseGenerator;
+import org.apache.tapestry.services.Ajax;
 import org.apache.tapestry.services.ComponentActionRequestFilter;
 import org.apache.tapestry.services.ComponentActionRequestHandler;
+import org.apache.tapestry.services.Request;
+
+import java.io.IOException;
 
 /**
  * A filter that intercepts Ajax-oriented requests, thos that originate on the client-side using
@@ -25,16 +28,23 @@
  */
 public class AjaxFilter implements ComponentActionRequestFilter
 {
-    public ActionResponseGenerator handle(String logicalPageName, String nestedComponentId,
-                                          String eventType, String[] context, String[] activationContext,
-                                          ComponentActionRequestHandler handler)
+    private final Request _request;
+
+    private final ComponentActionRequestHandler _ajaxHandler;
+
+    public AjaxFilter(Request request, @Ajax ComponentActionRequestHandler ajaxHandler)
     {
-        return handler.handle(
-                logicalPageName,
-                nestedComponentId,
-                eventType,
-                context,
-                activationContext);
+        _request = request;
+        _ajaxHandler = ajaxHandler;
+    }
+
+
+    public boolean handle(String logicalPageName, String nestedComponentId, String eventType, String[] context,
+                          String[] activationContext, ComponentActionRequestHandler handler) throws IOException
+    {
+        ComponentActionRequestHandler next = _request.isXHR() ? _ajaxHandler : handler;
+
+        return next.handle(logicalPageName, nestedComponentId, eventType, context, activationContext);
     }
 
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxResponseGenerator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxResponseGenerator.java?rev=598036&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxResponseGenerator.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxResponseGenerator.java Sun Nov 25 11:28:27 2007
@@ -0,0 +1,78 @@
+// Copyright 2007 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.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.dom.Element;
+import org.apache.tapestry.internal.structure.Page;
+import org.apache.tapestry.internal.util.ContentType;
+import org.apache.tapestry.json.JSONObject;
+import org.apache.tapestry.runtime.RenderCommand;
+import org.apache.tapestry.services.MarkupWriterFactory;
+import org.apache.tapestry.services.Response;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class AjaxResponseGenerator
+{
+    private final Page _page;
+
+    private final RenderCommand _rootRenderCommand;
+
+    private final MarkupWriterFactory _markupWriterFactory;
+
+    private final PageMarkupRenderer _renderer;
+
+
+    public AjaxResponseGenerator(Page page, RenderCommand rootRenderCommand, MarkupWriterFactory markupWriterFactory,
+                                 PageMarkupRenderer renderer)
+    {
+        _page = page;
+        _rootRenderCommand = rootRenderCommand;
+        _markupWriterFactory = markupWriterFactory;
+        _renderer = renderer;
+    }
+
+    public void sendClientResponse(Response response) throws IOException
+    {
+        // This may be problematic as the charset of the response is not
+        // going to be set properly I think.  We'll loop back to that.
+
+        ContentType contentType = new ContentType("text/javascript");
+
+        MarkupWriter writer = _markupWriterFactory.newMarkupWriter();
+
+        // The partial will quite often contain multiple elements, so those must be enclosed in a root element.
+
+        Element root = writer.element("ajax-partial");
+
+        _renderer.renderPartialPageMarkup(_page, _rootRenderCommand, writer);
+
+        writer.end();
+
+        String content = root.getChildText().trim();
+
+        JSONObject reply = new JSONObject();
+
+        reply.put("content", content);
+
+        PrintWriter pw = response.getPrintWriter(contentType.toString());
+
+        pw.print(reply);
+
+        pw.flush();
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClassResultProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClassResultProcessor.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClassResultProcessor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClassResultProcessor.java Sun Nov 25 11:28:27 2007
@@ -1,25 +1,27 @@
-// Copyright 2007 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.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2007 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.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.internal.services;
 
 import org.apache.tapestry.Link;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.runtime.Component;
-import org.apache.tapestry.services.ActionResponseGenerator;
 import org.apache.tapestry.services.ComponentClassResolver;
 import org.apache.tapestry.services.ComponentEventResultProcessor;
+import org.apache.tapestry.services.Response;
+
+import java.io.IOException;
 
 /**
  * Used when a component event handler returns a class value. The value is interpreted as the page
@@ -29,27 +31,33 @@
  */
 public class ClassResultProcessor implements ComponentEventResultProcessor<Class>
 {
-    private ComponentClassResolver _resolver;
+    private final ComponentClassResolver _resolver;
 
     private final RequestPageCache _requestPageCache;
 
     private final LinkFactory _linkFactory;
 
+    private final Response _response;
+
     public ClassResultProcessor(ComponentClassResolver resolver, RequestPageCache requestPageCache,
-                                LinkFactory linkFactory)
+                                LinkFactory linkFactory, Response response)
     {
         _resolver = resolver;
         _requestPageCache = requestPageCache;
         _linkFactory = linkFactory;
+        _response = response;
     }
 
-    public ActionResponseGenerator processComponentEvent(Class value, Component component, String methodDescripion)
+    public void processComponentEvent(Class value, Component component, String methodDescripion) throws IOException
     {
         String className = value.getName();
         String pageName = _resolver.resolvePageClassNameToPageName(className);
+
         Page page = _requestPageCache.get(pageName);
+
         Link link = _linkFactory.createPageLink(page, false);
-        return new LinkActionResponseGenerator(link);
+
+        _response.sendRedirect(link);
     }
 
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java Sun Nov 25 11:28:27 2007
@@ -17,7 +17,10 @@
 import org.apache.tapestry.TapestryConstants;
 import org.apache.tapestry.internal.InternalConstants;
 import org.apache.tapestry.internal.TapestryInternalUtils;
-import org.apache.tapestry.services.*;
+import org.apache.tapestry.services.ComponentActionRequestHandler;
+import org.apache.tapestry.services.Dispatcher;
+import org.apache.tapestry.services.Request;
+import org.apache.tapestry.services.Response;
 
 import java.io.IOException;
 
@@ -98,27 +101,18 @@
             logicalPageName = path.substring(1, colonx);
         }
 
-        if (logicalPageName == null)
-            return false;
+        if (logicalPageName == null) return false;
 
-        String[] eventContext = contextStart > 0 ? decodeContext(path.substring(contextStart))
-                                : _emptyString;
+        String[] eventContext = contextStart > 0 ? decodeContext(path.substring(contextStart)) : _emptyString;
 
         String activationContextValue = request.getParameter(InternalConstants.PAGE_CONTEXT_NAME);
 
-        String[] activationContext = activationContextValue == null ? _emptyString
-                                     : decodeContext(activationContextValue);
+        String[] activationContext = activationContextValue == null ? _emptyString : decodeContext(
+                activationContextValue);
 
-        ActionResponseGenerator responseGenerator = _componentActionRequestHandler.handle(
-                logicalPageName,
-                nestedComponentId,
-                eventType,
-                eventContext,
-                activationContext);
+        return _componentActionRequestHandler.handle(logicalPageName, nestedComponentId, eventType, eventContext,
+                                                     activationContext);
 
-        responseGenerator.sendClientResponse(response);
-
-        return true;
     }
 
     private String[] decodeContext(String input)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionRequestHandlerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionRequestHandlerImpl.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionRequestHandlerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionRequestHandlerImpl.java Sun Nov 25 11:28:27 2007
@@ -21,9 +21,12 @@
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.internal.util.Holder;
 import org.apache.tapestry.runtime.Component;
-import org.apache.tapestry.services.ActionResponseGenerator;
 import org.apache.tapestry.services.ComponentActionRequestHandler;
 import org.apache.tapestry.services.ComponentEventResultProcessor;
+import org.apache.tapestry.services.Response;
+import org.apache.tapestry.services.Traditional;
+
+import java.io.IOException;
 
 public class ComponentActionRequestHandlerImpl implements ComponentActionRequestHandler
 {
@@ -33,16 +36,19 @@
 
     private final LinkFactory _linkFactory;
 
-    public ComponentActionRequestHandlerImpl(ComponentEventResultProcessor resultProcessor,
-                                             RequestPageCache cache, LinkFactory linkFactory)
+    private final Response _response;
+
+    public ComponentActionRequestHandlerImpl(@Traditional ComponentEventResultProcessor resultProcessor,
+                                             RequestPageCache cache, LinkFactory linkFactory, Response response)
     {
         _resultProcessor = resultProcessor;
         _cache = cache;
         _linkFactory = linkFactory;
+        _response = response;
     }
 
-    public ActionResponseGenerator handle(String logicalPageName, String nestedComponentId,
-                                          String eventType, String[] context, String[] activationContext)
+    public boolean handle(String logicalPageName, String nestedComponentId, String eventType, String[] context,
+                          String[] activationContext) throws IOException
     {
         Page page = _cache.get(logicalPageName);
 
@@ -50,19 +56,23 @@
 
         ComponentPageElement element = page.getComponentElementByNestedId(nestedComponentId);
 
-        final Holder<ActionResponseGenerator> holder = new Holder<ActionResponseGenerator>();
+        final Holder<Boolean> holder = Holder.create();
 
         ComponentEventHandler handler = new ComponentEventHandler()
         {
             @SuppressWarnings("unchecked")
             public boolean handleResult(Object result, Component component, String methodDescription)
             {
-                ActionResponseGenerator generator = _resultProcessor.processComponentEvent(
-                        result,
-                        component,
-                        methodDescription);
+                try
+                {
+                    _resultProcessor.processComponentEvent(result, component, methodDescription);
+                }
+                catch (IOException ex)
+                {
+                    throw new RuntimeException(ex);
+                }
 
-                holder.put(generator);
+                holder.put(true);
 
                 return true;
             }
@@ -71,24 +81,18 @@
         // If activating the page returns a "navigational result", then don't trigger the action
         // on the component.
 
-        page.getRootElement().triggerEvent(
-                TapestryConstants.ACTIVATE_EVENT,
-                activationContext,
-                handler);
+        page.getRootElement().triggerEvent(TapestryConstants.ACTIVATE_EVENT, activationContext, handler);
 
-        if (holder.hasValue()) return holder.get();
+        if (holder.hasValue()) return true;
 
         element.triggerEvent(eventType, context, handler);
 
-        ActionResponseGenerator result = holder.get();
+        if (holder.hasValue()) return true;
 
-        if (result == null)
-        {
-            Link link = _linkFactory.createPageLink(page, false);
+        Link link = _linkFactory.createPageLink(page, false);
 
-            result = new LinkActionResponseGenerator(link);
-        }
+        _response.sendRedirect(link);
 
-        return result;
+        return true;
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessor.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessor.java Sun Nov 25 11:28:27 2007
@@ -18,10 +18,12 @@
 import org.apache.tapestry.Link;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.runtime.Component;
-import org.apache.tapestry.services.ActionResponseGenerator;
 import org.apache.tapestry.services.ComponentEventResultProcessor;
+import org.apache.tapestry.services.Response;
 import org.slf4j.Logger;
 
+import java.io.IOException;
+
 public class ComponentInstanceResultProcessor implements ComponentEventResultProcessor<Component>
 {
     private final RequestPageCache _requestPageCache;
@@ -30,24 +32,23 @@
 
     private final Logger _logger;
 
-    public ComponentInstanceResultProcessor(final RequestPageCache requestPageCache,
-                                            LinkFactory linkFactory, Logger logger)
+    private final Response _response;
+
+    public ComponentInstanceResultProcessor(Logger logger, Response response, RequestPageCache requestPageCache,
+                                            LinkFactory linkFactory)
     {
+        _response = response;
         _requestPageCache = requestPageCache;
         _linkFactory = linkFactory;
         _logger = logger;
     }
 
-    public ActionResponseGenerator processComponentEvent(Component value, Component component,
-                                                         String methodDescription)
+    public void processComponentEvent(Component value, Component component, String methodDescription) throws IOException
     {
         ComponentResources resources = value.getComponentResources();
 
         if (resources.getContainer() != null)
-            _logger.warn(ServicesMessages.componentInstanceIsNotAPage(
-                    methodDescription,
-                    component,
-                    value));
+            _logger.warn(ServicesMessages.componentInstanceIsNotAPage(methodDescription, component, value));
 
         // We have all these layers and layers between us and the page instance, but its easy to
         // extract the page class name and quickly re-resolve that to the page instance.
@@ -56,6 +57,6 @@
 
         Link link = _linkFactory.createPageLink(page, false);
 
-        return new LinkActionResponseGenerator(link);
+        _response.sendRedirect(link);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DocumentHeadBuilderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DocumentHeadBuilderImpl.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DocumentHeadBuilderImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DocumentHeadBuilderImpl.java Sun Nov 25 11:28:27 2007
@@ -126,7 +126,7 @@
 
             // This assumes that Prototype is available.
 
-            e.text("Event.observe(window, \"load\", function() {\n");
+            e.text("Event.observe(window, 'load', function() {\n");
 
             e.text(_scriptBlock.toString());
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LocationRenderer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LocationRenderer.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LocationRenderer.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LocationRenderer.java Sun Nov 25 11:28:27 2007
@@ -15,6 +15,7 @@
 package org.apache.tapestry.internal.services;
 
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.dom.Element;
 import org.apache.tapestry.internal.TapestryInternalUtils;
 import static org.apache.tapestry.ioc.IOCConstants.PERTHREAD_SCOPE;
 import org.apache.tapestry.ioc.Location;
@@ -87,18 +88,21 @@
 
                 writer.element("tr");
 
-                writer.element("td");
-                writer.attributes("class", line == current ? "t-location-line t-location-current"
-                                           : "t-location-line");
+                writer.element("td", "class", "t-location-line");
+
+                if (line == current) writer.getElement().addClassName("t-location-current");
+
                 writer.write(Integer.toString(current));
                 writer.end();
 
                 String css = "t-location-content";
-                if (line == current) css += " t-location-current";
-                if (start == current) css += " t-location-content-first";
 
-                writer.element("td");
-                writer.attributes("class", css);
+                Element td = writer.element("td", "class", "t-location-content");
+
+                if (line == current) td.addClassName("t-location-current");
+
+                if (start == current) td.addClassName("t-location-content-first");
+
                 writer.write(input);
                 writer.end();
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ObjectComponentEventResultProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ObjectComponentEventResultProcessor.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ObjectComponentEventResultProcessor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ObjectComponentEventResultProcessor.java Sun Nov 25 11:28:27 2007
@@ -16,9 +16,9 @@
 
 import org.apache.tapestry.ioc.internal.util.TapestryException;
 import org.apache.tapestry.runtime.Component;
-import org.apache.tapestry.services.ActionResponseGenerator;
 import org.apache.tapestry.services.ComponentEventResultProcessor;
 
+import java.io.IOException;
 import java.util.Collection;
 
 /**
@@ -28,19 +28,15 @@
 {
     private final Collection<Class> _configuredClasses;
 
-    public ObjectComponentEventResultProcessor(final Collection<Class> configuredClasses)
+    public ObjectComponentEventResultProcessor(Collection<Class> configuredClasses)
     {
         _configuredClasses = configuredClasses;
     }
 
-    public ActionResponseGenerator processComponentEvent(Object value, Component component,
-                                                         String methodDescripion)
+    public void processComponentEvent(Object value, Component component, String methodDescripion) throws IOException
     {
-        String message = ServicesMessages.invalidComponentEventResult(
-                component,
-                value,
-                methodDescripion,
-                _configuredClasses);
+        String message = ServicesMessages.invalidComponentEventResult(component, value, methodDescripion,
+                                                                      _configuredClasses);
 
         throw new TapestryException(message, component, null);
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageMarkupRenderer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageMarkupRenderer.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageMarkupRenderer.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageMarkupRenderer.java Sun Nov 25 11:28:27 2007
@@ -14,11 +14,33 @@
 
 package org.apache.tapestry.internal.services;
 
-import org.apache.tapestry.MarkupWriter;
-import org.apache.tapestry.internal.structure.Page;
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.internal.structure.Page;
+import org.apache.tapestry.runtime.RenderCommand;
 
+/**
+ * Service used to render page markup using a MarkupWriter.  This is usually used when rendering a complete
+ * page as part of a {@linkplain org.apache.tapestry.internal.services.PageRenderRequestHandlerImpl page render request},
+ * but may also be used to render portions of a page as part of an {@linkplain org.apache.tapestry.internal.services.AjaxResponseGenerator Ajax request}.
+ */
 public interface PageMarkupRenderer
 {
+    /**
+     * Initializes the rendering using the
+     * {@link org.apache.tapestry.services.PageRenderInitializer} change of command.
+     *
+     * @param page   page to render
+     * @param writer receives the markup
+     */
     void renderPageMarkup(Page page, MarkupWriter writer);
+
+    /**
+     * Used to render a partial response as part of an Ajax action request.
+     *
+     * @param page              page used to perform the render
+     * @param rootRenderCommand initial object to render
+     * @param writer            writer used to perform the render
+     */
+    void renderPartialPageMarkup(Page page, RenderCommand rootRenderCommand, MarkupWriter writer);
 
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageMarkupRendererImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageMarkupRendererImpl.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageMarkupRendererImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageMarkupRendererImpl.java Sun Nov 25 11:28:27 2007
@@ -16,6 +16,7 @@
 
 import org.apache.tapestry.MarkupWriter;
 import org.apache.tapestry.internal.structure.Page;
+import org.apache.tapestry.runtime.RenderCommand;
 import org.apache.tapestry.services.PageRenderInitializer;
 
 public class PageMarkupRendererImpl implements PageMarkupRenderer
@@ -31,13 +32,7 @@
     {
         _pageRenderInitializer.setup(writer);
 
-        RenderQueueImpl queue = new RenderQueueImpl(page.getLogger());
-
-        queue.push(page.getRootElement());
-
-        // Run the queue until empty.
-
-        queue.run(writer);
+        renderPartialPageMarkup(page, page.getRootElement(), writer);
 
         _pageRenderInitializer.cleanup(writer);
 
@@ -45,4 +40,14 @@
             throw new RuntimeException(ServicesMessages.noMarkupFromPageRender(page));
     }
 
+    public void renderPartialPageMarkup(Page page, RenderCommand rootRenderCommand, MarkupWriter writer)
+    {
+        RenderQueueImpl queue = new RenderQueueImpl(page.getLogger());
+
+        queue.push(rootRenderCommand);
+
+        // Run the queue until empty.
+
+        queue.run(writer);
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java Sun Nov 25 11:28:27 2007
@@ -31,8 +31,7 @@
 
     private final PageRenderRequestHandler _handler;
 
-    public PageRenderDispatcher(ComponentClassResolver componentClassResolver,
-                                PageRenderRequestHandler handler)
+    public PageRenderDispatcher(ComponentClassResolver componentClassResolver, PageRenderRequestHandler handler)
     {
         _componentClassResolver = componentClassResolver;
         _handler = handler;
@@ -64,9 +63,7 @@
                 String[] context = atEnd ? new String[0] : convertActivationContext(path
                         .substring(nextslashx + 1));
 
-                ActionResponseGenerator responseGenerator = _handler.handle(pageName, context);
-
-                if (responseGenerator != null) responseGenerator.sendClientResponse(response);
+                _handler.handle(pageName, context);
 
                 return true;
             }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java Sun Nov 25 11:28:27 2007
@@ -19,7 +19,6 @@
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.internal.util.Holder;
 import org.apache.tapestry.runtime.Component;
-import org.apache.tapestry.services.ActionResponseGenerator;
 import org.apache.tapestry.services.ComponentEventResultProcessor;
 import org.apache.tapestry.services.PageRenderRequestHandler;
 import org.apache.tapestry.services.Response;
@@ -40,8 +39,7 @@
 
     private final Response _response;
 
-    public PageRenderRequestHandlerImpl(RequestPageCache cache,
-                                        ComponentEventResultProcessor resultProcessor,
+    public PageRenderRequestHandlerImpl(RequestPageCache cache, ComponentEventResultProcessor resultProcessor,
                                         PageResponseRenderer pageResponseRenderer, Response response)
     {
         _cache = cache;
@@ -50,23 +48,27 @@
         _response = response;
     }
 
-    public ActionResponseGenerator handle(String logicalPageName, String[] context)
+    public void handle(String logicalPageName, String[] context)
     {
         Page page = _cache.get(logicalPageName);
 
-        final Holder<ActionResponseGenerator> holder = new Holder<ActionResponseGenerator>();
+        final Holder<Boolean> holder = Holder.create();
 
         ComponentEventHandler handler = new ComponentEventHandler()
         {
             @SuppressWarnings("unchecked")
             public boolean handleResult(Object result, Component component, String methodDescription)
             {
-                ActionResponseGenerator generator = _resultProcessor.processComponentEvent(
-                        result,
-                        component,
-                        methodDescription);
+                try
+                {
+                    _resultProcessor.processComponentEvent(result, component, methodDescription);
+                }
+                catch (IOException e)
+                {
+                    throw new RuntimeException(e);
+                }
 
-                holder.put(generator);
+                holder.put(true);
 
                 return true; // abort the event
             }
@@ -74,7 +76,9 @@
 
         page.getRootElement().triggerEvent(TapestryConstants.ACTIVATE_EVENT, context, handler);
 
-        if (holder.hasValue()) return holder.get();
+        // The handler will have asked the result processor to send a response.
+
+        if (holder.hasValue()) return;
 
         try
         {
@@ -85,6 +89,5 @@
             throw new RuntimeException(ex);
         }
 
-        return null;
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java Sun Nov 25 11:28:27 2007
@@ -36,8 +36,8 @@
 
     private final MetaDataLocator _metaDataLocator;
 
-    public PageResponseRendererImpl(MarkupWriterFactory markupWriterFactory,
-                                    PageMarkupRenderer markupRenderer, MetaDataLocator metaDataLocator)
+    public PageResponseRendererImpl(MarkupWriterFactory markupWriterFactory, PageMarkupRenderer markupRenderer,
+                                    MetaDataLocator metaDataLocator)
     {
         _markupWriterFactory = markupWriterFactory;
         _markupRenderer = markupRenderer;
@@ -46,11 +46,27 @@
 
     public void renderPageResponse(Page page, Response response) throws IOException
     {
+        ContentType contentType = findResponseContentType(page);
+
+        // Eventually we'll have to do work to figure out the correct markup type, content type,
+        // whatever. Right now its defaulting to plain HTML.
+
+        MarkupWriter writer = _markupWriterFactory.newMarkupWriter();
+
+        _markupRenderer.renderPageMarkup(page, writer);
+
+        PrintWriter pw = response.getPrintWriter(contentType.toString());
+
+        writer.toMarkup(pw);
+
+        pw.flush();
+    }
+
+    private ContentType findResponseContentType(Page page)
+    {
         ComponentResources pageResources = page.getRootComponent().getComponentResources();
 
-        String contentTypeString = _metaDataLocator.findMeta(
-                TapestryConstants.RESPONSE_CONTENT_TYPE,
-                pageResources);
+        String contentTypeString = _metaDataLocator.findMeta(TapestryConstants.RESPONSE_CONTENT_TYPE, pageResources);
         ContentType contentType = new ContentType(contentTypeString);
 
         // Make sure thre's always a charset specified.
@@ -63,18 +79,7 @@
             contentType.setParameter(CHARSET, encoding);
         }
 
-        // Eventually we'll have to do work to figure out the correct markup type, content type,
-        // whatever. Right now its defaulting to plain HTML.
-
-        MarkupWriter writer = _markupWriterFactory.newMarkupWriter();
-
-        _markupRenderer.renderPageMarkup(page, writer);
-
-        PrintWriter pw = response.getPrintWriter(contentType.toString());
-
-        writer.toMarkup(pw);
-
-        pw.flush();
+        return contentType;
     }
 
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ReflectiveInstantiator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ReflectiveInstantiator.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ReflectiveInstantiator.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ReflectiveInstantiator.java Sun Nov 25 11:28:27 2007
@@ -1,17 +1,17 @@
-// Copyright 2006, 2007 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.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
+// Copyright 2006, 2007 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.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.internal.services;
 
 import org.apache.tapestry.internal.InternalComponentResources;

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RequestImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RequestImpl.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RequestImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/RequestImpl.java Sun Nov 25 11:28:27 2007
@@ -32,7 +32,7 @@
 {
     static final String REQUESTED_WITH_HEADER = "X-Requested-With";
 
-    static final String XML_HTTP_REQUEST = "XmlHttpRequest";
+    static final String XML_HTTP_REQUEST = "XMLHttpRequest";
 
     private final HttpServletRequest _request;
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResponseImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResponseImpl.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResponseImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResponseImpl.java Sun Nov 25 11:28:27 2007
@@ -14,6 +14,7 @@
 
 package org.apache.tapestry.internal.services;
 
+import org.apache.tapestry.Link;
 import org.apache.tapestry.ioc.internal.util.Defense;
 import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
 import org.apache.tapestry.services.Response;
@@ -59,6 +60,15 @@
     public void sendRedirect(String URL) throws IOException
     {
         _response.sendRedirect(URL);
+    }
+
+    public void sendRedirect(Link link) throws IOException
+    {
+        Defense.notNull(link, "link");
+
+        String redirectURL = encodeRedirectURL(link.toRedirectURI());
+
+        sendRedirect(redirectURL);
     }
 
     public OutputStream getOutputStream(String contentType) throws IOException

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StreamResponseResultProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StreamResponseResultProcessor.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StreamResponseResultProcessor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StreamResponseResultProcessor.java Sun Nov 25 11:28:27 2007
@@ -17,7 +17,6 @@
 import org.apache.tapestry.StreamResponse;
 import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.runtime.Component;
-import org.apache.tapestry.services.ActionResponseGenerator;
 import org.apache.tapestry.services.ComponentEventResultProcessor;
 import org.apache.tapestry.services.Response;
 
@@ -30,48 +29,49 @@
 {
     private static final int BUFFER_SIZE = 5000;
 
-    public ActionResponseGenerator processComponentEvent(final StreamResponse streamResponse,
-                                                         Component component, final String methodDescripion)
+    private final Response _response;
+
+    public StreamResponseResultProcessor(Response response)
+    {
+        _response = response;
+    }
+
+    public void processComponentEvent(StreamResponse streamResponse, Component component, String methodDescripion)
+            throws IOException
     {
-        return new ActionResponseGenerator()
+        OutputStream os = null;
+        InputStream is = null;
+
+        streamResponse.prepareResponse(_response);
+
+        try
         {
-            public void sendClientResponse(Response response) throws IOException
+            is = new BufferedInputStream(streamResponse.getStream());
+
+            os = _response.getOutputStream(streamResponse.getContentType());
+
+            byte[] buffer = new byte[BUFFER_SIZE];
+
+            while (true)
             {
-                OutputStream os = null;
-                InputStream is = null;
+                int length = is.read(buffer, 0, buffer.length);
+                if (length < 0) break;
 
-                streamResponse.prepareResponse(response);
-                try
-                {
-                    is = new BufferedInputStream(streamResponse.getStream());
-
-                    os = response.getOutputStream(streamResponse.getContentType());
-
-                    byte[] buffer = new byte[BUFFER_SIZE];
-
-                    while (true)
-                    {
-                        int length = is.read(buffer, 0, buffer.length);
-                        if (length < 0)
-                            break;
-
-                        os.write(buffer, 0, length);
-                    }
-
-                    os.close();
-                    os = null;
-
-                    is.close();
-                    is = null;
-                }
-                finally
-                {
-                    TapestryInternalUtils.close(is);
-                    TapestryInternalUtils.close(os);
-                }
+                os.write(buffer, 0, length);
             }
 
-        };
+            os.close();
+            os = null;
+
+            is.close();
+            is = null;
+        }
+        finally
+        {
+            TapestryInternalUtils.close(is);
+            TapestryInternalUtils.close(os);
+        }
+
     }
 
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StringResultProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StringResultProcessor.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StringResultProcessor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StringResultProcessor.java Sun Nov 25 11:28:27 2007
@@ -17,14 +17,14 @@
 import org.apache.tapestry.Link;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.runtime.Component;
-import org.apache.tapestry.services.ActionResponseGenerator;
 import org.apache.tapestry.services.ComponentEventResultProcessor;
+import org.apache.tapestry.services.Response;
+
+import java.io.IOException;
 
 /**
  * Used when a component event handler returns a string value. The value is interpreted as the
- * logical name of a page. A link to the page will be sent.
- *
- * @see LinkActionResponseGenerator
+ * logical name of a page. A link to the page will be sent as a redirect.
  */
 public class StringResultProcessor implements ComponentEventResultProcessor<String>
 {
@@ -32,20 +32,22 @@
 
     private final LinkFactory _linkFactory;
 
-    public StringResultProcessor(RequestPageCache requestPageCache, LinkFactory linkFactory)
+    private final Response _response;
+
+    public StringResultProcessor(RequestPageCache requestPageCache, LinkFactory linkFactory, Response response)
     {
         _requestPageCache = requestPageCache;
         _linkFactory = linkFactory;
+        _response = response;
     }
 
-    public ActionResponseGenerator processComponentEvent(String value, Component component,
-                                                         String methodDescripion)
+    public void processComponentEvent(String value, Component component, String methodDescripion) throws IOException
     {
         Page page = _requestPageCache.get(value);
 
         Link link = _linkFactory.createPageLink(page, false);
 
-        return new LinkActionResponseGenerator(link);
+        _response.sendRedirect(link);
     }
 
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/ActionLinkInvoker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/ActionLinkInvoker.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/ActionLinkInvoker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/ActionLinkInvoker.java Sun Nov 25 11:28:27 2007
@@ -16,10 +16,12 @@
 
 import org.apache.tapestry.Link;
 import org.apache.tapestry.dom.Document;
-import org.apache.tapestry.internal.services.*;
+import org.apache.tapestry.internal.services.ActionLinkTarget;
+import org.apache.tapestry.internal.services.ComponentInvocation;
+import org.apache.tapestry.internal.services.ComponentInvocationMap;
+import org.apache.tapestry.internal.services.InvocationTarget;
 import org.apache.tapestry.ioc.Registry;
 import org.apache.tapestry.ioc.internal.util.Defense;
-import org.apache.tapestry.services.ActionResponseGenerator;
 import org.apache.tapestry.services.ComponentActionRequestHandler;
 
 /**
@@ -35,6 +37,8 @@
 
     private final ComponentInvocationMap _componentInvocationMap;
 
+    private final TestableResponse _response;
+
     public ActionLinkInvoker(Registry registry, ComponentInvoker followupInvoker,
                              ComponentInvocationMap componentInvocationMap)
     {
@@ -42,6 +46,9 @@
         _followupInvoker = followupInvoker;
         _componentActionRequestHandler = _registry.getService("ComponentActionRequestHandler",
                                                               ComponentActionRequestHandler.class);
+
+        _response = _registry.getObject(TestableResponse.class, null);
+
         _componentInvocationMap = componentInvocationMap;
 
     }
@@ -55,42 +62,35 @@
      */
     public Document invoke(ComponentInvocation invocation)
     {
-        ActionResponseGenerator generator = click(invocation);
+        click(invocation);
 
-        if (generator instanceof LinkActionResponseGenerator)
-        {
-            LinkActionResponseGenerator linkGenerator = (LinkActionResponseGenerator) generator;
+        Link link = _response.getRedirectLink();
 
-            Link link = linkGenerator.getLink();
+        _response.clear();
 
-            ComponentInvocation followup = _componentInvocationMap.get(link);
+        if (link == null) throw new RuntimeException("Action did not set a redirect link.");
 
-            return _followupInvoker.invoke(followup);
-        }
 
-        String message = String
-                .format(
-                        "ActionResponseGenerator %s is an instance of class %s, which is not compatible with PageTester.",
-                        generator,
-                        generator.getClass());
+        ComponentInvocation followup = _componentInvocationMap.get(link);
 
-        throw new RuntimeException(message);
+        return _followupInvoker.invoke(followup);
     }
 
-    private ActionResponseGenerator click(ComponentInvocation invocation)
+    private void click(ComponentInvocation invocation)
     {
         try
         {
             InvocationTarget target = invocation.getTarget();
 
-            ActionLinkTarget actionLinkTarget = Defense.cast(
-                    target,
-                    ActionLinkTarget.class,
-                    "target");
+            ActionLinkTarget actionLinkTarget = Defense.cast(target, ActionLinkTarget.class, "target");
 
-            return _componentActionRequestHandler.handle(actionLinkTarget.getPageName(), actionLinkTarget
+            _componentActionRequestHandler.handle(actionLinkTarget.getPageName(), actionLinkTarget
                     .getComponentNestedId(), actionLinkTarget.getEventType(), invocation
                     .getContext(), invocation.getActivationContext());
+        }
+        catch (java.io.IOException e)
+        {
+            throw new RuntimeException(e);
         }
         finally
         {

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/PageTesterModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/PageTesterModule.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/PageTesterModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/PageTesterModule.java Sun Nov 25 11:28:27 2007
@@ -37,16 +37,16 @@
     public static void bind(ServiceBinder binder)
     {
         binder.bind(TestableRequest.class, TestableRequestImpl.class);
+        binder.bind(TestableResponse.class, TestableResponseImpl.class);
         binder.bind(TestableMarkupWriterFactory.class, TestableMarkupWriterFactoryImpl.class);
     }
 
-    public static void contributeAlias(Configuration<AliasContribution> configuration,
-                                       ObjectLocator locator)
+    public static void contributeAlias(Configuration<AliasContribution> configuration, ObjectLocator locator)
     {
         add(configuration, ComponentInvocationMap.class, new PageTesterComponentInvocationMap());
-        add(configuration, Response.class, new TestableResponseImpl());
 
         add(configuration, locator, Request.class, "TestableRequest");
+        add(configuration, locator, Response.class, "TestableResponse");
         add(configuration, locator, MarkupWriterFactory.class, "TestableMarkupWriterFactory");
 
         TestableCookieSinkSource cookies = new TestableCookieSinkSource();
@@ -55,21 +55,17 @@
         add(configuration, CookieSource.class, cookies);
     }
 
-    private static <T> void add(Configuration<AliasContribution> configuration,
-                                ObjectLocator locator, Class<T> serviceClass, String serviceId)
+    private static <T> void add(Configuration<AliasContribution> configuration, ObjectLocator locator,
+                                Class<T> serviceClass, String serviceId)
     {
         T service = locator.getService(serviceId, serviceClass);
 
         add(configuration, serviceClass, service);
     }
 
-    private static <T> void add(Configuration<AliasContribution> configuration,
-                                Class<T> serviceClass, T service)
+    private static <T> void add(Configuration<AliasContribution> configuration, Class<T> serviceClass, T service)
     {
-        AliasContribution<T> contribution = AliasContribution.create(
-                serviceClass,
-                TEST_MODE,
-                service);
+        AliasContribution<T> contribution = AliasContribution.create(serviceClass, TEST_MODE, service);
 
         configuration.add(contribution);
     }

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableResponse.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableResponse.java?rev=598036&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableResponse.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableResponse.java Sun Nov 25 11:28:27 2007
@@ -0,0 +1,31 @@
+// Copyright 2007 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.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.test;
+
+import org.apache.tapestry.Link;
+import org.apache.tapestry.services.Response;
+
+public interface TestableResponse extends Response
+{
+    /**
+     * Returns the link redirected to via {@link org.apache.tapestry.services.Response#sendRedirect(org.apache.tapestry.Link)}.
+     */
+    Link getRedirectLink();
+
+    /**
+     * Clears internal state, in preparation for the next test.
+     */
+    void clear();
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableResponseImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableResponseImpl.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableResponseImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableResponseImpl.java Sun Nov 25 11:28:27 2007
@@ -14,21 +14,20 @@
 
 package org.apache.tapestry.internal.test;
 
-import org.apache.tapestry.services.Response;
+import org.apache.tapestry.Link;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
 
-public class TestableResponseImpl implements Response
+public class TestableResponseImpl implements TestableResponse
 {
+    private Link _link;
 
     private void nyi(String methodName)
     {
-        throw new RuntimeException(String.format(
-                "TestableResponse: Method %s() not yet implemented.",
-                methodName));
+        throw new RuntimeException(String.format("TestableResponse: Method %s() not yet implemented.", methodName));
     }
 
     public OutputStream getOutputStream(String contentType) throws IOException
@@ -75,6 +74,11 @@
         nyi("setIntHeader");
     }
 
+    public void sendRedirect(Link link) throws IOException
+    {
+        _link = link;
+    }
+
     public String encodeRedirectURL(String URL)
     {
         return URL;
@@ -85,4 +89,13 @@
         return URL;
     }
 
+    public Link getRedirectLink()
+    {
+        return _link;
+    }
+
+    public void clear()
+    {
+        _link = null;
+    }
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Ajax.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Ajax.java?rev=598036&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Ajax.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Ajax.java Sun Nov 25 11:28:27 2007
@@ -0,0 +1,31 @@
+// Copyright 2007 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.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.services;
+
+import java.lang.annotation.*;
+
+
+/**
+ * Marker annotation for services related to processing an Ajax request (rather than
+ * a {@linkplain org.apache.tapestry.services.Traditional traditional request}).
+ *
+ * @see org.apache.tapestry.services.ComponentActionRequestHandler
+ */
+@Target({ElementType.PARAMETER, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Ajax
+{
+}