You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2007/11/25 20:28:32 UTC

svn commit: r598036 [2/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...

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentActionRequestFilter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentActionRequestFilter.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentActionRequestFilter.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentActionRequestFilter.java Sun Nov 25 11:28:27 2007
@@ -14,6 +14,8 @@
 
 package org.apache.tapestry.services;
 
+import java.io.IOException;
+
 /**
  * Filter interface for {@link ComponentActionRequestHandler}.
  */
@@ -29,8 +31,8 @@
      * @param context           context information to provide to the event handler
      * @param activationContext activation context for the page
      * @param handler           to delegate to
+     * @return true if the request has been handled (and a response sent to the client), false otherwise
      */
-    ActionResponseGenerator handle(String logicalPageName, String nestedComponentId,
-                                   String eventType, String[] context, String[] activationContext,
-                                   ComponentActionRequestHandler handler);
+    boolean handle(String logicalPageName, String nestedComponentId, String eventType, String[] context,
+                   String[] activationContext, ComponentActionRequestHandler handler) throws IOException;
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentActionRequestHandler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentActionRequestHandler.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentActionRequestHandler.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentActionRequestHandler.java Sun Nov 25 11:28:27 2007
@@ -17,6 +17,8 @@
 import org.apache.tapestry.corelib.components.ActionLink;
 import org.apache.tapestry.corelib.components.Form;
 
+import java.io.IOException;
+
 /**
  * Handler interface for action requests. Action requests <em>do things</em> such as process a
  * form submission or otherwise change state. In the majority of cases, after the action, a redirect
@@ -29,16 +31,17 @@
 public interface ComponentActionRequestHandler
 {
     /**
-     * Handler for a component action request, which returns a response generator used to send the
-     * final response to the client.
+     * Handler for a component action request which will trigger an event on a component and use
+     * the return value to send a response to the client (typically, a redirect to a page render URL).
      *
      * @param logicalPageName   the page name containing the component, and the default component to render the
      *                          response
      * @param nestedComponentId the id of the component within the page
      * @param eventType         the type of event to trigger on the component
      * @param context           context information to provide to the event handler
-     * @parram activationContext activation context for the page
+     * @param activationContext activation context for the page
+     * @return true if the request has been handled (and a response sent to the client), false otherwise
      */
-    ActionResponseGenerator handle(String logicalPageName, String nestedComponentId,
-                                   String eventType, String[] context, String[] activationContext);
+    boolean handle(String logicalPageName, String nestedComponentId, String eventType, String[] context,
+                   String[] activationContext) throws IOException;
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentEventResultProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentEventResultProcessor.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentEventResultProcessor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ComponentEventResultProcessor.java Sun Nov 25 11:28:27 2007
@@ -16,6 +16,8 @@
 
 import org.apache.tapestry.runtime.Component;
 
+import java.io.IOException;
+
 /**
  * Responsible for handling the return value provided by a component event handler.
  *
@@ -24,15 +26,13 @@
 public interface ComponentEventResultProcessor<T>
 {
     /**
-     * For a given, non-null return value, provide a corresponding Link object (which will
-     * ultimately be transformed into a URL and sent to the client as a redirect).
+     * For a given, non-null return value from a component event method, construct and send a response.
      *
      * @param value            the value returned from a method
      * @param component        the component on which a method was invoked
      * @param methodDescripion a description of method which provided the value
      * @return an object that can send the request to the client
-     * @throws RuntimeException if the value can not be converted into a link
+     * @throws RuntimeException if the value can not be converted into a response
      */
-    ActionResponseGenerator processComponentEvent(T value, Component component,
-                                                  String methodDescripion);
+    void processComponentEvent(T value, Component component, String methodDescripion) throws IOException;
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestFilter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestFilter.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestFilter.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestFilter.java Sun Nov 25 11:28:27 2007
@@ -27,8 +27,6 @@
      * @param logicalPageName the logical name of the page to activate and render
      * @param context         context data, supplied by the page at render time, extracted from the render URL
      * @param handler         to delegate the invocation to
-     * @return an action response generator, or null if the page simply rendered
      */
-    ActionResponseGenerator handle(String logicalPageName, String[] context,
-                                   PageRenderRequestHandler handler);
+    void handle(String logicalPageName, String[] context, PageRenderRequestHandler handler);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestHandler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestHandler.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestHandler.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestHandler.java Sun Nov 25 11:28:27 2007
@@ -22,12 +22,12 @@
 public interface PageRenderRequestHandler
 {
     /**
-     * Invoked to activate and render a page. The return value of the event handler method(s) for
-     * the activate event may result in an action response generator being returned.
+     * Invoked to activate and render a page. In certain cases, based on values returned when
+     * activating the page, a {@link org.apache.tapestry.services.ComponentEventResultProcessor} may be used
+     * to send an alternate response (typically, a redirect).
      *
      * @param logicalPageName the logical name of the page to activate and render
      * @param context         context data, supplied by the page at render time, extracted from the render URL
-     * @return an action response generator, or null if the page simply rendered
      */
-    ActionResponseGenerator handle(String logicalPageName, String[] context);
+    void handle(String logicalPageName, String[] context);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Response.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Response.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Response.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Response.java Sun Nov 25 11:28:27 2007
@@ -14,6 +14,8 @@
 
 package org.apache.tapestry.services;
 
+import org.apache.tapestry.Link;
+
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
@@ -48,6 +50,13 @@
      * @see #encodeRedirectURL(String)
      */
     void sendRedirect(String URL) throws IOException;
+
+    /**
+     * Sends a redirect to a link.
+     *
+     * @param link link to redirect to.
+     */
+    void sendRedirect(Link link) throws IOException;
 
     /**
      * Sends an error response to the client using the specified status. The server defaults to

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java Sun Nov 25 11:28:27 2007
@@ -34,6 +34,7 @@
 import org.apache.tapestry.ioc.*;
 import static org.apache.tapestry.ioc.IOCConstants.PERTHREAD_SCOPE;
 import org.apache.tapestry.ioc.annotations.*;
+import org.apache.tapestry.ioc.internal.util.CollectionFactory;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newCaseInsensitiveMap;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.ioc.services.*;
@@ -107,6 +108,8 @@
         binder.bind(ResourceStreamer.class, ResourceStreamerImpl.class);
         binder.bind(ClientPersistentFieldStorage.class, ClientPersistentFieldStorageImpl.class);
         binder.bind(RequestEncodingInitializer.class, RequestEncodingInitializerImpl.class);
+        binder.bind(ComponentEventResultProcessor.class, ComponentInstanceResultProcessor.class).withId(
+                "ComponentInstanceResultProcessor");
     }
 
     public static Alias build(Logger logger,
@@ -495,8 +498,20 @@
      * terminates the pipeline by returning false. Generally, most filters should be ordered after
      * this filter.
      */
-    public static void contributeRequestHandler(OrderedConfiguration<RequestFilter> configuration, Context context,
-                                                final RequestExceptionHandler exceptionHandler)
+    public void contributeRequestHandler(OrderedConfiguration<RequestFilter> configuration, Context context,
+
+                                         final RequestExceptionHandler exceptionHandler,
+
+                                         RequestGlobals requestGlobals,
+
+                                         // @Inject not needed because its a long, not a String
+                                         @Symbol("tapestry.file-check-interval")
+                                         long checkInterval,
+
+                                         @Symbol("tapestry.file-check-update-timeout")
+                                         long updateTimeout,
+
+                                         LocalizationSetter localizationSetter)
     {
         RequestFilter staticFilesFilter = new StaticFilesFilter(context);
 
@@ -528,8 +543,14 @@
         };
 
         configuration.add("ErrorFilter", errorFilter);
+
+        configuration.add("CheckForUpdates",
+                          new CheckForUpdatesFilter(_updateListenerHub, checkInterval, updateTimeout), "before:*");
+
+        configuration.add("Localization", new LocalizationFilter(localizationSetter));
     }
 
+
     /**
      * Contributes the basic set of default translators:
      * <ul>
@@ -724,6 +745,8 @@
 
     private final Request _request;
 
+    private final Response _response;
+
     private final ThreadLocale _threadLocale;
 
     private final RequestGlobals _requestGlobals;
@@ -758,6 +781,8 @@
 
                           Request request,
 
+                          Response response,
+
                           ThreadLocale threadLocale)
     {
         _pipelineBuilder = pipelineBuilder;
@@ -777,6 +802,7 @@
         _threadCleanupHub = threadCleanupHub;
         _componentTemplateSource = componentTemplateSource;
         _request = request;
+        _response = response;
         _threadLocale = threadLocale;
     }
 
@@ -964,13 +990,15 @@
                                       ServletApplicationInitializerFilter.class, configuration, terminator);
     }
 
-    @Marker(Primary.class)
-    public ComponentEventResultProcessor build(Map<Class, ComponentEventResultProcessor> configuration)
+    @Marker({Primary.class, Traditional.class})
+    public ComponentEventResultProcessor buildComponentEventResultProcessor(
+            Map<Class, ComponentEventResultProcessor> configuration)
     {
+        Set<Class> handledTypes = CollectionFactory.newSet(configuration.keySet());
+
         // A slight hack!
 
-        configuration.put(Object.class, new ObjectComponentEventResultProcessor(configuration
-                .keySet()));
+        configuration.put(Object.class, new ObjectComponentEventResultProcessor(handledTypes));
 
         StrategyRegistry<ComponentEventResultProcessor> registry = StrategyRegistry.newInstance(
                 ComponentEventResultProcessor.class, configuration);
@@ -1038,10 +1066,6 @@
         return _shadowBuilder.build(_componentInstantiatorSource, "classFactory", ClassFactory.class);
     }
 
-    public ComponentEventResultProcessor buildComponentInstanceResultProcessor(Logger logger)
-    {
-        return new ComponentInstanceResultProcessor(_requestPageCache, _linkFactory, logger);
-    }
 
     /**
      * Ordered contributions to the MasterDispatcher service allow different URL matching strategies
@@ -1104,10 +1128,6 @@
      * <dl>
      * <dt>Object</dt>
      * <dd>Failure case, added to provide a more useful exception message</dd>
-     * <dt>ActionResponseGenerator</dt>
-     * <dd>Returns the ActionResponseGenerator; this sometimes occurs when a component generates
-     * events whose return values are converted to ActionResponseGenerators (this handles that
-     * bubble up case).</dd>
      * <dt>Link</dt>
      * <dd>Wraps the Link to send a redirect</dd>
      * <dt>String</dt>
@@ -1123,33 +1143,26 @@
 
             MappedConfiguration<Class, ComponentEventResultProcessor> configuration)
     {
-        configuration.add(ActionResponseGenerator.class, new ComponentEventResultProcessor<ActionResponseGenerator>()
-        {
-            public ActionResponseGenerator processComponentEvent(ActionResponseGenerator value, Component component,
-                                                                 String methodDescripion)
-            {
-                return value;
-            }
-        });
+
 
         configuration.add(Link.class, new ComponentEventResultProcessor<Link>()
         {
 
-            public ActionResponseGenerator processComponentEvent(Link value, Component component,
-                                                                 String methodDescripion)
+            public void processComponentEvent(Link value, Component component, String methodDescripion)
+                    throws IOException
             {
-                return new LinkActionResponseGenerator(value);
+                _response.sendRedirect(value);
             }
         });
 
-        configuration.add(String.class, new StringResultProcessor(_requestPageCache, _linkFactory));
+        configuration.add(String.class, new StringResultProcessor(_requestPageCache, _linkFactory, _response));
 
         configuration.add(Class.class,
-                          new ClassResultProcessor(componentClassResolver, _requestPageCache, _linkFactory));
+                          new ClassResultProcessor(componentClassResolver, _requestPageCache, _linkFactory, _response));
 
         configuration.add(Component.class, componentInstanceProcessor);
 
-        configuration.add(StreamResponse.class, new StreamResponseResultProcessor());
+        configuration.add(StreamResponse.class, new StreamResponseResultProcessor(_response));
     }
 
     public void contributeMasterDispatcher(OrderedConfiguration<Dispatcher> configuration,
@@ -1162,7 +1175,7 @@
 
                                            PageRenderRequestHandler pageRenderRequestHandler,
 
-                                           ComponentActionRequestHandler componentActionRequestHandler,
+                                           @Traditional ComponentActionRequestHandler componentActionRequestHandler,
 
                                            ComponentClassResolver componentClassResolver,
 
@@ -1284,6 +1297,7 @@
 
                                                                           "${tapestry.scriptaculous}/prototype.js",
                                                                           "${tapestry.scriptaculous}/scriptaculous.js",
+                                                                          "${tapestry.scriptaculous}/effects.js",
                                                                           "org/apache/tapestry/tapestry.js");
 
                 support.addStylesheetLink(stylesheetAsset, null);
@@ -1373,6 +1387,13 @@
                                       configuration, resources.autobuild(PageRenderRequestHandlerImpl.class));
     }
 
+    /**
+     * Builds the component action request handler for traditional (non-Ajax) requests. These typically
+     * result in a redirect to a Tapestry render URL.
+     *
+     * @see org.apache.tapestry.internal.services.ComponentActionRequestHandlerImpl
+     */
+    @Marker(Traditional.class)
     public ComponentActionRequestHandler buildComponentActionRequestHandler(
             List<ComponentActionRequestFilter> configuration, Logger logger, ServiceResources resources)
     {
@@ -1381,6 +1402,19 @@
     }
 
     /**
+     * Builds the action request handler for Ajax requests, based on
+     * {@link org.apache.tapestry.internal.services.AjaxComponentActionRequestHandler}.  Filters on
+     * the request handler are supported here as well.
+     */
+    @Marker(Ajax.class)
+    public ComponentActionRequestHandler buildAjaxComponentActionRequestHandler(
+            List<ComponentActionRequestFilter> configuration, Logger logger, ServiceResources resources)
+    {
+        return _pipelineBuilder.build(logger, ComponentActionRequestHandler.class, ComponentActionRequestFilter.class,
+                                      configuration, resources.autobuild(AjaxComponentActionRequestHandler.class));
+    }
+
+    /**
      * Configures the extensions that will require a digest to be downloaded via the asset
      * dispatcher. Most resources are "safe", they don't require a digest. For unsafe resources, the
      * digest is incorporated into the URL to ensure that the client side isn't just "fishing".
@@ -1442,7 +1476,8 @@
         // This is designed to make it easy to keep synchronized with script.aculo.ous. As we
         // support a new version, we create a new folder, and update the path entry. We can then
         // delete the old version folder (or keep it around). This should be more manageable than
-        // overwriting the local copy with updates. There's also a ClasspathAliasManager
+        // overwriting the local copy with updates (it's too easy for files deleted between scriptaculous
+        // releases to be accidentally left lying around). There's also a ClasspathAliasManager
         // contribution based on the path.
 
         configuration.add("tapestry.scriptaculous", "classpath:${tapestry.scriptaculous.path}");
@@ -1609,7 +1644,12 @@
 
     /**
      * Adds content types for "css" and "js" file extensions.
+     * <dl>
+     * <dt>css</dt> <dd>test/css</dd>
+     * <dt>js</dt> <dd>text/javascript</dd>
+     * </dl>
      */
+    @SuppressWarnings({"JavaDoc"})
     public void contributeResourceStreamer(MappedConfiguration<String, String> configuration)
     {
         configuration.add("css", "text/css");
@@ -1789,26 +1829,6 @@
         configuration.add("StringLiteral", stringFactory);
     }
 
-    /**
-     * Adds a filter that checks for updates to classes and other resources. It is ordered before:*.
-     */
-    public void contributeRequestHandler(OrderedConfiguration<RequestFilter> configuration,
-                                         RequestGlobals requestGlobals,
-
-                                         // @Inject not needed because its a long, not a String
-                                         @Symbol("tapestry.file-check-interval")
-                                         long checkInterval,
-
-                                         @Symbol("tapestry.file-check-update-timeout")
-                                         long updateTimeout,
-
-                                         LocalizationSetter localizationSetter)
-    {
-        configuration.add("CheckForUpdates",
-                          new CheckForUpdatesFilter(_updateListenerHub, checkInterval, updateTimeout), "before:*");
-
-        configuration.add("Localization", new LocalizationFilter(localizationSetter));
-    }
 
     public PersistentFieldStrategy buildClientPersistentFieldStrategy(LinkFactory linkFactory,
                                                                       ServiceResources resources)
@@ -1821,15 +1841,14 @@
         return service;
     }
 
