Author: hlship
Date: Tue Feb  6 11:54:40 2007
New Revision: 504259

URL: http://svn.apache.org/viewvc?view=rev&rev=504259
Log:
Add annotations for the page load, page attach and page detach events.
Add a worker to connect the events to component methods.
Use the TypeCoercer to convert context values in URLs to strings for inclusion 
in the path portion of the URL.
Allow final fields to be treated as if they were @Retain.

Added:
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageAttached.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageDetached.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageLoaded.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLifecycleAnnotationWorker.java
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/lifecycle.apt
    
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/PageLoadedDemo.html
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/PageLoadedDemo.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/CheckFieldType.java
Removed:
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingAnnotationProvider.java
Modified:
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkImpl.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLinkHandler.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLinkHandlerImpl.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/UnclaimedFieldWorker.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
    
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/pagelevel/PageTester.java
    
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/component-classes.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml
    tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInvocationTest.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/LinkFactoryImplTest.java
    
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/UnclaimedFieldWorkerTest.java

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageAttached.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageAttached.java?view=auto&rev=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageAttached.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageAttached.java
 Tue Feb  6 11:54:40 2007
@@ -0,0 +1,39 @@
+// 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.annotations;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Method annotation used for methods that should be invoked when the page is 
first attached to a
+ * request. This is useful for initializations that should occur on each 
request that involves the
+ * page. Often, such initializations will be balanced by cleanups when the 
page is detached.
+ * <p>
+ * PageAttached methods should take no parameters and return void. They must 
either have this
+ * annotation, or be named "pageAttached".
+ * 
+ * @see PageDetached
+ */
[EMAIL PROTECTED](METHOD)
[EMAIL PROTECTED](RUNTIME)
[EMAIL PROTECTED]
+public @interface PageAttached {
+
+}

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageDetached.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageDetached.java?view=auto&rev=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageDetached.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageDetached.java
 Tue Feb  6 11:54:40 2007
@@ -0,0 +1,38 @@
+// 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.annotations;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Method annotation used for methods that should be invoked when the page is 
detached at the end of
+ * a request, before it is returned to the page pool for later reuse.
+ * <p>
+ * PageDetached methods should take no parameters and return void. They must 
either have this
+ * annotation, or be named "pageDetached".
+ * 
+ * @see PageAttached
+ */
[EMAIL PROTECTED](METHOD)
[EMAIL PROTECTED](RUNTIME)
[EMAIL PROTECTED]
+public @interface PageDetached {
+
+}

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageLoaded.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageLoaded.java?view=auto&rev=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageLoaded.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/PageLoaded.java
 Tue Feb  6 11:54:40 2007
@@ -0,0 +1,37 @@
+// 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.annotations;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Method annotation used for methods that should be invoked once the page is 
fully loaded. This is
+ * useful for one-time component initializations that can't be done at 
instantance initialzation
+ * time, such as refrerences to embedded components or blocks.
+ * <p>
+ * PageLoaded methods should take no parameters and return void. They must 
either have this
+ * annotation, or be named "pageLoaded".
+ */
[EMAIL PROTECTED](METHOD)
[EMAIL PROTECTED](RUNTIME)
[EMAIL PROTECTED]
+public @interface PageLoaded {
+
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
 Tue Feb  6 11:54:40 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -31,13 +31,13 @@
  */
 public class ComponentInvocation
 {
-    private final Object[] _context;
+    private final String[] _context;
 
     private Map<String, String> _parameters;
 
     private InvocationTarget _target;
 
-    public ComponentInvocation(InvocationTarget target, Object[] context)
+    public ComponentInvocation(InvocationTarget target, String[] context)
     {
         _target = target;
         _context = context;
@@ -102,12 +102,12 @@
 
             // TODO: Need to encode this for URLs? What if the string contains 
slashes, etc.?
 
-            builder.append(id.toString());
+            builder.append(id);
         }
         return builder.toString();
     }
 
-    public Object[] getContext()
+    public String[] getContext()
     {
         return _context;
     }

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java
 Tue Feb  6 11:54:40 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
 Tue Feb  6 11:54:40 2007
@@ -970,6 +970,20 @@
         return type.getName();
     }
 
