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 2006/10/19 07:20:03 UTC

svn commit: r465496 [2/2] - in /tapestry/tapestry5/tapestry-core/trunk/src: main/aspect/org/apache/tapestry/internal/aspects/ main/java/org/apache/tapestry/ main/java/org/apache/tapestry/annotations/ main/java/org/apache/tapestry/corelib/components/ ma...

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java Wed Oct 18 22:20:00 2006
@@ -51,14 +51,18 @@
 import org.apache.tapestry.internal.services.InjectWorker;
 import org.apache.tapestry.internal.services.InjectionProvider;
 import org.apache.tapestry.internal.services.InternalModule;
+import org.apache.tapestry.internal.services.LinkFactory;
 import org.apache.tapestry.internal.services.MarkupWriterImpl;
 import org.apache.tapestry.internal.services.OnEventWorker;
 import org.apache.tapestry.internal.services.PageRenderDispatcher;
 import org.apache.tapestry.internal.services.PageResponseRenderer;
 import org.apache.tapestry.internal.services.ParameterWorker;
+import org.apache.tapestry.internal.services.PersistWorker;
+import org.apache.tapestry.internal.services.PersistentFieldManagerImpl;
 import org.apache.tapestry.internal.services.RequestGlobalsImpl;
 import org.apache.tapestry.internal.services.RequestPageCache;
 import org.apache.tapestry.internal.services.RetainWorker;
+import org.apache.tapestry.internal.services.SessionPersistentFieldStrategy;
 import org.apache.tapestry.internal.services.StaticFilesFilter;
 import org.apache.tapestry.internal.services.UnclaimedFieldWorker;
 import org.apache.tapestry.internal.services.WebContextImpl;
@@ -72,6 +76,7 @@
 import org.apache.tapestry.ioc.ServiceLocator;
 import org.apache.tapestry.ioc.annotations.Contribute;
 import org.apache.tapestry.ioc.annotations.Id;
+import org.apache.tapestry.ioc.annotations.Inject;
 import org.apache.tapestry.ioc.annotations.InjectService;
 import org.apache.tapestry.ioc.annotations.Lifecycle;
 import org.apache.tapestry.ioc.annotations.SubModule;
@@ -83,8 +88,6 @@
 
 /**
  * The root module for Tapestry.
- * 
- * 
  */
 @Id("tapestry")
 @SubModule(
@@ -106,9 +109,12 @@
 
     private final PageResponseRenderer _pageResponseRenderer;
 
+    private final WebRequest _request;
+
     // Yes, you can inject services defined by this module into this module. The service proxy is
     // created without instantiating the module itself. We're careful about making as many
-    // service builder and contributor methods static as possible to avoid recursive build exceptions.
+    // service builder and contributor methods static as possible to avoid recursive build
+    // exceptions.
 
     public TapestryModule(@InjectService("tapestry.ioc.PipelineBuilder")
     PipelineBuilder pipelineBuilder, @InjectService("tapestry.ioc.PropertyShadowBuilder")
@@ -117,7 +123,8 @@
     ApplicationGlobals applicationGlobals, @InjectService("tapestry.ioc.ChainBuilder")
     ChainBuilder chainBuilder, @InjectService("tapestry.internal.RequestPageCache")
     RequestPageCache requestPageCache, @InjectService("tapestry.internal.PageResponseRenderer")
-    PageResponseRenderer pageResponseRenderer)
+    PageResponseRenderer pageResponseRenderer, @Inject("infrastructure:request")
+    WebRequest request)
     {
         _pipelineBuilder = pipelineBuilder;
         _shadowBuilder = shadowBuilder;
@@ -126,6 +133,7 @@
         _chainBuilder = chainBuilder;
         _requestPageCache = requestPageCache;
         _pageResponseRenderer = pageResponseRenderer;
+        _request = request;
     }
 
     private static <T> void add(Configuration<InfrastructureContribution> configuration,
@@ -360,6 +368,7 @@
             TypeCoercer typeCoercer)
     {
         add(configuration, locator, MarkupWriterFactory.class);
+        add(configuration, locator, PersistentFieldManager.class);
 
         configuration.add(new InfrastructureContribution("request", request));
         configuration.add(new InfrastructureContribution("response", response));
@@ -379,7 +388,9 @@
         configuration.add("infrastructure", infrastructure.getObjectProvider());
     }
 
-    public void contributeMasterDispatcher(OrderedConfiguration<Dispatcher> configuration)
+    public void contributeMasterDispatcher(OrderedConfiguration<Dispatcher> configuration,
+            @InjectService("tapestry.internal.LinkFactory")
+            LinkFactory linkFactory)
     {
         configuration.add(
                 "HTML",
@@ -387,8 +398,8 @@
 
         // This goes after the HTML one so that the "." in ".html" doesn't confuse it.
 
-        configuration.add("ComponentEvent", new ComponentEventDispatcher(_pageResponseRenderer,
-                _requestPageCache), "after:HTML");
+        configuration.add("ComponentEvent", new ComponentEventDispatcher(_requestPageCache,
+                linkFactory), "after:HTML");
     }
 
     public static ComponentClassResolver buildComponentClassResolver(
@@ -464,6 +475,7 @@
      * Adds a number of standard component class transform workers:
      * <ul>
      * <li>Retain -- allows fields to retain their values between requests</li>
+     * <li>Persist -- allows fields to store their their value persistently between requests</li>
      * <li>Parameter -- identifies parameters based on the
      * {@link org.apache.tapestry.annotations.Parameter} annotation</li>
      * <li>Component -- identifies embedded components based on the
@@ -484,7 +496,9 @@
             InjectionProvider injectionProvider, @InjectService("Environment")
             Environment environment)
     {
-        // TODO: Proper scheduling of all of this.
+        // TODO: Proper scheduling of all of this. Since a given field or method should
+        // only have a single annotation, the order doesn't matter so much, as long as
+        // UnclaimedField is last.
 
         configuration.add("Inject", new InjectWorker(objectProvider, locator, injectionProvider));
         configuration.add("Parameter", new ParameterWorker());
@@ -503,6 +517,7 @@
         add(configuration, TransformConstants.CLEANUP_RENDER_SIGNATURE, CleanupRender.class);
 
         configuration.add("Retain", new RetainWorker());
+        configuration.add("Persist", new PersistWorker());
         configuration.add("UnclaimedField", new UnclaimedFieldWorker(), "after:*.*");
     }
 
@@ -547,5 +562,21 @@
                     r.run();
             }
         };