-    public static void contributeComponentActionRequestHandler(
+    public void contributeComponentActionRequestHandler(
             OrderedConfiguration<ComponentActionRequestFilter> configuration,
-            final RequestEncodingInitializer encodingInitializer)
+            final RequestEncodingInitializer encodingInitializer, @Ajax ComponentActionRequestHandler ajaxHandler)
     {
-        ComponentActionRequestFilter filter = new ComponentActionRequestFilter()
+        ComponentActionRequestFilter requestEncodingFilter = new ComponentActionRequestFilter()
         {
-            public ActionResponseGenerator handle(String logicalPageName, String nestedComponentId, String eventType,
-                                                  String[] context, String[] activationContext,
-                                                  ComponentActionRequestHandler handler)
+            public boolean handle(String logicalPageName, String nestedComponentId, String eventType, String[] context,
+                                  String[] activationContext, ComponentActionRequestHandler handler) throws IOException
             {
                 encodingInitializer.initializeRequestEncoding(logicalPageName);
 
@@ -1838,8 +1857,8 @@
 
         };
 
-        configuration.add("SetRequestEncoding", filter, "before:*");
+        configuration.add("SetRequestEncoding", requestEncodingFilter, "before:*");
 
-        configuration.add("Ajax", new AjaxFilter());
+        configuration.add("Ajax", new AjaxFilter(_request, ajaxHandler));
     }
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Traditional.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Traditional.java?rev=598036&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Traditional.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Traditional.java Sun Nov 25 11:28:27 2007
@@ -0,0 +1,30 @@
+// 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 a service that should be used for traditional (non-Ajax) requests.
+ *
+ * @see org.apache.tapestry.services.ComponentActionRequestHandler
+ */
+@Target({ElementType.PARAMETER, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Traditional
+{
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/scriptaculous_1_8/scriptaculous.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/scriptaculous_1_8/scriptaculous.js?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/scriptaculous_1_8/scriptaculous.js (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/scriptaculous_1_8/scriptaculous.js Sun Nov 25 11:28:27 2007
@@ -39,27 +39,23 @@
             return parseInt(r[0]) * 100000 + parseInt(r[1]) * 1000 + parseInt(r[2]);
         }
 
-        if ((typeof Prototype == 'undefined') ||
-            (typeof Element == 'undefined') ||
-            (typeof Element.Methods == 'undefined') ||
-            (convertVersionString(Prototype.Version) <
-             convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
-            throw("script.aculo.us requires the Prototype JavaScript framework >= " +
-                  Scriptaculous.REQUIRED_PROTOTYPE);
+        if ((typeof Prototype == 'undefined') || (typeof Element == 'undefined') || (typeof Element.Methods == 'undefined') || (convertVersionString(Prototype.Version) < convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+            throw("script.aculo.us requires the Prototype JavaScript framework >= " + Scriptaculous.REQUIRED_PROTOTYPE);
 
-        $A(document.getElementsByTagName("script")).findAll(function(s)
-        {
-            return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
-        }).each(function(s)
-        {
-            var path = s.src.replace(/scriptaculous\.js(\?.*)?$/, '');
-            var includes = s.src.match(/\?.*load=([a-z,]*)/);
-            (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
-                    function(include)
-                    {
-                        Scriptaculous.require(path + include + '.js')
-                    });
-        });
+// Tapestry turns off this mechanism, and replaces it with PageRenderSupport.addScriptLink().        
+        //        $A(document.getElementsByTagName("script")).findAll(function(s)
+        //        {
+        //            return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+        //        }).each(function(s)
+        //        {
+        //            var path = s.src.replace(/scriptaculous\.js(\?.*)?$/, '');
+        //            var includes = s.src.match(/\?.*load=([a-z,]*)/);
+        //            (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+        //                    function(include)
+        //                    {
+        //                        Scriptaculous.require(path + include + '.js')
+        //                    });
+        //        });
     }
 }
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/tapestry.js Sun Nov 25 11:28:27 2007
@@ -131,6 +131,34 @@
         });
     },
 
+    // Convert a link into a trigger of an Ajax update that
+    // updates the indicated zone.
+
+    linkZone : function(link, zone)
+    {
+        link = $(link);
+        zone = $(zone);
+
+        var clickHandler = function(event)
+        {
+            var successHandler = function(transport)
+            {
+                var response = transport.responseText;
+                var reply = eval("(" + response + ")");
+
+                zone.innerHTML = reply.content;
+
+                zone.show();
+            };
+
+            var request = new Ajax.Request(link.href, { onSuccess : successHandler });
+
+            return false;
+        };
+
+        link.onclick = clickHandler;
+    },
+
 
 
     FormEvent : Class.create(),
@@ -361,7 +389,7 @@
     }
 };
 
-Event.observe(window, "load", function()
+Event.observe(window, 'load', function()
 {
     $$(".t-invisible").each(function(element)
     {

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/ajax.apt Sun Nov 25 11:28:27 2007
@@ -16,6 +16,22 @@
   Ajax support takes the form of new components and, occasionally,
   {{{mixins.html}component mixins}}.  
 
+Changes to Scriptaculous
+
+  Scriptaculous normally has a special {{{http://wiki.script.aculo.us/scriptaculous/show/Usage}script loading option}}.
+  Loading just the Scriptaculous main library, scriptaculous.js, will also load <all> the other scripts in the library. Normally,
+  you can fine-tune this using "load" query parameter.
+
+  This doesn't fit well with the Tapestry; as discussed below, Tapestry has the capability to allow
+  individual components to control which JavaScript libraries are loaded with the page.  Further, the exact set of scripts
+  needed is determined over the course of rendering the page, and depends on the needs of the specific components that have
+  rendered.
+
+  The main Scriptaculous library, scriptaculous.js, is modified to turn off the autoloading behavior.
+  Tapestry will automatically link in prototype.js, scriptaculous.js, effects.js and the Tapestry library, tapestry.js.
+  You can add additional libraries as needed.
+
+
 Basic JavaScript
 
   The general strategy in Tapestry is that any significant amount of JavaScript should be packaged up
@@ -42,8 +58,36 @@
   ignored.  In this way, each component can add the assets it needs, without worrying about conflicts
   with other components.
 
-  Note that the Prototype, Scriptaculous and the base Tapestry library (which largely consists of
+  Note that the Prototype, Scriptaculous main and effects libraries, and the base Tapestry library (which largely consists of
   support for form input validation) are included automatically.
+
+  If you are need access to other Scriptaculous libraries, you can provide them as follows:
+
++---+
+
+  @Inject @Path("${tapestry.scriptaculous}/dragdrop.js")
+  private Asset _dragDropLibrary;
+
+  @Environmental
+  private PageRenderSupport _pageRenderSupport;
+
+  void setupRender()
+  {
+    _pageRenderSupport.addScriptLink(_dragDropLibrary);
+  }
+
++---+
+
+  The Asset is injected, using the ${tapestry.scriptaculous} symbol to reference the location
+  of the Scriptaculous library.
+
+  The PageRenderSupport is accessed as an Environmental service.
+
+  The setupRender() method (the name is specifically linked to a
+  {{{rendering.html}render phase}}) is the correct place to inform the PageRenderSupport service that
+  the library is needed.
+
+  
 
 * addScript()
 

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneDemo.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneDemo.tml?rev=598036&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneDemo.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/ZoneDemo.tml Sun Nov 25 11:28:27 2007
@@ -0,0 +1,22 @@
+<html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+    <h1>Zone/Ajax Demo</h1>
+
+
+    <t:zone t:id="output" style="float:right;">
+        No name has been selected.
+
+        <t:block id="showName">
+            Selected: ${name}
+        </t:block>
+
+    </t:zone>
+
+
+    <ul>
+        <li t:type="loop" source="names" value="name">
+            <t:actionlink t:id="select" context="name" zone="output">Select "${name}"</t:actionlink>
+        </li>
+    </ul>
+
+
+</html>
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/dom/DOMTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/dom/DOMTest.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/dom/DOMTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/dom/DOMTest.java Sun Nov 25 11:28:27 2007
@@ -288,9 +288,7 @@
         root.elementAt(1, "one").element("tiny");
         root.elementAt(2, "two").element("bubbles");
 
-        assertEquals(
-                d.toString(),
-                "<fred><start/><one><tiny/></one><two><bubbles/></two><end/></fred>");
+        assertEquals(d.toString(), "<fred><start/><one><tiny/></one><two><bubbles/></two><end/></fred>");
     }
 
     @Test
@@ -363,8 +361,22 @@
         root.attribute("alpha-only", "abcdef");
         root.attribute("entities", "\"<>&");
 
-        assertEquals(
-                root.toString(),
-                "<prime alpha-only=\"abcdef\" entities=\"&quot;&lt;&gt;&amp;\"/>");
+        assertEquals(root.toString(), "<prime alpha-only=\"abcdef\" entities=\"&quot;&lt;&gt;&amp;\"/>");
+    }
+
+    @Test
+    public void add_class_names()
+    {
+        Document d = new Document(new XMLMarkupModel());
+
+        Element root = d.newRootElement("div");
+
+        assertSame(root.addClassName("fred"), root);
+
+        assertEquals(root.toString(), "<div class=\"fred\"/>");
+
+        assertSame(root.addClassName("barney", "wilma"), root);
+
+        assertEquals(root.toString(), "<div class=\"fred barney wilma\"/>");
     }
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/ZoneDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/ZoneDemo.java?rev=598036&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/ZoneDemo.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/ZoneDemo.java Sun Nov 25 11:28:27 2007
@@ -0,0 +1,57 @@
+// 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.integration.app1.pages;
+
+import org.apache.tapestry.Block;
+import org.apache.tapestry.ioc.annotations.Inject;
+import org.slf4j.Logger;
+
+public class ZoneDemo
+{
+    @Inject
+    private Logger _logger;
+
+    private String _name;
+
+    private static final String[] NAMES = {"Fred & Wilma", "Mr. <Roboto>", "Grim Fandango"};
+
+    @Inject
+    private Block _showName;
+
+    public String[] getNames()
+    {
+        return NAMES;
+    }
+
+
+    public String getName()
+    {
+        return _name;
+    }
+
+    public void setName(String name)
+    {
+        _name = name;
+    }
+
+    Object onActionFromSelect(String name)
+    {
+        _name = name;
+
+        _logger.info("Selected: '" + _name + "'");
+
+        return _showName;
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentActionDispatcherTest.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.test.InternalBaseTestCase;
-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 static org.easymock.EasyMock.aryEq;
 import static org.easymock.EasyMock.eq;
 import org.testng.annotations.Test;
@@ -70,27 +73,14 @@
     @Test
     public void default_event_with_nested_id_and_context() throws Exception
     {
-        test(
-                "/foo/MyPage.fred/fee/fie/foe/fum",
-                "foo/MyPage",
-                "fred",
-                TapestryConstants.ACTION_EVENT,
-                "fee",
-                "fie",
-                "foe",
-                "fum");
+        test("/foo/MyPage.fred/fee/fie/foe/fum", "foo/MyPage", "fred", TapestryConstants.ACTION_EVENT, "fee", "fie",
+             "foe", "fum");
     }
 
     @Test
     public void default_event_with_context_that_includes_a_colon() throws Exception
     {
-        test(
-                "/foo/MyPage.underdog/a:b:c/d",
-                "foo/MyPage",
-                "underdog",
-                TapestryConstants.ACTION_EVENT,
-                "a:b:c",
-                "d");
+        test("/foo/MyPage.underdog/a:b:c/d", "foo/MyPage", "underdog", TapestryConstants.ACTION_EVENT, "a:b:c", "d");
     }
 
     @Test
@@ -108,14 +98,7 @@
     @Test
     public void nested_component_event_with_context() throws Exception
     {
-        test(
-                "/foo/MyPage.nested:trigger/foo/bar/baz",
-                "foo/MyPage",
-                "nested",
-                "trigger",
-                "foo",
-                "bar",
-                "baz");
+        test("/foo/MyPage.nested:trigger/foo/bar/baz", "foo/MyPage", "nested", "trigger", "foo", "bar", "baz");
     }
 
     @Test
@@ -124,22 +107,14 @@
         ComponentActionRequestHandler handler = newComponentActionRequestHandler();
         Request request = mockRequest();
         Response response = mockResponse();
-        ActionResponseGenerator generator = newMock(ActionResponseGenerator.class);
 
         train_getPath(request, "/mypage:eventname");
 
         train_getParameter(request, InternalConstants.PAGE_CONTEXT_NAME, "alpha/beta");
 
-        expect(
-                handler.handle(
-                        eq("mypage"),
-                        eq(""),
-                        eq("eventname"),
-                        aryEq(new String[0]),
-                        aryEq(new String[]
-                                {"alpha", "beta"}))).andReturn(generator);
+        expect(handler.handle(eq("mypage"), eq(""), eq("eventname"), aryEq(new String[0]),
+                              aryEq(new String[]{"alpha", "beta"}))).andReturn(true);
 
-        generator.sendClientResponse(response);
 
         replay();
 
@@ -150,27 +125,19 @@
         verify();
     }
 
-    private void test(String requestPath, String logicalPageName, String nestedComponentId,
-                      String eventType, String... context) throws IOException
+    private void test(String requestPath, String logicalPageName, String nestedComponentId, String eventType,
+                      String... context) throws IOException
     {
         ComponentActionRequestHandler handler = newComponentActionRequestHandler();
         Request request = mockRequest();
         Response response = mockResponse();
-        ActionResponseGenerator generator = newMock(ActionResponseGenerator.class);
 
         train_getPath(request, requestPath);
 
         train_getParameter(request, InternalConstants.PAGE_CONTEXT_NAME, null);
 
-        expect(
-                handler.handle(
-                        eq(logicalPageName),
-                        eq(nestedComponentId),
-                        eq(eventType),
-                        aryEq(context),
-                        aryEq(new String[0]))).andReturn(generator);
-
-        generator.sendClientResponse(response);
+        expect(handler.handle(eq(logicalPageName), eq(nestedComponentId), eq(eventType), aryEq(context),
+                              aryEq(new String[0]))).andReturn(true);
 
         replay();
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessorTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessorTest.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessorTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessorTest.java Sun Nov 25 11:28:27 2007
@@ -30,8 +30,6 @@
 
     private static final String METHOD_DESCRIPTION = "foo.bar.Baz.biff()";
 
-    private static final String LINK_URI = "{LinkURI}";
-
     @Test
     public void result_is_root_component() throws Exception
     {
@@ -52,17 +50,15 @@
         train_get(cache, PAGE_NAME, page);
 
         train_createPageLink(factory, page, link);
-        train_toRedirectURI(link, LINK_URI);
 
-        response.sendRedirect(LINK_URI);
+        response.sendRedirect(link);
 
         replay();
 
-        ComponentEventResultProcessor<Component> processor = new ComponentInstanceResultProcessor(
-                cache, factory, logger);
+        ComponentEventResultProcessor<Component> processor = new ComponentInstanceResultProcessor(logger, response,
+                                                                                                  cache, factory);
 
-        processor.processComponentEvent(result, source, METHOD_DESCRIPTION).sendClientResponse(
-                response);
+        processor.processComponentEvent(result, source, METHOD_DESCRIPTION);
 
         verify();
     }
@@ -97,17 +93,15 @@
         train_get(cache, PAGE_NAME, page);
 
         train_createPageLink(factory, page, link);
-        train_toRedirectURI(link, LINK_URI);
 
-        response.sendRedirect(LINK_URI);
+        response.sendRedirect(link);
 
         replay();
 
-        ComponentEventResultProcessor<Component> processor = new ComponentInstanceResultProcessor(
-                cache, factory, logger);
+        ComponentEventResultProcessor<Component> processor = new ComponentInstanceResultProcessor(logger, response,
+                                                                                                  cache, factory);
 
-        processor.processComponentEvent(value, source, METHOD_DESCRIPTION).sendClientResponse(
-                response);
+        processor.processComponentEvent(value, source, METHOD_DESCRIPTION);
 
         verify();
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ObjectComponentEventResultProcessorTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ObjectComponentEventResultProcessorTest.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ObjectComponentEventResultProcessorTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ObjectComponentEventResultProcessorTest.java Sun Nov 25 11:28:27 2007
@@ -51,11 +51,12 @@
         }
         catch (TapestryException ex)
         {
-            assertEquals(
-                    ex.getMessage(),
-                    "An event handler for component foo.Bar:gnip.gnop returned the value *INVALID* (from method foo.component.Gnop.blip()).  "
-                            + "Return type java.lang.String can not be handled.  "
-                            + "Configured return types are java.lang.String, java.util.List, java.util.Map.");
+            assertEquals(ex.getMessage(),
+                         "An event handler for component foo.Bar:gnip.gnop returned the value *INVALID* (from method foo.component.Gnop.blip()).  " + "Return type java.lang.String can not be handled.  " + "Configured return types are java.lang.String, java.util.List, java.util.Map.");
+        }
+        catch (java.io.IOException e)
+        {
+            throw new RuntimeException(e);
         }
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/RequestImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/RequestImplTest.java?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/RequestImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/RequestImplTest.java Sun Nov 25 11:28:27 2007
@@ -123,11 +123,6 @@
     @DataProvider(name = "xhr_inputs")
     public Object[][] xhr_inputs()
     {
-        return new Object[][]
-                {
-                        {null, false},
-                        {"", false},
-                        {"some other value", false},
-                        {"XmlHttpRequest", true}};
+        return new Object[][]{{null, false}, {"", false}, {"some other value", false}, {"XMLHttpRequest", true}};
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/add_script.txt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/add_script.txt?rev=598036&r1=598035&r2=598036&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/add_script.txt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/add_script.txt Sun Nov 25 11:28:27 2007
@@ -1,6 +1,6 @@
 <html><body><p>Ready to be updated with scripts.</p><script type="text/javascript">
 <!--
-Event.observe(window, "load", function() {
+Event.observe(window, 'load', function() {
 doSomething();
 doSomethingElse();
 });