+    public int getFieldModifiers(String fieldName)
+    {
+        failIfFrozen();
+
+        try
+        {
+            return _ctClass.getDeclaredField(fieldName).getModifiers();
+        }
+        catch (NotFoundException ex)
+        {
+            throw new RuntimeException(ex);
+        }
+    }
+
     private CtClass getFieldCtType(String fieldName)
     {
         try

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
 Tue Feb  6 11:54:40 2007
@@ -517,12 +517,19 @@
 
     /** Service used to create links for components and pages. */
     public LinkFactory buildLinkFactory(@InjectService("ContextPathSource")
-    ContextPathSource contextPathSource, @InjectService("URLEncoder")
-    URLEncoder encoder, @InjectService("ComponentInvocationMap")
-    ComponentInvocationMap componentInvocationMap)
+    ContextPathSource contextPathSource,
+
+    @InjectService("URLEncoder")
+    URLEncoder encoder,
+
+    @InjectService("ComponentInvocationMap")
+    ComponentInvocationMap componentInvocationMap,
+
+    @Inject("infrastructure:TypeCoercer")
+    TypeCoercer typeCoercer)
     {
         return new LinkFactoryImpl(contextPathSource, encoder, 
_componentClassResolver,
-                componentInvocationMap, _pageCache);
+                componentInvocationMap, _pageCache, typeCoercer);
     }
 
     public ContextPathSource buildContextPathSource()

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java
 Tue Feb  6 11:54:40 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
 import org.apache.tapestry.internal.structure.ComponentPageElement;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.ioc.internal.util.Defense;
+import org.apache.tapestry.ioc.services.TypeCoercer;
 import org.apache.tapestry.ioc.util.StrategyRegistry;
 import org.apache.tapestry.runtime.Component;
 import org.apache.tapestry.services.ComponentClassResolver;
@@ -44,6 +45,8 @@
 
     private final RequestPageCache _pageCache;
 
+    private final TypeCoercer _typeCoercer;
+
     private final List<LinkFactoryListener> _listeners = newThreadSafeList();
 
     private final StrategyRegistry<PassivateContextHandler> _registry;