+    }
+
+    /** A public service since extensions may provide new persistent strategies. */
+    public static PersistentFieldManager buildPersistentFieldManager(
+            Map<String, PersistentFieldStrategy> configuration)
+    {
+        return new PersistentFieldManagerImpl(configuration);
+    }
+
+    /**
+     * Contributes the "session" strategy.
+     */
+    public void contributePersistentFieldManager(
+            MappedConfiguration<String, PersistentFieldStrategy> configuration)
+    {
+        configuration.add("session", new SessionPersistentFieldStrategy(_request));
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TransformConstants.java Wed Oct 18 22:20:00 2006
@@ -24,8 +24,6 @@
 /**
  * Constants used by implementations of
  * {@link org.apache.tapestry.services.ComponentClassTransformWorker}.
- * 
- * 
  */
 @Utility
 public final class TransformConstants
@@ -62,6 +60,13 @@
      */
     public static final MethodSignature CONTAINING_PAGE_DID_DETACH_SIGNATURE = new MethodSignature(
             "containingPageDidDetach");
+
+    /**
+     * Signature for
+     * {@link org.apache.tapestry.runtime.PageLifecycleListener#containingPageDidAttach()}.
+     */
+    public static final MethodSignature CONTAINING_PAGE_DID_ATTACH_SIGNATURE = new MethodSignature(
+            "containingPageDidAttach");
 
     /**
      * Signature for

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebRequest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebRequest.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebRequest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebRequest.java Wed Oct 18 22:20:00 2006
@@ -18,8 +18,6 @@
 
 /**
  * Generic version of {@link javax.servlet.http.HttpServletRequest}.
- * 
- * 
  */
 public interface WebRequest
 {
@@ -50,7 +48,16 @@
      * Returns the context path portion of the URI. This always starts with a "/" character and does
      * not end with one, with the exception of servlets in the root context, which return the empty
      * string.
-     * 
      */
     String getContextPath();
+
+    /**
+     * Gets the {@link WebSession}. If create is false and the session has not be created
+     * previously, returns null.
+     * 
+     * @param create
+     *            true to force the creation of the session
+     * @return the session (or null if create is false the session has not been previously created)
+     */
+    WebSession getSession(boolean create);
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebResponse.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebResponse.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebResponse.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebResponse.java Wed Oct 18 22:20:00 2006
@@ -19,8 +19,6 @@
 
 /**
  * API agnostic wrapper for generating a response.
- * 
- * 
  */
 public interface WebResponse
 {
@@ -38,4 +36,22 @@
      * @return the same URL or a different one with additional information to track the user session
      */
     String encodeURL(String URL);
+
+    /**
+     * Encodes the URL for use as a redirect, ensuring that a session id is included (if a session
+     * exists, and as necessary depending on the client browser's use of cookies).
+     * 
+     * @param URL
+     * @return the same URL or a different one with additional information to track the user session
+     */
+    String encodeRedirectURL(String URL);
+
+    /**
+     * Sends a redirect to the client.
+     * 
+     * @param URL
+     *            full or partial (relative) URL to send to the client
+     * @see #encodeRedirectURL(String)
+     */
+    void sendRedirect(String URL) throws IOException;
 }

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebSession.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebSession.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebSession.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/WebSession.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,43 @@
+// Copyright 2006 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.util.List;
+
+import javax.servlet.http.HttpSession;
+
+/**
+ * Generic version of {@link HttpSession}.
+ */
+public interface WebSession
+{
+    /**
+     * Returns a list of the names of all attributes stored in the session. The names are returned
+     * sorted alphabetically.
+     */
+    List<String> getAttributeNames();
+
+    /**
+     * Returns a list of the names of all attributes stored in the session whose name has the
+     * provided prefix. The names are returned in alphabetical order.
+     */
+    List<String> getAttributeNames(String prefix);
+
+    /** Returns the value previously stored in the session. */
+    Object getAttribute(String name);
+
+    /** Sets the value of an attribute. If the value is null, then the attribute is deleted. */
+    void setAttribute(String name, Object value);
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java Wed Oct 18 22:20:00 2006
@@ -30,6 +30,9 @@
 import java.util.List;
 import java.util.UUID;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
 import org.apache.commons.logging.Log;
 import org.apache.tapestry.Binding;
 import org.apache.tapestry.ComponentResources;
@@ -62,6 +65,7 @@
 import org.apache.tapestry.services.MethodSignature;
 import org.apache.tapestry.services.WebRequest;
 import org.apache.tapestry.services.WebResponse;
+import org.apache.tapestry.services.WebSession;
 
 /**
  * Base test case that adds a number of convienience factory and training methods to
@@ -536,5 +540,56 @@
     protected final WebResponse newWebResponse()
     {
         return newMock(WebResponse.class);
+    }
+
+    protected void train_getAttribute(HttpSession session, String attributeName, Object value)
+    {
+        session.getAttribute(attributeName);
+        setReturnValue(value);
+    }
+
+    protected final HttpServletRequest newHttpServletRequest()
+    {
+        return newMock(HttpServletRequest.class);
+    }
+
+    protected final void train_getSession(HttpServletRequest request, boolean create, HttpSession session)
+    {
+        request.getSession(create);
+        setReturnValue(session);
+    }
+
+    protected final HttpSession newHttpSession()
+    {
+        return newMock(HttpSession.class);
+    }
+
+    protected final void train_getAttributeNames(WebSession session, String prefix, String... names)
+    {
+        session.getAttributeNames(prefix);
+        setReturnValue(Arrays.asList(names));
+    }
+
+    protected final void train_getAttribute(WebSession session, String name, Object attribute)
+    {
+        session.getAttribute(name);
+        setReturnValue(attribute);
+    }
+
+    protected final WebSession newWebSession()
+    {
+        return newMock(WebSession.class);
+    }
+
+    protected final void train_getSession(WebRequest request, boolean create, WebSession session)
+    {
+        request.getSession(create);
+        setReturnValue(session);
+    }
+
+    protected final void train_encodeRedirectURL(WebResponse response, String URI, String encoded)
+    {
+        response.encodeRedirectURL(URI);
+        setReturnValue(encoded);
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/model/ModelStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/model/ModelStrings.properties?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/model/ModelStrings.properties (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/model/ModelStrings.properties Wed Oct 18 22:20:00 2006
@@ -14,4 +14,5 @@
 
 duplicate-parameter=Parameter '%s' of component %s is already defined.
 duplicate-parameter-value=A value for parameter '%s' of embedded component %s (of component class %s) has already been provided.
-duplicate-component-id=Embedded component '%s' has already been defined for component class %s.
\ No newline at end of file
+duplicate-component-id=Embedded component '%s' has already been defined for component class %s.
+missing-persistent-field=No field persistence strategy has been defined for field '%s'.
\ No newline at end of file

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties Wed Oct 18 22:20:00 2006
@@ -52,4 +52,5 @@
 page-name-unresolved=Unable to resolve class name %s to a logical page name.
 context-index-out-of-range=Method %s has more parameters than there are context values for this component event.
 exception-in-method-parameter=Exception in method %s, parameter #%d: %s
-component-event-is-aborted=Can not store result from invoking method %s, because an event result value has already been obtained from some other event handler method.
\ No newline at end of file
+component-event-is-aborted=Can not store result from invoking method %s, because an event result value has already been obtained from some other event handler method.
+unknown-persistent-field-strategy='%s' is not a defined persistent strategy.  Defined stategies: %s.
\ No newline at end of file

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/component-classes.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/component-classes.apt?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/component-classes.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/component-classes.apt Wed Oct 18 22:20:00 2006
@@ -127,6 +127,9 @@
   {{{parameters.html}Component parameters}} are also identified using private fields of your class, with
   the {{{.../apidocs/org/apache/tapestry/annotations/Parameter.html}Parameter}} annotation.
   
+Persistent Fields
+
+  Fields may be annotated so that they {{{persist.html}retain their value across requests}}.  
   
 {Embedded Components}
 

Added: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/event.apt Wed Oct 18 22:20:00 2006
@@ -0,0 +1,104 @@
+ ---
+ Component Events
+ ---
+ 
+Component Events
+
+  Component events are the means by which components are made aware of behaviors by the user, such
+  as clicking links and submitting forms.
+  
+  In Tapestry 4, you would configure a parameter of a component with the name of a method to invoke
+  when a certain event occured, usually a request from the client.
+  
+  This has some limitations, including the fact that only a single method could be invoked.
+  
+  Tapestry 5 introduces the
+  {{{../apidocs/org/apache/tapestry/annotations/OnEvent.html}OnEvent annotation}} which is used
+  to mark methods as <event handler methods>.  As with other annotations, these methods
+  may be private or public.
+  
+  Rather than configure a component to invoke a particular method, you annotate one or more
+  methods to listen for events from that component.
+  
+  For example, here's a portion of a page that lets the user choose a value between 1 and 10:
+  
++---+
+<p> Choose a number from 1 to 10: </p>
+
+<p>
+    <t:comp type="Count" end="10" value="prop:index">
+        <t:comp id="choose" type="ActionLink" context="prop:index">${index}</t:comp>
+    </t:comp>
+</p>
++---+
+
+  The ActionLink component creates an action URL.
+  
+  The URL identifies the page that contains the component, the type of event
+  ("action", the default), the id of the component ("choose"), plus the additional context value.
+  A sample URL: <<<http://localhost:8080/ActionPage.action/choose/3>>>.
+  
+  When there are additional context values, they are appended to the path.
+   
+  A Java method can be invoked when the link for the component is clicked by the user:
+  
++---+
+  @OnEvent(component = "choose")
+  void choose(int value)
+  {
+    _value = value;
+  }
++---+
+
+  Tapestry has done two things here:
+  
+  * It has identified method choose() as the method to invoke.
+  
+  * It has converted the context value from a string to an integer and passed it into the method.
+  
+  The OnEvent annotation allows events to be selected based on the originating component,
+  or on the type of event.
+  
+Context
+
+  The context values (the context parameter to the ActionLink component) can be any object.
+  However, only a simple conversion to string occurs.  This is in contrast to Tapestry 4, which had
+  an elaborate type mechanism with the odd name "DataSqueezer".
+  
+  Again, whatever your value is (string, number, date), it is converted into a plain string.
+  This results in a more readable string.
+  
+  If you have multiple context values (by binding a list or array of objects to the ActionLink's
+  context parameter), then each one, in order, will be added to the URL.
+  
+  When an event handler method is invoked, a
+  {{{coercion.html}coercion}} from string to the actual type occurs. A runtime exception
+  occurs if there are more parameters than context strings.
+  
+Event Bubbling
+
+  The event will bubble up the hierarchy, until it is aborted. The event is aborted
+  when an event handler method returns a non-null value.
+  
+  The value returned from an event handler method determines how Tapestry will render a response.
+  
+Event Handler Returns Types
+
+  To be determined.  For the moment, the return type of event handler methods is <<ignored>>.
+  
+End of Action Request
+
+  The default behavior at the end of an action request is to set up the page containing
+  the component to render.
+  
+  <<This is very important:>> The rendering occurs in a <<new>> request. The normal response
+  to an action request is a client-side redirect to re-render the page. Thus an action is <<two>>
+  requests: one to process the action and update server-side state, and a second request to render
+  the resulting page.
+  
+  It is very important that you make use of 
+  {{{persist.html}page persistence}} to allow information from the action request
+  to survive to the next render request.
+  
+  
+   
\ No newline at end of file

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/infrastructure.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/infrastructure.apt?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/infrastructure.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/infrastructure.apt Wed Oct 18 22:20:00 2006
@@ -49,6 +49,10 @@
 *-----------------------+--------------------------------------------------------------------+------------------------------------+
 | <<Property>>          | <<Service Interface>>                                             | <<Default Service>>               |
 *-----------------------+--------------------------------------------------------------------+-----------------------------------+
+| markupWriterFactory | {{{../apidocs/org/apache/tapestry/services/MarkupWriterFactory.html}MarkupWriterFactory}} | tapestry.MarkupWriterFactory |
+*-----------------------+--------------------------------------------------------------------+-----------------------------------+
+| persistentFieldManager | {{{../apidocs/org/apache/tapestry/services/PersistentFieldManager.html}PersistentFieldManager}} | tapestry.PersistentFieldManager |
+*-----------------------+--------------------------------------------------------------------+-----------------------------------+
 | request               | {{{../apidocs/org/apache/tapestry/services/WebRequest.html}WebRequest}}  | tapestry.WebRequest         |        
 *-----------------------+--------------------------------------------------------------------------------------------------------+
 | response | {{{../apidocs/org/apache/tapestry/services/WebResponse.html}WebResponse}}  | tapestry.WebResponse |        

Added: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt Wed Oct 18 22:20:00 2006
@@ -0,0 +1,59 @@
+ ----
+ Persistent Page Data
+ ----
+ 
+Persistent Page Data
+
+  Most instance variables in Tapestry are automatically cleared at the end of each request.
+  
+  This is important, as it pertains to how Tapestry pages are pooled and shared, over time,
+  by many users.
+  
+  However, you often want to store some persistent data on a page, and have access
+  to it in later requests.
+  
+  This is accomplished with the 
+  {{{../apidocs/org/apache/tapestry/annotations/Persist.html}Persist annotation}}.
+  
+  This annotation is applied to private instance fields.
+    
++----+
+  @Persist
+  private int _value;
++----+
+  
+
+  
+  Annotated fields will store their state between requests. Generally, speaking, this means
+  that the value is stored into the session (but other approaches are possible).
+  
+  Whenever you make a change to a persistent field, its value is stored.
+  
+  On later requests, the value for such persistent fields is reloaded from storage.
+  
+Persistence Strategies
+
+  The value for each field is the <strategy> used to store the field between requests.
+  
+  Currently, only the default value, "session", is supported. Other implementations, that store
+  the value on the client, are forthcoming.
+  
+* session strategy
+
+  The session strategy stores field changes into the session; the session is created as necessary.
+  
+  A suitably long session attribute name is used; it incorporates the
+  name of the page, the nested component id, and the name of the field.
+  
+Default Values
+
+  As with other fields, a default value may be specified inline, or inside a constructor.
+  
+  This value is retained and used to reset the value of the field at the end of each request,
+  before the page is returned to the page pool.
+  
+  Handling of the null value can be a tricky case, due to the limitations of the underlying 
+  Servlet API.  Changing a persistent field's value to null <removes> the
+  field's attribute from the session. On later requests, the field will reset to its
+  default value. Since that is usually null, this is not a problem ... it is only a problem
+  if a field has a non-null default value and may be changed to null. 
\ No newline at end of file

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/reload.apt Wed Oct 18 22:20:00 2006
@@ -1,8 +1,8 @@
  ---
- Class and Template Reloading
+ Live Class and Template Reloading
  ---
  
-Class and Template Reloading
+Live Class and Template Reloading
 
   One of the great new features of Tapestry 5 is automatic reloading of changed classes and templates.
   
@@ -14,6 +14,22 @@
   
   <Note: eventually, there will be some configuration to control how often changes are checked for. Currently it is forced
   to operate on virtually every request, which is fine for development but not appropriate for production.>
+  
+* Template Reloading
+
+  When a template changes, all page instances (as well as the hiearchy of components below them) are discarded and
+  reconstructed with the new template. However, classes are not reloaded in this case.
+  
+  A future version of Tapestry may be more selective, removing only page instances that are affected by the changed
+  file(s).
+  
+* Class Reloading
+
+  On a change to <any> class inside a controlled package (or any sub-package of a controlled package), Tapestry will
+  discard all page instances and the class loader.
+  
+  {{{persist.html}Persistent data}} on the pages will usually not be affected (as it is stored separately, in the session).
+  This allows you to make fairly significant changes to a component class even while the application continues to run.
   
 Page and Component Packages
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/templates.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/templates.apt?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/templates.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/templates.apt Wed Oct 18 22:20:00 2006
@@ -53,6 +53,8 @@
 
   Tapestry elements are elements defined using the Tapestry namespace prefix.
   
+  <<Tapestry 4 style templates with "invisible annotations" will be re-implemented soon. They are not being abandoned.>>  
+  
 * \<comp\>
 
   The \<comp\> element is used to identify an <embedded component> within the template.

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt Wed Oct 18 22:20:00 2006
@@ -66,6 +66,9 @@
   
   You can get a peek of upcoming ideas in the {{{tap5devwiki.html#MasterIndex}Developer Wiki}}.  
   
+  Also, check out the {{{screencast.html}Tapestry 5 Screencasts}} for a visual introduction to what
+  Tapestry 5 has to offer.
+  
 Adaptive API
 
   A key feature of Tapestry 5 is <adaptive API>.

Added: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/screencast.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/screencast.apt?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/screencast.apt (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/screencast.apt Wed Oct 18 22:20:00 2006
@@ -0,0 +1,17 @@
+ ----
+ Tapestry Screencasts
+ ----
+ 
+  Screencasts are a great way to learn about a new tool or framework without having to download
+  a single thing to your computer.
+ 
+  Howard Lewis Ship has started creating a series of screencasts about Tapestry 5.
+  
+Screencast #1
+
+  Howard demonstrates how to set up a new Tapestry 5 project inside Eclipse (using the 
+  Maven plugin). He also demonstrates 
+  {{{guide/reload.html}live class reloading}}.
+  
+  {{{http://howardlewisship.com/screencasts/tap5-classreload-oct2006/tap5-classreload-oct2006.html}Tapestry 5 Technology Preview -- 17 Oct 2006}}
+  
\ No newline at end of file

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml Wed Oct 18 22:20:00 2006
@@ -49,14 +49,17 @@
             <item name="Introduction" href="/index.html"/>
             <item name="Upgrade from Tapestry 4" href="/upgrade.html"/>
             <item name="Tapestry for Struts Developers" href="struts.html"/>
+            <item name="Screencasts" href="screencast.html"/>
         </menu> 
 
         <menu name="User Guide">
             <item name="Component Classes" href="guide/component-classes.html"/>
             <item name="Component Parameters" href="guide/parameters.html"/>
+            <item name="Component Events" href="guide/event.html"/>
             <item name="Type Coercion" href="guide/coercion.html"/>
             <item name="Component Rendering" href="guide/rendering.html"/>
-            <item name="Component Templates" href="guide/templates.html"/>
+            <item name="Component Templates" href="guide/templates.html"/>
+            <item name="Persistent Data" href="guide/persist.html"/>
             <item name="Injection" href="guide/inject.html"/>
             <item name="Infrastructure" href="guide/infrastructure.html"/>
             <item name="Configuration" href="guide/conf.html"/>

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ActionPage.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ActionPage.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ActionPage.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ActionPage.java Wed Oct 18 22:20:00 2006
@@ -1,7 +1,22 @@
+// Copyright 2006 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.annotations.ComponentClass;
 import org.apache.tapestry.annotations.OnEvent;
+import org.apache.tapestry.annotations.Persist;
 
 /**
  * 
@@ -11,6 +26,9 @@
 {
     private int _index;
 
+    // Must be persistent, to survive from one request to the next.
+    // An action request is always followed by a redirect request.
+    @Persist
     private int _value;
 
     @OnEvent(component = "choose")

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java Wed Oct 18 22:20:00 2006
@@ -22,8 +22,6 @@
 
 /**
  * For use in places where we don't want to have to transform a class just for testing purposes.
- * 
- * 
  */
 public class DefaultComponentLifecyle implements ComponentLifecycle
 {

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/IOCUtilitiesTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/IOCUtilitiesTest.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/IOCUtilitiesTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/IOCUtilitiesTest.java Wed Oct 18 22:20:00 2006
@@ -17,8 +17,6 @@
 import static org.apache.tapestry.util.CollectionFactory.newMap;
 
 import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
 import java.util.List;
 import java.util.Map;
 
@@ -68,17 +66,6 @@
         // Make sure that joinSorted() doesn't change the input list
 
         assertEquals(copy, unsorted);
-    }
-
-    @Test
-    public void enumeration_to_list()
-    {
-        List<String> input = Arrays.asList("wilma", "fred", "barney");
-        Enumeration e = Collections.enumeration(input);
-
-        List<String> output = IOCUtilities.toList(e);
-
-        assertEquals(output, Arrays.asList("barney", "fred", "wilma"));
     }
 
     @Test(dataProvider = "capitalize_inputs")

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java Wed Oct 18 22:20:00 2006
@@ -27,8 +27,6 @@
 /**
  * Tests {@link org.apache.tapestry.internal.model.MutableComponentModelImpl} and
  * {@link org.apache.tapestry.internal.model.MutableEmbeddedComponentModelImpl}.
- * 
- * 
  */
 public class MutableComponentModelImplTest extends InternalBaseTestCase
 {
@@ -44,7 +42,7 @@
 
         replay();
 
-        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r);
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
 
         assertTrue(model.getParameterNames().isEmpty());
 
@@ -68,7 +66,7 @@
 
         replay();
 
-        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r);
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
 
         model.addParameter("fred", true);
 
@@ -95,7 +93,7 @@
 
         replay();
 
-        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r);
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
 
         assertNull(model.getParameterModel("foo"));
 
@@ -110,7 +108,7 @@
 
         replay();
 
-        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r);
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
         model.addParameter("fred", true);
 
         assertNull(model.getParameterModel("barney"));