@@ -55,13 +58,15 @@
 
     public LinkFactoryImpl(ContextPathSource contextPathSource, URLEncoder 
encoder,
             ComponentClassResolver componentClassResolver,
-            ComponentInvocationMap componentInvocationMap, RequestPageCache 
pageCache)
+            ComponentInvocationMap componentInvocationMap, RequestPageCache 
pageCache,
+            TypeCoercer typeCoercer)
     {
         _contextPathSource = contextPathSource;
         _encoder = encoder;
         _componentClassResolver = componentClassResolver;
         _componentInvocationMap = componentInvocationMap;
         _pageCache = pageCache;
+        _typeCoercer = typeCoercer;
 
         Map<Class, PassivateContextHandler> registrations = newMap();
 
@@ -113,7 +118,10 @@
 
         ActionLinkTarget target = new ActionLinkTarget(action, 
logicalPageName, component
                 .getNestedId());
-        ComponentInvocation invocation = new ComponentInvocation(target, 
context);
+
+        String[] contextStrings = toContextStrings(context);
+
+        ComponentInvocation invocation = new ComponentInvocation(target, 
contextStrings);
 
         Link link = new LinkImpl(_encoder, 
_contextPathSource.getContextPath(), invocation, forForm);
 
@@ -154,7 +162,8 @@
         rootElement.triggerEvent(TapestryConstants.PASSIVATE_EVENT, null, 
handler);
 
         PageLinkTarget target = new PageLinkTarget(logicalPageName);
-        ComponentInvocation invocation = new ComponentInvocation(target, 
context.toArray());
+        ComponentInvocation invocation = new ComponentInvocation(target, 
toContextStrings(context
+                .toArray()));
 
         Link link = new LinkImpl(_encoder, 
_contextPathSource.getContextPath(), invocation, false);
 
@@ -166,6 +175,19 @@
         // TODO: query parameter for case where active page != component page.
 
         return link;
+    }
+
+    private String[] toContextStrings(Object[] context)
+    {
+        if (context == null)
+            return new String[0];
+
+        String[] result = new String[context.length];
+
+        for (int i = 0; i < context.length; i++)
+            result[i] = _typeCoercer.coerce(context[i], String.class);
+
+        return result;
     }
 
     public Link createPageLink(String pageName)

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkImpl.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkImpl.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LinkImpl.java
 Tue Feb  6 11:54:40 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@
     public LinkImpl(URLEncoder encoder, String contextPath, String targetPath, 
boolean forForm)
     {
         this(encoder, contextPath, new ComponentInvocation(new 
OpaqueConstantTarget(targetPath),
-                new Object[0]), forForm);
+                new String[0]), forForm);
     }
 
     public LinkImpl(URLEncoder encoder, String contextPath, 
ComponentInvocation invocation,

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLifecycleAnnotationWorker.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLifecycleAnnotationWorker.java?view=auto&rev=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLifecycleAnnotationWorker.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLifecycleAnnotationWorker.java
 Tue Feb  6 11:54:40 2007
@@ -0,0 +1,77 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import java.lang.annotation.Annotation;
+
+import org.apache.tapestry.internal.util.MethodInvocationBuilder;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassTransformWorker;
+import org.apache.tapestry.services.MethodFilter;
+import org.apache.tapestry.services.MethodSignature;
+
+/**
+ * Similar to [EMAIL PROTECTED] ComponentLifecycleMethodWorker} but applies to 
annotations/methods related to
+ * the overall page lifecycle.
+ */
+public class PageLifecycleAnnotationWorker implements 
ComponentClassTransformWorker
+{
+    private final Class<? extends Annotation> _methodAnnotationClass;
+
+    private final MethodSignature _lifecycleMethodSignature;
+
+    private final String _methodAlias;
+
+    private final MethodInvocationBuilder _invocationBuilder = new 
MethodInvocationBuilder();
+
+    public PageLifecycleAnnotationWorker(final Class<? extends Annotation> 
methodAnnotationClass,
+            final MethodSignature lifecycleMethodSignature, final String 
methodAlias)
+    {
+        _methodAnnotationClass = methodAnnotationClass;
+        _lifecycleMethodSignature = lifecycleMethodSignature;
+        _methodAlias = methodAlias;
+    }
+
+    public void transform(final ClassTransformation transformation, 
MutableComponentModel model)
+    {
+        MethodFilter filter = new MethodFilter()
+        {
+            public boolean accept(MethodSignature signature)
+            {
+                if (signature.getMethodName().equals(_methodAlias))
+                    return true;
+
+                return transformation.getMethodAnnotation(signature, 
_methodAnnotationClass) != null;
+            }
+        };
+
+        // Did this they easy way, because I doubt there will be more than one 
signature.
+        // If I expected lots of signatures, I'd build up a BodyBuilder in the 
loop and extend the
+        // method outside the loop.
+
+        for (MethodSignature signature : transformation.findMethods(filter))
+        {
+            // TODO: Filter out the non-void methods (with a non-fatal 
warning/error?) For the
+            // moment, we just invoke the method anyway, and ignore the 
result. Also, MethodInvocationBuilder
+            // is very forgiving (and silent) about unexpected parameters 
(passing null/0/false).
+
+            String body = _invocationBuilder.buildMethodInvocation(signature, 
transformation);
+
+            transformation.extendMethod(_lifecycleMethodSignature, body + ";");
+        }
+    }
+
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLinkHandler.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLinkHandler.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLinkHandler.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLinkHandler.java
 Tue Feb  6 11:54:40 2007
@@ -21,7 +21,7 @@
  */
 public interface PageLinkHandler
 {
-    void handle(String logicalPageName, Object[] context, PageRenderer 
renderer);
+    void handle(String logicalPageName, String[] context, PageRenderer 
renderer);
 
     void handle(ComponentInvocation invocation, PageRenderer renderer);
 }

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLinkHandlerImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLinkHandlerImpl.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLinkHandlerImpl.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLinkHandlerImpl.java
 Tue Feb  6 11:54:40 2007
@@ -31,7 +31,7 @@
         _cache = cache;
     }
 