@@ -126,7 +124,7 @@
 
         replay();
 
-        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r);
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
 
         assertTrue(model.getEmbeddedComponentIds().isEmpty());
 
@@ -151,7 +149,7 @@
         assertEquals(
                 fred.toString(),
                 "EmbeddedComponentModel[id=fred type=Fred class=org.example.components.Fred]");
-        
+
         verify();
     }
 
@@ -163,7 +161,7 @@
 
         replay();
 
-        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r);
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
 
         model.addEmbeddedComponent("fred", "Fred1", COMPONENT_CLASS_NAME);
 
@@ -191,7 +189,7 @@
 
         replay();
 
-        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r);
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
 
         MutableEmbeddedComponentModel fred = model.addEmbeddedComponent(
                 "fred",
@@ -218,7 +216,7 @@
 
         replay();
 
-        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r);
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
 
         MutableEmbeddedComponentModel fred = model.addEmbeddedComponent(
                 "fred",
@@ -238,6 +236,125 @@
                     ex.getMessage(),
                     "A value for parameter 'city' of embedded component fred (of component class org.example.components.Foo) has already been provided.");
         }
+
+        verify();
+    }
+
+    @Test
+    public void get_persistent_field_names_when_none_defined()
+    {
+        Resource r = newResource();
+        Log log = newLog();
+
+        replay();
+
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
+
+        assertTrue(model.getPersistentFieldNames().isEmpty());
+
+        verify();
+    }
+
+    @Test
+    public void get_persistent_field_names_are_sorted()
+    {
+        Resource r = newResource();
+        Log log = newLog();
+
+        replay();
+
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
+
+        model.setFieldPersistenceStrategy("fred", "session");
+        model.setFieldPersistenceStrategy("barney", "client");
+
+        assertEquals(model.getPersistentFieldNames(), Arrays.asList("barney", "fred"));
+
+        verify();
+    }
+
+    @Test
+    public void get_persistent_field_names_reflects_parent_model()
+    {
+        Resource r = newResource();
+        Log log = newLog();
+
+        replay();
+
+        MutableComponentModel parent = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, parent);
+
+        parent.setFieldPersistenceStrategy("wilma", "session");
+
+        model.setFieldPersistenceStrategy("fred", "session");
+        model.setFieldPersistenceStrategy("barney", "client");
+
+        assertEquals(model.getPersistentFieldNames(), Arrays.asList("barney", "fred", "wilma"));
+
+        verify();
+    }
+
+    @Test
+    public void get_persistent_field_defined_in_model()
+    {
+        Resource r = newResource();
+        Log log = newLog();
+
+        replay();
+
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
+
+        model.setFieldPersistenceStrategy("fred", "session");
+        model.setFieldPersistenceStrategy("barney", "client");
+
+        assertEquals(model.getFieldPersistenceStrategy("fred"), "session");
+        assertEquals(model.getFieldPersistenceStrategy("barney"), "client");
+
+        verify();
+    }
+
+    @Test
+    public void no_persistence_defined_for_field()
+    {
+        Resource r = newResource();
+        Log log = newLog();
+
+        replay();
+
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
+
+        try
+        {
+            model.getFieldPersistenceStrategy("someField");
+            unreachable();
+        }
+        catch (IllegalArgumentException ex)
+        {
+            assertEquals(
+                    ex.getMessage(),
+                    "No field persistence strategy has been defined for field \'someField\'.");
+        }
+
+        verify();
+
+    }
+
+    @Test
+    public void get_persistent_field_defined_in_parent()
+    {
+        Resource r = newResource();
+        Log log = newLog();
+
+        replay();
+
+        MutableComponentModel parent = new MutableComponentModelImpl(CLASS_NAME, log, r, null);
+        MutableComponentModel model = new MutableComponentModelImpl(CLASS_NAME, log, r, parent);
+
+        parent.setFieldPersistenceStrategy("wilma", "parent");
+
+        model.setFieldPersistenceStrategy("fred", "session");
+
+        assertEquals(model.getFieldPersistenceStrategy("wilma"), "parent");
 
         verify();
     }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentEventImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentEventImplTest.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentEventImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentEventImplTest.java Wed Oct 18 22:20:00 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 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;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java Wed Oct 18 22:20:00 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 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;