-    public void handle(String logicalPageName, Object[] context, PageRenderer 
renderer)
+    public void handle(String logicalPageName, String[] context, PageRenderer 
renderer)
     {
         PageLinkTarget target = new PageLinkTarget(logicalPageName);
         ComponentInvocation invocation = new ComponentInvocation(target, 
context);

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java
 Tue Feb  6 11:54:40 2007
@@ -66,7 +66,7 @@
             {
                 // TODO: UUDecode the strings in the context?
 
-                Object[] context = atEnd ? new Object[0] : 
path.substring(nextslashx + 1)
+                String[] context = atEnd ? new String[0] : 
path.substring(nextslashx + 1)
                         .split("/");
 
                 PageRenderer renderer = new PageRenderer()

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/UnclaimedFieldWorker.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/UnclaimedFieldWorker.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/UnclaimedFieldWorker.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/UnclaimedFieldWorker.java
 Tue Feb  6 11:54:40 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -26,7 +26,9 @@
 
 /**
  * Designed to be just about the last worker in the pipeline. Its job is to 
add cleanup code that
- * restores transient fields back to their initial (null) value.
+ * restores transient fields back to their initial (null) value. Fields that 
have been previously
+ * [EMAIL PROTECTED] ClassTransformation#claimField(String, Object) claimed} 
are ignored, as are fields that
+ * are final.
  */
 public final class UnclaimedFieldWorker implements 
ComponentClassTransformWorker
 {
@@ -43,6 +45,11 @@
 
     private void transformField(String fieldName, ClassTransformation 
transformation)
     {
+        int modifiers = transformation.getFieldModifiers(fieldName);
+
+        if (Modifier.isFinal(modifiers))
+            return;
+
         String type = transformation.getFieldType(fieldName);
 
         String defaultFieldName = transformation.addField(Modifier.PRIVATE, 
type, fieldName

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
 Tue Feb  6 11:54:40 2007
@@ -58,7 +58,8 @@
     String newMemberName(String suggested);
 
     /**
-     * Generates a list of the names of declared instance fields that have the 
indicated annotation.
+     * Generates a list of the names of declared instance fields that have the 
indicated annotation. Non-private and static
+     * fields are ignored.
      * Only the names of private instance fields are returned. Any
      * [EMAIL PROTECTED] #claimField(String, Object) claimed} fields are 
excluded.
      */
@@ -89,7 +90,8 @@
     List<MethodSignature> findMethods(MethodFilter filter);
 
     /**
-     * Finds all unclaimed fields matched by the provided filter.
+     * Finds all unclaimed fields matched by the provided filter.  Only 
considers
+     * unclaimed, private, instance fields.
      * 
      * @param filter
      *            passed each field name and field type
@@ -311,4 +313,7 @@
      * concerning the class being transformed may be logged.
      */
     Log getLog();
+
+    /** Returns the modifiers for the named field. */
+    int getFieldModifiers(String fieldName);
 }

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=504259&r1=504258&r2=504259
==============================================================================
--- 
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
 Tue Feb  6 11:54:40 2007
@@ -39,6 +39,9 @@
 import org.apache.tapestry.annotations.BeginRender;
 import org.apache.tapestry.annotations.CleanupRender;
 import org.apache.tapestry.annotations.InjectPage;
+import org.apache.tapestry.annotations.PageAttached;
+import org.apache.tapestry.annotations.PageDetached;
+import org.apache.tapestry.annotations.PageLoaded;
 import org.apache.tapestry.annotations.SetupRender;
 import org.apache.tapestry.beaneditor.Validate;
 import org.apache.tapestry.dom.DefaultMarkupModel;
@@ -106,6 +109,7 @@
 import org.apache.tapestry.internal.services.MixinWorker;
 import 
org.apache.tapestry.internal.services.ObjectComponentEventResultProcessor;
 import org.apache.tapestry.internal.services.OnEventWorker;
+import org.apache.tapestry.internal.services.PageLifecycleAnnotationWorker;
 import org.apache.tapestry.internal.services.PageLinkHandler;
 import org.apache.tapestry.internal.services.PageLinkHandlerImpl;
 import org.apache.tapestry.internal.services.PageRenderDispatcher;
@@ -715,14 +719,31 @@
      */
     public static void contributeComponentClassTransformWorker(
             OrderedConfiguration<ComponentClassTransformWorker> configuration,
-            ServiceLocator locator, 
@InjectService("tapestry.ioc.MasterObjectProvider")
-            ObjectProvider objectProvider, @InjectService("InjectionProvider")
-            InjectionProvider injectionProvider, @InjectService("Environment")
-            Environment environment, 
@InjectService("tapestry.ComponentClassResolver")
-            ComponentClassResolver resolver, 
@InjectService("tapestry.internal.RequestPageCache")
-            RequestPageCache requestPageCache, 
@Inject("infrastructure:AssetSource")
-            AssetSource assetSource, @Inject("infrastructure:BindingSource")
-            BindingSource bindingsource, 
@Inject("infrastructure:ApplicationStateManager")
+
+            ServiceLocator locator,
+
+            @InjectService("tapestry.ioc.MasterObjectProvider")
+            ObjectProvider objectProvider,
+
+            @InjectService("InjectionProvider")
+            InjectionProvider injectionProvider,
+
+            @Inject("infrastructure:Environment")
+            Environment environment,
+
+            @Inject("infrastructure:ComponentClassResolver")
+            ComponentClassResolver resolver,
+
+            @InjectService("tapestry.internal.RequestPageCache")
+            RequestPageCache requestPageCache,
+
+            @Inject("infrastructure:AssetSource")
+            AssetSource assetSource,
+
+            @Inject("infrastructure:BindingSource")
+            BindingSource bindingsource,
+
+            @Inject("infrastructure:ApplicationStateManager")
             ApplicationStateManager applicationStateManager)
     {
         // TODO: Proper scheduling of all of this. Since a given field or 
method should
@@ -785,6 +806,25 @@
         add(configuration, TransformConstants.AFTER_RENDER_SIGNATURE, 
AfterRender.class, true);
         add(configuration, TransformConstants.CLEANUP_RENDER_SIGNATURE, 
CleanupRender.class, true);
 
+        // Ideally, these should be ordered pretty late in the process to make 
sure there are no side effects
+        // with other workers that do work inside the page lifecycle methods.
+        
+        add(
+                configuration,
+                PageLoaded.class,
+                TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE,
+                "pageLoaded");
+        add(
+                configuration,
+                PageAttached.class,
+                TransformConstants.CONTAINING_PAGE_DID_ATTACH_SIGNATURE,
+                "pageAttached");
+        add(
+                configuration,
+                PageDetached.class,
+                TransformConstants.CONTAINING_PAGE_DID_DETACH_SIGNATURE,
+                "pageDetached");
+
         configuration.add("Retain", new RetainWorker());
         configuration.add("Persist", new PersistWorker());
         configuration.add("UnclaimedField", new UnclaimedFieldWorker(), 
"after:*.*");
@@ -799,6 +839,18 @@
 
         configuration.add(name, new ComponentLifecycleMethodWorker(signature, 
annotationClass,
                 reverse));
+    }
+
+    private static void 
add(OrderedConfiguration<ComponentClassTransformWorker> configuration,
+            Class<? extends Annotation> annotationClass, MethodSignature 
lifecycleMethodSignature,
+            String methodAlias)
+    {
+        ComponentClassTransformWorker worker = new 
PageLifecycleAnnotationWorker(annotationClass,
+                lifecycleMethodSignature, methodAlias);
+
+        String name = IOCUtilities.toSimpleId(annotationClass.getName());
+
+        configuration.add(name, worker);
     }
 
     @Lifecycle("perthread")

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/pagelevel/PageTester.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/pagelevel/PageTester.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/pagelevel/PageTester.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/pagelevel/PageTester.java
 Tue Feb  6 11:54:40 2007
@@ -181,7 +181,7 @@
      */
     public Document renderPage(String pageName)
     {
-        return invoke(new ComponentInvocation(new PageLinkTarget(pageName), 
new Object[0]));
+        return invoke(new ComponentInvocation(new PageLinkTarget(pageName), 
new String[0]));
     }
 
     /**

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=504259&r1=504258&r2=504259
==============================================================================
--- 
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 
Tue Feb  6 11:54:40 2007
@@ -128,18 +128,26 @@
   
   Be aware that you will need to provide getter and setter methods to access 
your classes'
   instance variables. Tapestry <does not> do this automatically.
-  
-  
+    
   
 Transient Instance Variables
 
   Unless an instance variable is decorated with an annotation, it will be a
   <transient> instance variable. This means that its value resets to its
   default value
-  at the end of reach request.
+  at the end of reach request (when the
+  {{{lifecycle.html}page is detached from the request}}.
+  
+  If you have a variable that can keep its value between requests and you 
would like
+  to defeat that reset logic, then you should attach a
+  {{{../apidocs/org/apache/tapestry/annotations/Retain.html}Retain}} 
annotation to the field.  You should take
+  care that no client-specific data is stored into such a field, since on a 
later request
+  the same page <instance> may be used for a different user. Likewise, on a 
later request for the <same> user,
+  a <different> page instance may be used.
   
+  Use {{{persist.html}persistent fields} to hold information form one request 
to the next.
   
-  <<TODO: Setting an initial value with @OnPageLoad>>
+  Further, final fields are (in fact) final, and will not be reset.
   
 Constructors
 

Added: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/lifecycle.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/lifecycle.apt?view=auto&rev=504259
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/lifecycle.apt 
(added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/lifecycle.apt Tue 
Feb  6 11:54:40 2007
@@ -0,0 +1,37 @@
+ ----
+ Page Lifecycle Methods
+ ----
+ 
+Page Lifecycle Methods
+
+  There are a few situations where it is useful for a component to perform 
some operations, usually some kind of initialization or
+  caching, based on the lifecycle of the page.
+  
+  The page lifecycle is quite simple.  When first needed, a page is loaded.  
Loading a page involves instantitating the components of the page
+  and connecting them together.
+  
+  Once a page is loaded, it is <attached> to the current request.  Remember 
that there will be many threads, each handling its own request.
+  In many cases, there will be multiple copies of the same page attached to 
different requests (and different threads). This is how Tapestry keeps you
+  from worrying about multi-threading issues ... the objects involved in any 
request are reserved to <just> that request (and <just> that thread).
+  
+  At the end of a request, after a response has been sent to the client, the 
page is <detached> from the request.  This is a chance to perform
+  a lot of cleanup of the page, discarding temporary objects (so that they can 
be reclaimed by the garbage collector) and otherwise returning the
+  page to its pristine state.  After detaching, a page is placed into the page 
pool, where it will await reuse for some future request (likely by a completely
+  different user).
+  
+  As with {{{rendering.html}component rendering}}, you have the ability to 
make your components "aware" of these events by identifying methods to be 
invoked.
+  
+  You have the choice of attaching an annotation to a method, or simply naming 
the method correctly.  
+  
+  Page lifecycle methods should take no parameters and return void.
+  
+  The annotations / method names are:
+  
+   * 
{{{../apidocs/org/apache/tapestry/annotations/PageLoaded.html}PageLoaded}} 
annotation, or method name "pageLoaded"
+   
+   * 
{{{../apidocs/org/apache/tapestry/annotations/PageAttached.html}PageAttached}} 
annotation, or method name "pageAttached"
+   
+   * 
{{{../apidocs/org/apache/tapestry/annotations/PageDetached.html}PageDetached}} 
annotation, or method name "pageDetached"
+   
+   
+   
\ 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=504259&r1=504258&r2=504259
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml Tue Feb  6 
11:54:40 2007
@@ -40,11 +40,16 @@
             <item name="Apache" href="http://www.apache.org/"; />
         </links>
 
-        <head>
+
+<!--
+
+This is probably useful but it drives me crazy whenever I reload a page.
+
+         <head>
             <script src="http://www.google-analytics.com/urchin.js"; 
type="text/javascript"></script>
             <script type="text/javascript">_uacct = "UA-400821-1"; 
urchinTracker();</script>
         </head>
-
+ -->
         <menu name="Tapestry Core">
             <item name="Introduction" href="/index.html"/>
             <item name="Upgrade from Tapestry 4" href="/upgrade.html"/>
@@ -56,7 +61,8 @@
             <item name="Component Templates" href="guide/templates.html"/>
             <item name="Component Parameters" href="guide/parameters.html"/>
             <item name="Input Validation" href="guide/validation.html"/>
-            <item name="Component Events" href="guide/event.html"/>
+            <item name="Component Events" href="guide/event.html"/>
+            <item name="Page Lifecycle" href="guide/lifecycle.html"/>
             <item name="Component Mixins" href="guide/mixins.html"/>
             <item name="Localization" href="guide/localization.html"/>
             <item name="Assets" href="guide/assets.html"/>

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/PageLoadedDemo.html
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/PageLoadedDemo.html?view=auto&rev=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/PageLoadedDemo.html
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/PageLoadedDemo.html
 Tue Feb  6 11:54:40 2007
@@ -0,0 +1,9 @@
+<html t:type="Border" 
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
+    
+    <h1>Page Loaded Demo</h1>
+
+    <p>
+        The message: [${message}]
+    </p>    
+
+</html>

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html Tue Feb  6 
11:54:40 2007
@@ -96,6 +96,9 @@
                         <li>
                             <a href="beaneditordemo">BeanEditor Demo</a> -- 
demonstrate the BeanEditor mega-component
                         </li>
+                        <li>
+                        <a href="pageloadeddemo">PageLoaded Demo</a> -- shows 
that page lifecycle methods are invoked
+                        </li>
                     </ul>
                 </td>
             </tr>

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
 Tue Feb  6 11:54:40 2007
@@ -740,4 +740,13 @@
 
         assertTextPresent("[Howard]", "[Lewis Ship]", "[1966]", "[MARTIAN]", 
"[true]");
     }
+
+    @Test
+    public void pageloaded_lifecycle_method_invoked()
+    {
+        _selenium.open(BASE_URL);
+        clickAndWait("link=PageLoaded Demo");
+
+        assertTextPresent("[pageLoaded() was invoked.]");
+    }
 }

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/PageLoadedDemo.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/PageLoadedDemo.java?view=auto&rev=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/PageLoadedDemo.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/PageLoadedDemo.java
 Tue Feb  6 11:54:40 2007
@@ -0,0 +1,35 @@
+// 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.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Retain;
+
[EMAIL PROTECTED]
+public class PageLoadedDemo
+{
+    @Retain
+    private String _message;
+
+    void pageLoaded()
+    {
+        _message = "pageLoaded() was invoked.";
+    }
+
+    public String getMessage()
+    {
+        return _message;
+    }
+}

Added: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/CheckFieldType.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/CheckFieldType.java?view=auto&rev=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/CheckFieldType.java
 (added)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/CheckFieldType.java
 Tue Feb  6 11:54:40 2007
@@ -0,0 +1,40 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import java.util.Map;
+
+public class CheckFieldType
+{
+    private boolean _privateField;
+
+    private final Map _map = null;
+
+    public boolean isPrivateField()
+    {
+        return _privateField;
+    }
+
+    public void setPrivateField(boolean privateField)
+    {
+        _privateField = privateField;
+    }
+
+    public Map getMap()
+    {
+        return _map;
+    }
+
+}

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInvocationTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInvocationTest.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInvocationTest.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentInvocationTest.java
 Tue Feb  6 11:54:40 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
     public void no_context()
     {
         ComponentInvocation invocation = new ComponentInvocation(new 
OpaqueConstantTarget("abc"),
-                new Object[0]);
+                new String[0]);
         assertEquals(invocation.buildURI(false), "abc");
         assertEquals(invocation.buildURI(true), "abc");
     }
@@ -32,8 +32,8 @@
     public void context()
     {
         ComponentInvocation invocation = new ComponentInvocation(new 
OpaqueConstantTarget("abc"),
-                new Object[]
-                { "x", 123 });
+                new String[]
+                { "x", "123" });
         assertEquals(invocation.buildURI(false), "abc/x/123");
         assertEquals(invocation.buildURI(true), "abc/x/123");
     }
@@ -42,8 +42,8 @@
     public void parameters()
     {
         ComponentInvocation invocation = new ComponentInvocation(new 
OpaqueConstantTarget("abc"),
-                new Object[]
-                { "x", 123 });
+                new String[]
+                { "x", "123" });
         invocation.addParameter("p1", "foo");
         invocation.addParameter("p2", "bar");
         assertEquals(invocation.buildURI(false), "abc/x/123?p1=foo&p2=bar");

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java
 Tue Feb  6 11:54:40 2007
@@ -248,6 +248,19 @@
     }
 
     @Test
+    public void get_field_modifiers() throws Exception
+    {
+        Log log = newLog();
+
+        replay();
+
+        ClassTransformation ct = 
createClassTransformation(CheckFieldType.class, log);
+
+        assertEquals(ct.getFieldModifiers("_privateField"), Modifier.PRIVATE);
+        assertEquals(ct.getFieldModifiers("_map"), Modifier.PRIVATE + 
Modifier.FINAL);
+    }
+
+    @Test
     public void find_fields_of_type_excludes_claimed_fields() throws Exception
     {
         Log log = newLog();

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=504259&r1=504258&r2=504259
==============================================================================
--- 
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
 Tue Feb  6 11:54:40 2007
@@ -23,11 +23,14 @@
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.internal.test.InternalBaseTestCase;
 import org.apache.tapestry.internal.util.Holder;
+import org.apache.tapestry.ioc.services.TypeCoercer;
 import org.apache.tapestry.services.ComponentClassResolver;
 import org.apache.tapestry.services.Request;
 import org.apache.tapestry.services.Response;
 import org.easymock.EasyMock;
 import org.easymock.IAnswer;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 public class LinkFactoryImplTest extends InternalBaseTestCase
@@ -38,6 +41,20 @@
 
     private static final String PAGE_CLASS_NAME = "foo.pages.sub.MyPage";
 
+    private TypeCoercer _typeCoercer;
+
+    @BeforeClass
+    public void setup()
+    {
+        _typeCoercer = getObject("service:tapestry.ioc.TypeCoercer", 
TypeCoercer.class);
+    }
+
+    @AfterClass
+    public void cleanup()
+    {
+        _typeCoercer = null;
+    }
+
     @Test
     public void action_link_root_context_no_ids()
     {
@@ -147,7 +164,8 @@
 
         replay();
 
-        LinkFactory factory = new LinkFactoryImpl(request, response, resolver, 
map, null);
+        LinkFactory factory = new LinkFactoryImpl(request, response, resolver, 
map, null,
+                _typeCoercer);
         factory.addListener(listener);
 
         Link link = factory.createPageLink(page);
@@ -235,7 +253,8 @@
 
         replay();
 
-        LinkFactory factory = new LinkFactoryImpl(request, response, resolver, 
map, cache);
+        LinkFactory factory = new LinkFactoryImpl(request, response, resolver, 
map, cache,
+                _typeCoercer);
         factory.addListener(listener);
 
         Link link = factory.createPageLink(PAGE_LOGICAL_NAME);
@@ -292,7 +311,8 @@
 
         replay();
 
-        LinkFactory factory = new LinkFactoryImpl(request, response, resolver, 
map, null);
+        LinkFactory factory = new LinkFactoryImpl(request, response, resolver, 
map, null,
+                _typeCoercer);
         factory.addListener(listener);
 
         Link link = factory.createActionLink(element, eventName, false, 
context);

Modified: 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/UnclaimedFieldWorkerTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/UnclaimedFieldWorkerTest.java?view=diff&rev=504259&r1=504258&r2=504259
==============================================================================
--- 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/UnclaimedFieldWorkerTest.java
 (original)
+++ 
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/UnclaimedFieldWorkerTest.java
 Tue Feb  6 11:54:40 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -24,9 +24,6 @@
 import org.apache.tapestry.services.ClassTransformation;
 import org.testng.annotations.Test;
 
-/**
- * 
- */
 public class UnclaimedFieldWorkerTest extends InternalBaseTestCase
 {
     @Test
@@ -52,7 +49,9 @@
 
         train_findUnclaimedFields(ct, "_fred");
 
-        expect(ct.getFieldType("_fred")).andReturn("foo.Bar");
+        train_getFieldModifiers(ct, "_fred", Modifier.PRIVATE);
+
+        train_getFieldType(ct, "_fred", "foo.Bar");
 
         expect(ct.addField(Modifier.PRIVATE, "foo.Bar", 
"_fred_default")).andReturn(
                 "_$fred_default");
@@ -65,5 +64,28 @@
         new UnclaimedFieldWorker().transform(ct, model);
 
         verify();
+    }
+
+    @Test
+    public void final_fields_are_skipped()
+    {
+        ClassTransformation ct = newClassTransformation();
+        MutableComponentModel model = newMutableComponentModel();
+
+        train_findUnclaimedFields(ct, "_fred");
+
+        train_getFieldModifiers(ct, "_fred", Modifier.PRIVATE | 
Modifier.FINAL);
+
+        replay();
+
+        new UnclaimedFieldWorker().transform(ct, model);
+
+        verify();
+    }
+
+    protected final void train_getFieldModifiers(ClassTransformation 
transformation,
+            String fieldName, int modifiers)
+    {
+        
expect(transformation.getFieldModifiers(fieldName)).andReturn(modifiers).atLeastOnce();
     }
 }


Reply via email to