@@ -9,23 +23,24 @@
 import org.apache.tapestry.services.WebResponse;
 import org.testng.annotations.Test;
 
-/**
- * 
- */
 public class LinkFactoryImplTest extends InternalBaseTestCase
 {
+    private static final String PAGE_LOGICAL_NAME = "sub/MyPage";
+
+    private static final String PAGE_CLASS_NAME = "foo.pages.sub.MyPage";
+
     @Test
     public void action_link_root_context_no_ids()
     {
-        run("foo.pages.sub.MyPage", "sub/MyPage", "foo.bar", "", "/sub/MyPage.someaction/foo.bar");
+        run(PAGE_CLASS_NAME, PAGE_LOGICAL_NAME, "foo.bar", "", "/sub/MyPage.someaction/foo.bar");
     }
 
     @Test
     public void action_link_root_context_with_ids()
     {
         run(
-                "foo.pages.sub.MyPage",
-                "sub/MyPage",
+                PAGE_CLASS_NAME,
+                PAGE_LOGICAL_NAME,
                 "foo.bar",
                 "",
                 "/sub/MyPage.someaction/foo.bar/fred/5",
@@ -37,11 +52,36 @@
     public void action_link_named_context_no_ids()
     {
         run(
-                "foo.pages.sub.MyPage",
-                "sub/MyPage",
+                PAGE_CLASS_NAME,
+                PAGE_LOGICAL_NAME,
                 "foo.bar",
                 "/fred",
                 "/fred/sub/MyPage.someaction/foo.bar");
+    }
+
+    @Test
+    public void page_link()
+    {
+        WebRequest request = newWebRequest();
+        WebResponse response = newWebResponse();
+        ComponentClassResolver resolver = newComponentClassResolver();
+        Page page = newPage();
+
+        train_getName(page, PAGE_CLASS_NAME);
+        train_resolvePageClassNameToPageName(resolver, PAGE_CLASS_NAME, PAGE_LOGICAL_NAME);
+        train_getContextPath(request, "/barney");
+
+        train_encodeRedirectURL(response, "/barney/" + PAGE_LOGICAL_NAME + ".html", "*encoded*");
+
+        replay();
+
+        LinkFactory factory = new LinkFactoryImpl(request, response, resolver);
+
+        Link link = factory.createPageLink(page);
+
+        assertEquals(link.toRedirectURI(), "*encoded*");
+
+        verify();
     }
 
     private void run(String pageClassName, String logicalPageName, String nestedId,

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/OnEventWorkerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/OnEventWorkerTest.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/OnEventWorkerTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/OnEventWorkerTest.java Wed Oct 18 22:20:00 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 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 java.lang.annotation.Annotation;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLoaderImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLoaderImplTest.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLoaderImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLoaderImplTest.java Wed Oct 18 22:20:00 2006
@@ -81,7 +81,7 @@
 
         replay();
 
-        PageLoader loader = new PageLoaderImpl(templateSource, elementFactory, bindingSource, null);
+        PageLoader loader = new PageLoaderImpl(templateSource, elementFactory, bindingSource, null, null);
 
         loader.loadPage(PAGE_CLASS_NAME, LOCALE);
 
@@ -151,7 +151,7 @@
 
         replay();
 
-        PageLoader loader = new PageLoaderImpl(templateSource, elementFactory, bindingSource, null);
+        PageLoader loader = new PageLoaderImpl(templateSource, elementFactory, bindingSource, null, null);
 
         loader.loadPage(PAGE_CLASS_NAME, LOCALE);
 

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PersistentFieldBundleImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PersistentFieldBundleImplTest.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PersistentFieldBundleImplTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PersistentFieldBundleImplTest.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,63 @@
+// Copyright 2006 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 java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.services.PersistentFieldBundle;
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.testng.annotations.Test;
+
+public class PersistentFieldBundleImplTest extends InternalBaseTestCase
+{
+    @Test
+    public void get_root_component_value()
+    {
+        String value = "FIELD-VALUE";
+
+        PersistentFieldChange change = new PersistentFieldChangeImpl("", "field", value);
+        Collection<PersistentFieldChange> changes = Arrays.asList(change);
+
+        PersistentFieldBundle bundle = new PersistentFieldBundleImpl(changes);
+
+        assertTrue(bundle.containsValue("", "field"));
+        assertTrue(bundle.containsValue(null, "field"));
+
+        assertSame(bundle.getValue("", "field"), value);
+        assertSame(bundle.getValue(null, "field"), value);
+
+        assertFalse(bundle.containsValue("", "other"));
+        assertFalse(bundle.containsValue(null, "other"));
+    }
+
+    @Test
+    public void get_nested_component_value()
+    {
+        String value = "FIELD-VALUE";
+
+        PersistentFieldChange change = new PersistentFieldChangeImpl("foo.bar", "field", value);
+        Collection<PersistentFieldChange> changes = Arrays.asList(change);
+
+        PersistentFieldBundle bundle = new PersistentFieldBundleImpl(changes);
+
+        assertTrue(bundle.containsValue("foo.bar", "field"));
+
+        assertSame(bundle.getValue("foo.bar", "field"), value);
+
+        assertFalse(bundle.containsValue("foo.bar", "other"));
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,131 @@
+// Copyright 2006 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 static org.apache.tapestry.util.CollectionFactory.newList;
+import static org.apache.tapestry.util.CollectionFactory.newMap;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.services.PersistentFieldBundle;
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.apache.tapestry.services.PersistentFieldManager;
+import org.apache.tapestry.services.PersistentFieldStrategy;
+import org.apache.tapestry.util.CollectionFactory;
+import org.testng.annotations.Test;
+
+public class PersistentFieldManagerImplTest extends InternalBaseTestCase
+{
+    @Test
+    public void post_change_with_unknown_strategy()
+    {
+        PersistentFieldStrategy strat1 = newPersistentFieldStrategy();
+        PersistentFieldStrategy strat2 = newPersistentFieldStrategy();
+
+        Map<String, PersistentFieldStrategy> strategies = CollectionFactory.newMap();
+        strategies.put("foo", strat1);
+        strategies.put("bar", strat2);
+
+        replay();
+
+        PersistentFieldManager manager = new PersistentFieldManagerImpl(strategies);
+
+        try
+        {
+            manager.postChange("foo.Bar", null, "field", "braveheart", null);
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertEquals(
+                    ex.getMessage(),
+                    "\'braveheart\' is not a defined persistent strategy.  Defined stategies: bar, foo.");
+        }
+
+        verify();
+    }
+
+    @Test
+    public void post_change()
+    {
+        PersistentFieldStrategy strat = newPersistentFieldStrategy();
+
+        Map<String, PersistentFieldStrategy> strategies = CollectionFactory.newMap();
+        strategies.put("foo", strat);
+
+        Object value = new Object();
+
+        strat.postChange("foo.Bar", "nested", "field", value);
+
+        replay();
+
+        PersistentFieldManager manager = new PersistentFieldManagerImpl(strategies);
+
+        manager.postChange("foo.Bar", "nested", "field", "foo", value);
+
+        verify();
+    }
+
+    private PersistentFieldStrategy newPersistentFieldStrategy()
+    {
+        return newMock(PersistentFieldStrategy.class);
+    }
+
+    @Test
+    public void gather_changes()
+    {
+        Object value1 = new Object();
+        Object value2 = new Object();
+
+        PersistentFieldStrategy strat1 = newPersistentFieldStrategy();
+
+        Collection<PersistentFieldChange> changes1 = newList();
+        changes1.add(new PersistentFieldChangeImpl("component", "field1", value1));
+
+        PersistentFieldStrategy strat2 = newPersistentFieldStrategy();
+
+        Collection<PersistentFieldChange> changes2 = newList();
+        changes2.add(new PersistentFieldChangeImpl("component", "field2", value2));
+
+        // We don't know the exact order the strategies will be ordered in the map,
+        // so we can't guarantee the order the strategies will be invoked.
+
+        getMocksControl().checkOrder(false);
+
+        strat1.gatherFieldChanges("foo.Bar");
+        setReturnValue(changes1);
+
+        strat2.gatherFieldChanges("foo.Bar");
+        setReturnValue(changes2);
+
+        replay();
+
+        Map<String, PersistentFieldStrategy> strategies = newMap();
+
+        strategies.put("alpha", strat1);
+        strategies.put("beta", strat2);
+
+        PersistentFieldManager manager = new PersistentFieldManagerImpl(strategies);
+
+        PersistentFieldBundle bundle = manager.gatherChanges("foo.Bar");
+
+        assertSame(bundle.getValue("component", "field1"), value1);
+        assertSame(bundle.getValue("component", "field2"), value2);
+
+        verify();
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,124 @@
+// Copyright 2006 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 java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.apache.tapestry.services.WebRequest;
+import org.apache.tapestry.services.WebSession;
+import org.testng.annotations.Test;
+
+public class SessionPersistentFieldStrategyTest extends InternalBaseTestCase
+{
+    @Test
+    public void post_change_to_root_component()
+    {
+        WebSession session = newWebSession();
+        WebRequest request = newWebRequest();
+
+        train_getSession(request, true, session);
+
+        session.setAttribute("state:foo.Bar::field", "VALUE");
+
+        replay();
+
+        SessionPersistentFieldStrategy strategy = new SessionPersistentFieldStrategy(request);
+
+        strategy.postChange("foo.Bar", null, "field", "VALUE");
+
+        verify();
+    }
+
+    @Test
+    public void post_change_to_nested_component()
+    {
+        WebSession session = newWebSession();
+        WebRequest request = newWebRequest();
+
+        train_getSession(request, true, session);
+
+        session.setAttribute("state:foo.Bar:fee.fum:field", "VALUE");
+
+        replay();
+
+        SessionPersistentFieldStrategy strategy = new SessionPersistentFieldStrategy(request);
+
+        strategy.postChange("foo.Bar", "fee.fum", "field", "VALUE");
+
+        verify();
+    }
+
+    @Test
+    public void gather_changes_with_no_session()
+    {
+        WebRequest request = newWebRequest();
+
+        train_getSession(request, false, null);
+
+        replay();
+
+        SessionPersistentFieldStrategy strategy = new SessionPersistentFieldStrategy(request);
+
+        Collection<PersistentFieldChange> changes = strategy.gatherFieldChanges("foo.Bar");
+
+        assertTrue(changes.isEmpty());
+
+        verify();
+    }
+
+    @Test
+    public void gather_changes_with_active_session()
+    {
+        WebSession session = newWebSession();
+        WebRequest request = newWebRequest();
+
+        train_getSession(request, false, session);
+        train_getAttributeNames(
+                session,
+                "state:foo.Bar:",
+                "state:foo.Bar::root",
+                "state:foo.Bar:nested:down");
+
+        train_getAttribute(session, "state:foo.Bar::root", "ROOT");
+        train_getAttribute(session, "state:foo.Bar:nested:down", "DOWN");
+
+        replay();
+
+        SessionPersistentFieldStrategy stategy = new SessionPersistentFieldStrategy(request);
+
+        Collection<PersistentFieldChange> changes = stategy.gatherFieldChanges("foo.Bar");
+
+        assertEquals(changes.size(), 2);
+
+        Iterator<PersistentFieldChange> i = changes.iterator();
+
+        PersistentFieldChange change1 = i.next();
+
+        assertEquals(change1.getComponentId(), "");
+        assertEquals(change1.getFieldName(), "root");
+        assertEquals(change1.getValue(), "ROOT");
+
+        PersistentFieldChange change2 = i.next();
+
+        assertEquals(change2.getComponentId(), "nested");
+        assertEquals(change2.getFieldName(), "down");
+        assertEquals(change2.getValue(), "DOWN");
+
+        verify();
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WebRequestImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WebRequestImplTest.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WebRequestImplTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WebRequestImplTest.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,62 @@
+// Copyright 2006 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 javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.services.WebRequest;
+import org.apache.tapestry.services.WebSession;
+import org.testng.annotations.Test;
+
+public class WebRequestImplTest extends InternalBaseTestCase
+{
+    @Test
+    public void get_session_doesnt_exist()
+    {
+        HttpServletRequest sr = newHttpServletRequest();
+
+        train_getSession(sr, false, null);
+
+        replay();
+
+        WebRequest request = new WebRequestImpl(sr);
+
+        assertNull(request.getSession(false));
+
+        verify();
+    }
+
+    @Test
+    public void force_session_create()
+    {
+        HttpServletRequest sr = newHttpServletRequest();
+        HttpSession ss = newHttpSession();
+
+        train_getSession(sr, true, ss);
+
+        train_getAttribute(ss, "foo", "bar");
+
+        replay();
+
+        WebRequest request = new WebRequestImpl(sr);
+        WebSession session = request.getSession(true);
+
+        assertEquals(session.getAttribute("foo"), "bar");
+
+        verify();
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WebSessionImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WebSessionImplTest.java?view=auto&rev=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WebSessionImplTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/WebSessionImplTest.java Wed Oct 18 22:20:00 2006
@@ -0,0 +1,64 @@
+// Copyright 2006 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 java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpSession;
+
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.services.WebSession;
+import org.testng.annotations.Test;
+
+public class WebSessionImplTest extends InternalBaseTestCase
+{
+    @Test
+    public void get_attribute_names()
+    {
+        Enumeration e = Collections.enumeration(Arrays.asList("fred", "barney"));
+        HttpSession hs = newHttpSession();
+
+        hs.getAttributeNames();
+        setReturnValue(e);
+
+        replay();
+
+        WebSession session = new WebSessionImpl(hs);
+
+        assertEquals(session.getAttributeNames(), Arrays.asList("barney", "fred"));
+
+        verify();
+    }
+
+    @Test
+    public void get_attribute_names_by_prefix()
+    {
+        Enumeration e = Collections.enumeration(Arrays.asList("fred", "barney", "fanny"));
+        HttpSession hs = newHttpSession();
+
+        hs.getAttributeNames();
+        setReturnValue(e);
+
+        replay();
+
+        WebSession session = new WebSessionImpl(hs);
+
+        assertEquals(session.getAttributeNames("f"), Arrays.asList("fanny", "fred"));
+
+        verify();
+    }
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/PageImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/PageImplTest.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/PageImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/PageImplTest.java Wed Oct 18 22:20:00 2006
@@ -20,9 +20,6 @@
 import org.apache.tapestry.runtime.PageLifecycleListener;
 import org.testng.annotations.Test;
 
-/**
- * 
- */
 public class PageImplTest extends InternalBaseTestCase
 {
     private final Locale _locale = Locale.ENGLISH;
@@ -36,7 +33,7 @@
 
         replay();
 
-        Page page = new PageImpl(PAGE_NAME, _locale, null);
+        Page page = new PageImpl(PAGE_NAME, _locale, null, null);
 
         assertNull(page.getRootElement());
 
@@ -60,7 +57,7 @@
 
         replay();
 
-        Page page = new PageImpl(PAGE_NAME, _locale, null);
+        Page page = new PageImpl(PAGE_NAME, _locale, null, null);
 
         page.addLifecycleListener(listener1);
         page.addLifecycleListener(listener2);
@@ -82,7 +79,7 @@
 
         replay();
 
-        Page page = new PageImpl(PAGE_NAME, _locale, null);
+        Page page = new PageImpl(PAGE_NAME, _locale, null, null);
 
         page.addLifecycleListener(listener1);
         page.addLifecycleListener(listener2);
@@ -108,7 +105,7 @@
 
         replay();
 
-        Page page = new PageImpl(PAGE_NAME, _locale, null);
+        Page page = new PageImpl(PAGE_NAME, _locale, null, null);
 
         page.addLifecycleListener(listener1);
         page.addLifecycleListener(listener2);

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/EventHandlerTarget.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/EventHandlerTarget.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/EventHandlerTarget.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/EventHandlerTarget.java Wed Oct 18 22:20:00 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 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.transform.pages;
 
 import org.apache.tapestry.annotations.OnEvent;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/TargetObjectSubclass.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/TargetObjectSubclass.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/TargetObjectSubclass.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/TargetObjectSubclass.java Wed Oct 18 22:20:00 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 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.transform.pages;
 
 /**

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/InternalUtilsTest.java Wed Oct 18 22:20:00 2006
@@ -14,12 +14,14 @@
 
 package org.apache.tapestry.internal.util;
 
+import static org.apache.tapestry.internal.util.InternalUtils.toList;
 import static org.testng.Assert.assertEquals;
 
 import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Enumeration;
 import java.util.List;
 
 import org.testng.annotations.DataProvider;
@@ -103,4 +105,14 @@
         { "$_$__$__$_$___$_$_$_$$name$", "name$" } };
     }
 
+    @Test
+    public void enumeration_to_list()
+    {
+        List<String> input = Arrays.asList("wilma", "fred", "barney");
+        Enumeration e = Collections.enumeration(input);
+
+        List<String> output = toList(e);
+
+        assertEquals(output, Arrays.asList("barney", "fred", "wilma"));
+    }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/StaticModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/StaticModule.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/StaticModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/StaticModule.java Wed Oct 18 22:20:00 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 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.ioc;
 
 import java.util.Collection;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/util/StrategyRegistryTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/util/StrategyRegistryTest.java?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/util/StrategyRegistryTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/util/StrategyRegistryTest.java Wed Oct 18 22:20:00 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 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.util;
 
 import static org.apache.tapestry.util.CollectionFactory.newMap;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/resources/log4j.properties?view=diff&rev=465496&r1=465495&r2=465496
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/resources/log4j.properties (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/resources/log4j.properties Wed Oct 18 22:20:00 2006
@@ -21,6 +21,7 @@
 log4j.appender.A1.layout=org.apache.log4j.PatternLayout
 log4j.appender.A1.layout.ConversionPattern=[%p] %c{1} %m%n
 
+log4j.category.org.apache.tapestry.TapestryFilter=info
 log4j.category.org.apache.tapestry=error
 log4j.category.tapestry=error
 log4j.category.tapestry.ioc.ClassFactory=error