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 2010/01/28 12:35:54 UTC

svn commit: r904043 - in /tapestry/tapestry5/trunk: tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ tapestry-core/src/main/java/org/apache/tapestry5/runtime/ tapes...

Author: hlship
Date: Thu Jan 28 11:35:54 2010
New Revision: 904043

URL: http://svn.apache.org/viewvc?rev=904043&view=rev
Log:
Merge branch 'tap5-993' into trunk

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ReadOnlyFieldValueConduit.java   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/runtime/PageLifecycleAdapter.java   (with props)
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/FieldValueConduit.java   (contents, props changed)
      - copied, changed from r903976, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldValueConduit.java
Removed:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldValueConduit.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformation.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ApplicationStateWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/EnvironmentalWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectPageWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterConduit.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/InternalClassTransformationImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/ApplicationStateWorkerTest.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformation.java?rev=904043&r1=904042&r2=904043&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformation.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformation.java Thu Jan 28 11:35:54 2010
@@ -1,10 +1,10 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2010 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
+// 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,
@@ -38,7 +38,7 @@
 
     /**
      * Called (after {@link #finish()}) to construct an instantiator for the component.
-     *
+     * 
      * @return the component's instantiator
      */
     Instantiator createInstantiator();
@@ -57,13 +57,11 @@
     /**
      * Searchs for an existing injection of an object, returning the name of the protected field into which the value
      * was injected.
-     * <p/>
-     * TODO: Howard sayz: Uggh! At least define a real key (MultiKey is intended for internal use, never part of an
-     * API). Is this necessary?  The cost of re-injection is tiny.
      */
     String searchForPreviousInjection(InjectionKey key);
 
-    InternalClassTransformation createChildTransformation(CtClass childClass, MutableComponentModel childModel);
+    InternalClassTransformation createChildTransformation(CtClass childClass,
+            MutableComponentModel childModel);
 
     /**
      * Returns the parent transformation, or null for a root class.
@@ -71,18 +69,21 @@
     InternalClassTransformation getParentTransformation();
 
     /**
-     * Creates a new method by copying the body of an existing method.  This is part of the scheme for providing method
+     * Creates a new method by copying the body of an existing method. This is part of the scheme for providing method
      * advice.
-     *
-     * @param sourceMethod  method to be copied
-     * @param modifiers     modifiers for the new method
-     * @param newMethodName name of new method to create
+     * 
+     * @param sourceMethod
+     *            method to be copied
+     * @param modifiers
+     *            modifiers for the new method
+     * @param newMethodName
+     *            name of new method to create
      */
     void copyMethod(TransformMethodSignature sourceMethod, int modifiers, String newMethodName);
 
     /**
      * Returns true if the provided signature is a method implemented by the transformed class.
-     *
+     * 
      * @param signature
      * @return true if implemented
      */

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java?rev=904043&r1=904042&r2=904043&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java Thu Jan 28 11:35:54 2010
@@ -37,6 +37,7 @@
 import org.apache.tapestry5.ioc.services.ClassFab;
 import org.apache.tapestry5.ioc.services.ClassFabUtils;
 import org.apache.tapestry5.ioc.services.ClassFactory;
+import org.apache.tapestry5.ioc.services.FieldValueConduit;
 import org.apache.tapestry5.ioc.services.MethodSignature;
 import org.apache.tapestry5.ioc.util.BodyBuilder;
 import org.apache.tapestry5.model.ComponentModel;
@@ -45,7 +46,6 @@
 import org.apache.tapestry5.services.ComponentMethodAdvice;
 import org.apache.tapestry5.services.ComponentValueProvider;
 import org.apache.tapestry5.services.FieldFilter;
-import org.apache.tapestry5.services.FieldValueConduit;
 import org.apache.tapestry5.services.MethodFilter;
 import org.apache.tapestry5.services.TransformField;
 import org.apache.tapestry5.services.TransformMethod;
@@ -158,9 +158,7 @@
 
         private final CtClass fieldType;
 
-        private final String name;
-
-        private final String type;
+        private final String name, type;
 
         private final boolean primitive;
 
@@ -172,6 +170,8 @@
 
         boolean removed;
 
+        String readValueBody, writeValueBody;
+
         TransformFieldImpl(CtField field, boolean added)
         {
             this.field = field;
@@ -232,7 +232,7 @@
                         String
                                 .format(
                                         "Field %s of class %s is already claimed by %s and can not be claimed by %s.",
-                                        getName(), ctClass.getName(), claimTag, tag));
+                                        getName(), getClassName(), claimTag, tag));
 
             claimTag = tag;
         }
@@ -247,6 +247,42 @@
             return field.getModifiers();
         }
 
+        void replaceReadAccess(String methodName)
+        {
+            failIfFrozen();
+
+            if (readValueBody != null)
+                throw new IllegalStateException(String.format(
+                        "Field %s.%s has already had read access replaced.", getClassName(), name));
+
+            // Explicitly reference $0 (aka "this") because of TAPESTRY-1511.
+            // $0 is valid even inside a static method.
+
+            readValueBody = String.format("$_ = $0.%s();", methodName);
+
+            formatter.format("replace read %s: %s();\n\n", name, methodName);
+
+            fieldAccessReplaced = true;
+        }
+
+        void replaceWriteAccess(String methodName)
+        {
+            failIfFrozen();
+
+            if (writeValueBody != null)
+                throw new IllegalStateException(String.format(
+                        "Field %s.%s has already had write access replaces.", getClassName(), name));
+
+            // Explicitly reference $0 (aka "this") because of TAPESTRY-1511.
+            // $0 is valid even inside a static method.
+
+            writeValueBody = String.format("$0.%s($1);", methodName);
+
+            formatter.format("replace write %s: %s();\n\n", name, methodName);
+
+            fieldAccessReplaced = true;
+        }
+
         public void remove()
         {
             if (removed)
@@ -277,6 +313,14 @@
                     conduitProvider));
         }
 
+        public void replaceAccess(FieldValueConduit conduit)
+        {
+            String fieldName = addInjectedFieldUncached(FieldValueConduit.class, name + "$conduit",
+                    conduit);
+
+            replaceAccess(getTransformFieldImpl(fieldName));
+        }
+
         public void replaceAccess(TransformField conduitField)
         {
             failIfFrozen();
@@ -297,7 +341,7 @@
             addMethod(readSig, String
                     .format("return ($r) ((%s) %s.get());", cast, conduitFieldName));
 
-            replaceReadAccess(name, readMethodName);
+            replaceReadAccess(readMethodName);
 
             String writeMethodName = newMemberName("set", name);
 
@@ -307,7 +351,7 @@
 
             addMethod(writeSig, String.format("%s.set(($w) $1);", conduitFieldName));
 
-            replaceWriteAccess(name, writeMethodName);
+            replaceWriteAccess(writeMethodName);
 
             remove();
         }
@@ -386,13 +430,6 @@
 
     private List<Annotation> classAnnotations;
 
-    // Key is field name, value is expression used to replace read access
-
-    private Map<String, String> fieldReadTransforms;
-
-    // Key is field name, value is expression used to replace read access
-    private Map<String, String> fieldWriteTransforms;
-
     /**
      * Contains the assembled Javassist code for the class' default constructor.
      */
@@ -414,6 +451,10 @@
 
     private final CtClassSource classSource;
 
+    // If true, then during finish, it is necessary to search for field replacements
+    // (field reads or writes replaces with method calls).
+    private boolean fieldAccessReplaced;
+
     /**
      * Signature for newInstance() method of Instantiator.
      */
@@ -528,8 +569,6 @@
         fields = null;
 
         classAnnotations = null;
-        fieldReadTransforms = null;
-        fieldWriteTransforms = null;
         constructor = null;
         formatter = null;
     }
@@ -683,16 +722,20 @@
 
     public TransformField getField(String fieldName)
     {
+        return getTransformFieldImpl(fieldName);
+    }
+
+    private TransformFieldImpl getTransformFieldImpl(String fieldName)
+    {
         failIfFrozen();
 
-        TransformField result = fields.get(fieldName);
+        TransformFieldImpl result = fields.get(fieldName);
 
         if (result != null)
             return result;
 
         throw new RuntimeException(String.format("Class %s does not contain a field named '%s'.",
-                ctClass.getName(), fieldName));
-
+                getClassName(), fieldName));
     }
 
     public String newMemberName(String suggested)
@@ -1119,7 +1162,7 @@
             return result;
 
         throw new IllegalArgumentException(String.format("Class %s does not declare method '%s'.",
-                ctClass.getName(), signature));
+                getClassName(), signature));
 
     }
 
@@ -1600,7 +1643,7 @@
             throw new RuntimeException(ex);
         }
 
-        formatter.format("add constructor: %s(", ctClass.getName());
+        formatter.format("add constructor: %s(", getClassName());
 
         for (int i = 0; i < count; i++)
         {
@@ -1662,7 +1705,7 @@
             }
         }; }
 
-        String componentClassName = ctClass.getName();
+        String componentClassName = getClassName();
 
         String name = ClassFabUtils.generateClassName("Instantiator");
 
@@ -1757,7 +1800,7 @@
     {
         if (frozen)
             throw new IllegalStateException("The ClassTransformation instance (for "
-                    + ctClass.getName()
+                    + getClassName()
                     + ") has completed all transformations and may not be further modified.");
     }
 
@@ -1765,7 +1808,7 @@
     {
         if (!frozen)
             throw new IllegalStateException("The ClassTransformation instance (for "
-                    + ctClass.getName() + ") has not yet completed all transformations.");
+                    + getClassName() + ") has not yet completed all transformations.");
     }
 
     public IdAllocator getIdAllocator()
@@ -1864,7 +1907,7 @@
                 methodName, new String[]
                 { fieldType }, null);
 
-        String message = ServicesMessages.readOnlyField(ctClass.getName(), fieldName);
+        String message = ServicesMessages.readOnlyField(getClassName(), fieldName);
 
         String body = String.format("throw new java.lang.RuntimeException(\"%s\");", message);
 
@@ -1880,36 +1923,12 @@
 
     public void replaceReadAccess(String fieldName, String methodName)
     {
-        // Explicitly reference $0 (aka "this") because of TAPESTRY-1511.
-        // $0 is valid even inside a static method.
-
-        String body = String.format("$_ = $0.%s();", methodName);
-
-        if (fieldReadTransforms == null)
-            fieldReadTransforms = CollectionFactory.newMap();
-
-        // TODO: Collisions?
-
-        fieldReadTransforms.put(fieldName, body);
-
-        formatter.format("replace read %s: %s();\n\n", fieldName, methodName);
+        getTransformFieldImpl(fieldName).replaceReadAccess(methodName);
     }
 
     public void replaceWriteAccess(String fieldName, String methodName)
     {
-        // Explicitly reference $0 (aka "this") because of TAPESTRY-1511.
-        // $0 is valid even inside a static method.
-
-        String body = String.format("$0.%s($1);", methodName);
-
-        if (fieldWriteTransforms == null)
-            fieldWriteTransforms = CollectionFactory.newMap();
-
-        // TODO: Collisions?
-
-        fieldWriteTransforms.put(fieldName, body);
-
-        formatter.format("replace write %s: %s();\n\n", fieldName, methodName);
+        getTransformFieldImpl(fieldName).replaceWriteAccess(methodName);
     }
 
     private void performFieldTransformations()
@@ -1917,7 +1936,7 @@
         // If no field transformations have been requested, then we can save ourselves some
         // trouble!
 
-        if (fieldReadTransforms != null || fieldWriteTransforms != null)
+        if (fieldAccessReplaced)
             replaceFieldAccess();
 
         for (TransformFieldImpl tfi : fields.values())
@@ -1931,14 +1950,14 @@
 
     private void replaceFieldAccess()
     {
-        // Provide empty maps here, to make the code in the inner class a tad
-        // easier.
-
-        if (fieldReadTransforms == null)
-            fieldReadTransforms = CollectionFactory.newMap();
+        final Map<String, String> fieldReadTransforms = CollectionFactory.newMap();
+        final Map<String, String> fieldWriteTransforms = CollectionFactory.newMap();
 
-        if (fieldWriteTransforms == null)
-            fieldWriteTransforms = CollectionFactory.newMap();
+        for (TransformFieldImpl tfi : fields.values())
+        {
+            putIfNotNull(fieldReadTransforms, tfi.name, tfi.readValueBody);
+            putIfNotNull(fieldWriteTransforms, tfi.name, tfi.writeValueBody);
+        }
 
         ExprEditor editor = new ExprEditor()
         {
@@ -2003,6 +2022,12 @@
         formatter.format("\n");
     }
 
+    private static <K, V> void putIfNotNull(Map<K, V> map, K key, V value)
+    {
+        if (value != null)
+            map.put(key, value);
+    }
+
     public Class toClass(String type)
     {
         String finalType = TransformUtils.getWrapperTypeName(type);

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ApplicationStateWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ApplicationStateWorker.java?rev=904043&r1=904042&r2=904043&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ApplicationStateWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ApplicationStateWorker.java Thu Jan 28 11:35:54 2010
@@ -1,10 +1,10 @@
-// Copyright 2007, 2008 The Apache Software Foundation
+// Copyright 2007, 2008, 2010 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
+// 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,
@@ -14,21 +14,20 @@
 
 package org.apache.tapestry5.internal.transform;
 
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
 import org.apache.tapestry5.annotations.ApplicationState;
 import org.apache.tapestry5.annotations.SessionState;
 import org.apache.tapestry5.internal.services.ComponentClassCache;
-import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
-import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.ioc.Predicate;
+import org.apache.tapestry5.ioc.services.FieldValueConduit;
 import org.apache.tapestry5.model.MutableComponentModel;
 import org.apache.tapestry5.services.ApplicationStateManager;
 import org.apache.tapestry5.services.ClassTransformation;
 import org.apache.tapestry5.services.ComponentClassTransformWorker;
-import org.apache.tapestry5.services.TransformMethodSignature;
-
-import static java.lang.String.format;
-import java.lang.reflect.Modifier;
-import java.util.List;
-import java.util.Map;
+import org.apache.tapestry5.services.TransformField;
 
 /**
  * Looks for the {@link ApplicationState} and {@link org.apache.tapestry5.annotations.SessionState} annotations and
@@ -41,7 +40,7 @@
     private final ComponentClassCache componentClassCache;
 
     public ApplicationStateWorker(ApplicationStateManager applicationStateManager,
-                                  ComponentClassCache componentClassCache)
+            ComponentClassCache componentClassCache)
     {
         this.applicationStateManager = applicationStateManager;
         this.componentClassCache = componentClassCache;
@@ -49,110 +48,79 @@
 
     public void transform(ClassTransformation transformation, MutableComponentModel model)
     {
-        Map<String, Boolean> fields = CollectionFactory.newMap();
-
-        List<String> asoNames = transformation.findFieldsWithAnnotation(ApplicationState.class);
+        Map<TransformField, Boolean> fields = new TreeMap<TransformField, Boolean>();
 
-        for (String name : asoNames)
+        for (TransformField field : transformation
+                .matchFieldsWithAnnotation(ApplicationState.class))
         {
-            ApplicationState applicationState = transformation.getFieldAnnotation(name, ApplicationState.class);
-
-            fields.put(name, applicationState.create());
-        }
-
+            ApplicationState annotation = field.getAnnotation(ApplicationState.class);
 
-        List<String> ssoNames = transformation.findFieldsWithAnnotation(SessionState.class);
+            fields.put(field, annotation.create());
 
-        for (String name : ssoNames)
-        {
-            SessionState sessionState = transformation.getFieldAnnotation(name, SessionState.class);
-
-            fields.put(name, sessionState.create());
+            field.claim(annotation);
         }
 
-
-        if (fields.isEmpty()) return;
-
-        String managerFieldName = transformation.addInjectedField(ApplicationStateManager.class,
-                                                                  "applicationStateManager", applicationStateManager);
-
-        for (String fieldName : InternalUtils.sortedKeys(fields))
+        for (TransformField field : transformation.matchFieldsWithAnnotation(SessionState.class))
         {
-            processField(fieldName, managerFieldName, transformation, fields.get(fieldName));
-        }
-    }
-
-    private void processField(String fieldName, String managerFieldName, ClassTransformation transformation,
-                              boolean create)
-    {
-        String fieldType = transformation.getFieldType(fieldName);
-
-        Class fieldClass = componentClassCache.forName(fieldType);
+            SessionState annotation = field.getAnnotation(SessionState.class);
 
-        String typeFieldName = transformation.addInjectedField(Class.class, fieldName + "_type", fieldClass);
+            fields.put(field, annotation.create());
 
-        replaceRead(transformation, fieldName, fieldType, managerFieldName, typeFieldName, create);
-
-        replaceWrite(transformation, fieldName, fieldType, managerFieldName, typeFieldName);
-
-        transformation.removeField(fieldName);
-
-        String booleanFieldName = fieldName + "Exists";
+            field.claim(annotation);
+        }
 
-        if (transformation.isField(booleanFieldName) && transformation.getFieldType(booleanFieldName).equals("boolean"))
+        for (Map.Entry<TransformField, Boolean> e : fields.entrySet())
         {
-            replaceFlagRead(transformation, booleanFieldName, typeFieldName, managerFieldName);
+            transform(transformation, e.getKey(), e.getValue());
         }
     }
 
-    private void replaceFlagRead(ClassTransformation transformation, String booleanFieldName, String typeFieldName,
-                                 String managerFieldName)
-    {
-        String readMethodName = transformation.newMemberName("read", booleanFieldName);
-
-        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PRIVATE, "boolean", readMethodName, null,
-                                                                    null);
-
-        String body = format("return %s.exists(%s);", managerFieldName, typeFieldName);
-
-        transformation.addMethod(sig, body);
-
-        transformation.replaceReadAccess(booleanFieldName, readMethodName);
-        transformation.makeReadOnly(booleanFieldName);
-        transformation.removeField(booleanFieldName);
-    }
-
-    private void replaceWrite(ClassTransformation transformation, String fieldName, String fieldType,
-                              String managerFieldName, String typeFieldName)
+    @SuppressWarnings("unchecked")
+    private void transform(ClassTransformation transformation, TransformField field,
+            final boolean create)
     {
-        String writeMethodName = transformation.newMemberName("write", fieldName);
-
-        TransformMethodSignature writeSignature = new TransformMethodSignature(Modifier.PRIVATE, "void",
-                                                                               writeMethodName,
-                                                                               new String[] { fieldType },
-                                                                               null);
-
-        String body = format("%s.set(%s, $1);", managerFieldName, typeFieldName);
+        final Class fieldClass = componentClassCache.forName(field.getType());
 
-        transformation.addMethod(writeSignature, body);
-
-        transformation.replaceWriteAccess(fieldName, writeMethodName);
-    }
+        field.replaceAccess(new FieldValueConduit()
+        {
+            public void set(Object newValue)
+            {
+                applicationStateManager.set(fieldClass, newValue);
+            }
+
+            public Object get()
+            {
+                return create ? applicationStateManager.get(fieldClass) : applicationStateManager
+                        .getIfExists(fieldClass);
+            }
+        });
 
-    private void replaceRead(ClassTransformation transformation, String fieldName, String fieldType,
-                             String managerFieldName, String typeFieldName, boolean create)
-    {
-        String readMethodName = transformation.newMemberName("read", fieldName);
+        final String expectedName = field.getName() + "Exists";
 
-        TransformMethodSignature readMethodSignature = new TransformMethodSignature(Modifier.PRIVATE, fieldType,
-                                                                                    readMethodName, null, null);
+        List<TransformField> fields = transformation.matchFields(new Predicate<TransformField>()
+        {
+            public boolean accept(TransformField field)
+            {
+                return field.getType().equals("boolean")
+                        && field.getName().equalsIgnoreCase(expectedName);
+            }
+        });
 
-        String methodName = create ? "get" : "getIfExists";
+        for (TransformField existsField : fields)
+        {
+            existsField.claim(this);
 
-        String body = format("return (%s) %s.%s(%s);", fieldType, managerFieldName, methodName, typeFieldName);
+            String className = transformation.getClassName();
 
-        transformation.addMethod(readMethodSignature, body);
+            String fieldName = existsField.getName();
 
-        transformation.replaceReadAccess(fieldName, readMethodName);
+            existsField.replaceAccess(new ReadOnlyFieldValueConduit(className, fieldName)
+            {
+                public Object get()
+                {
+                    return applicationStateManager.exists(fieldClass);
+                }
+            });
+        }
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java?rev=904043&r1=904042&r2=904043&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java Thu Jan 28 11:35:54 2010
@@ -23,13 +23,13 @@
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.ioc.internal.util.TapestryException;
+import org.apache.tapestry5.ioc.services.FieldValueConduit;
 import org.apache.tapestry5.ioc.services.TypeCoercer;
 import org.apache.tapestry5.model.ComponentModel;
 import org.apache.tapestry5.model.MutableComponentModel;
 import org.apache.tapestry5.services.ClassTransformation;
 import org.apache.tapestry5.services.ComponentClassTransformWorker;
 import org.apache.tapestry5.services.ComponentValueProvider;
-import org.apache.tapestry5.services.FieldValueConduit;
 
 /**
  * Responsible for identifying, via the {@link org.apache.tapestry5.annotations.BindParameter} annotation, mixin fields

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/EnvironmentalWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/EnvironmentalWorker.java?rev=904043&r1=904042&r2=904043&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/EnvironmentalWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/EnvironmentalWorker.java Thu Jan 28 11:35:54 2010
@@ -1,10 +1,10 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2010 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
+// 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,
@@ -14,14 +14,19 @@
 
 package org.apache.tapestry5.internal.transform;
 
+import org.apache.tapestry5.ComponentResources;
 import org.apache.tapestry5.annotations.Environmental;
 import org.apache.tapestry5.ioc.services.Builtin;
 import org.apache.tapestry5.ioc.services.ClassFactory;
+import org.apache.tapestry5.ioc.services.FieldValueConduit;
 import org.apache.tapestry5.model.MutableComponentModel;
-import org.apache.tapestry5.services.*;
-
-import java.lang.reflect.Modifier;
-import java.util.List;
+import org.apache.tapestry5.runtime.PageLifecycleAdapter;
+import org.apache.tapestry5.services.ClassTransformation;
+import org.apache.tapestry5.services.ComponentClassTransformWorker;
+import org.apache.tapestry5.services.ComponentValueProvider;
+import org.apache.tapestry5.services.Environment;
+import org.apache.tapestry5.services.EnvironmentalAccess;
+import org.apache.tapestry5.services.TransformField;
 
 /**
  * Obtains a value from the {@link Environment} service based on the field type. This is triggered by the presence of
@@ -33,90 +38,90 @@
 
     private final ClassLoader classLoader;
 
-    public EnvironmentalWorker(Environment environment, @Builtin ClassFactory servicesLayerClassFactory)
-    {
-        this.environment = environment;
-
-        classLoader = servicesLayerClassFactory.getClassLoader();
-    }
-
-    public void transform(ClassTransformation transformation, MutableComponentModel model)
+    @SuppressWarnings("unchecked")
+    private final class EnvironmentalConduit extends ReadOnlyFieldValueConduit
     {
-        List<String> names = transformation.findFieldsWithAnnotation(Environmental.class);
+        private final Class environmentalType;
 
-        if (names.isEmpty())
-            return;
+        private final boolean required;
 
-        // TODO: addInjectField should be smart about if the field has already been injected (with
-        // the same type)
-        // for this transformation, or the parent transformation.
+        private EnvironmentalAccess access;
 
-        String envField = transformation.addInjectedField(
-                Environment.class,
-                "environment",
-                environment);
-
-        for (String name : names)
+        private EnvironmentalConduit(ComponentResources resources, String fieldName,
+                final Class environmentalType, boolean required)
         {
-            Environmental annotation = transformation.getFieldAnnotation(name, Environmental.class);
-
-            transformation.claimField(name, annotation);
+            super(resources, fieldName);
 
-            String typeName = transformation.getFieldType(name);
+            this.environmentalType = environmentalType;
+            this.required = required;
 
-            // TODO: Check for primitives
-
-            // TAP5-417: Calls to javassist.runtime.Desc.getType() are showing up as method hot spots.
-
-            Class type = null;
-
-            try
-            {
-                type = classLoader.loadClass(typeName);
-            }
-            catch (ClassNotFoundException ex)
+            resources.addPageLifecycleListener(new PageLifecycleAdapter()
             {
-                throw new RuntimeException(ex);
-            }
-
-            // TAP5-417: Changed the code to use EnvironmentalAccess, which encapsulates
-            // efficient caching.
+                @Override
+                public void containingPageDidDetach()
+                {
+                    access = null;
+                }
+            });
+        }
 
-            String injectedTypeFieldName = transformation.addInjectedField(Class.class, "type", type);
+        public Object get()
+        {
+            if (access == null)
+                access = environment.getAccess(environmentalType);
 
-            // First we need (at page attach) to acquire the closure for the type.
+            return required ? access.peekRequired() : access.peek();
+        }
+    }
 
-            String accessFieldName = transformation.addField(Modifier.PRIVATE, EnvironmentalAccess.class.getName(),
-                                                             name + "_access");
+    public EnvironmentalWorker(Environment environment, @Builtin
+    ClassFactory servicesLayerClassFactory)
+    {
+        this.environment = environment;
 
-            String attachBody = String.format("%s = %s.getAccess(%s);",
-                                              accessFieldName, envField, injectedTypeFieldName);
+        classLoader = servicesLayerClassFactory.getClassLoader();
+    }
 
-            transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_ATTACH_SIGNATURE, attachBody);
+    public void transform(ClassTransformation transformation, MutableComponentModel model)
+    {
+        for (TransformField field : transformation.matchFieldsWithAnnotation(Environmental.class))
+        {
+            transform(field);
+        }
+    }
 
-            // Clear the closure field when the page detaches.  We'll get a new one when we next attach.
+    private void transform(TransformField field)
+    {
+        Environmental annotation = field.getAnnotation(Environmental.class);
 
-            transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_DETACH_SIGNATURE,
-                                        accessFieldName + " = null;");
+        field.claim(annotation);
 
-            // Now build a read method that invokes peek() or peekRequired() on the closure. The closure
-            // is responsible for safe caching of the environmental value.
+        final String fieldName = field.getName();
 
-            String methodName = transformation.newMemberName("environment_read", name);
+        final Class fieldType = toClass(field.getType());
 
-            TransformMethodSignature sig = new TransformMethodSignature(Modifier.PRIVATE, typeName, methodName, null,
-                                                                        null);
+        final boolean required = annotation.value();
 
-            String body = String.format(
-                    "return ($r) %s.%s();",
-                    accessFieldName,
-                    annotation.value() ? "peekRequired" : "peek");
+        ComponentValueProvider<FieldValueConduit> provider = new ComponentValueProvider<FieldValueConduit>()
+        {
+            public FieldValueConduit get(ComponentResources resources)
+            {
+                return new EnvironmentalConduit(resources, fieldName, fieldType, required);
+            }
+        };
 
-            transformation.addMethod(sig, body);
+        field.replaceAccess(provider);
+    }
 
-            transformation.replaceReadAccess(name, methodName);
-            transformation.makeReadOnly(name);
-            transformation.removeField(name);
+    private Class toClass(String typeName)
+    {
+        try
+        {
+            return classLoader.loadClass(typeName);
+        }
+        catch (ClassNotFoundException ex)
+        {
+            throw new RuntimeException(ex);
         }
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectPageWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectPageWorker.java?rev=904043&r1=904042&r2=904043&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectPageWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectPageWorker.java Thu Jan 28 11:35:54 2010
@@ -1,10 +1,10 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2010 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
+// 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,
@@ -14,22 +14,58 @@
 
 package org.apache.tapestry5.internal.transform;
 
+import org.apache.tapestry5.ComponentResources;
 import org.apache.tapestry5.annotations.InjectPage;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
-import org.apache.tapestry5.ioc.util.BodyBuilder;
+import org.apache.tapestry5.ioc.services.FieldValueConduit;
 import org.apache.tapestry5.model.MutableComponentModel;
-import org.apache.tapestry5.services.*;
-
-import java.lang.reflect.Modifier;
-import java.util.List;
+import org.apache.tapestry5.runtime.PageLifecycleAdapter;
+import org.apache.tapestry5.services.ClassTransformation;
+import org.apache.tapestry5.services.ComponentClassResolver;
+import org.apache.tapestry5.services.ComponentClassTransformWorker;
+import org.apache.tapestry5.services.ComponentSource;
+import org.apache.tapestry5.services.ComponentValueProvider;
+import org.apache.tapestry5.services.TransformField;
 
 /**
  * Peforms transformations that allow pages to be injected into components.
- *
+ * 
  * @see org.apache.tapestry5.annotations.InjectPage
  */
 public class InjectPageWorker implements ComponentClassTransformWorker
 {
+    private final class InjectedPageConduit extends ReadOnlyFieldValueConduit
+    {
+        private final String injectedPageName;
+
+        private Object page;
+
+        private InjectedPageConduit(ComponentResources resources, String fieldName,
+                String injectedPageName)
+        {
+            super(resources, fieldName);
+
+            this.injectedPageName = injectedPageName;
+
+            resources.addPageLifecycleListener(new PageLifecycleAdapter()
+            {
+                @Override
+                public void containingPageDidDetach()
+                {
+                    page = null;
+                }
+            });
+        }
+
+        public Object get()
+        {
+            if (page == null)
+                page = componentSource.getPage(injectedPageName);
+
+            return page;
+        }
+    }
+
     private final ComponentSource componentSource;
 
     private final ComponentClassResolver resolver;
@@ -42,46 +78,33 @@
 
     public void transform(ClassTransformation transformation, MutableComponentModel model)
     {
-        List<String> names = transformation.findFieldsWithAnnotation(InjectPage.class);
-
-        if (names.isEmpty()) return;
-
-        String componentSource = transformation.addInjectedField(ComponentSource.class, "componentSource",
-                                                                 this.componentSource);
-
-
-        for (String name : names)
-            addInjectedPage(transformation, name, componentSource);
-
+        for (TransformField field : transformation.matchFieldsWithAnnotation(InjectPage.class))
+        {
+            addInjectedPage(field);
+        }
     }
 
-    private void addInjectedPage(ClassTransformation transformation, String fieldName, String componentSource)
+    private void addInjectedPage(TransformField field)
     {
-        InjectPage annotation = transformation.getFieldAnnotation(fieldName, InjectPage.class);
-        
-        transformation.claimField(fieldName, annotation);
+        InjectPage annotation = field.getAnnotation(InjectPage.class);
 
-        String pageName = annotation.value();
-
-        String fieldType = transformation.getFieldType(fieldName);
-        String methodName = transformation.newMemberName("read_inject_page", fieldName);
+        field.claim(annotation);
 
-        String injectedPageName = InternalUtils.isBlank(pageName) ? resolver
-                .resolvePageClassNameToPageName(fieldType) : pageName;
-
-        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PRIVATE, fieldType, methodName, null,
-                                                                    null);
+        String pageName = annotation.value();
 
-        BodyBuilder builder = new BodyBuilder();
-        builder.begin();
+        final String fieldName = field.getName();
 
-        builder.addln("return (%s) %s.getPage(\"%s\");", fieldType, componentSource, injectedPageName);
+        final String injectedPageName = InternalUtils.isBlank(pageName) ? resolver
+                .resolvePageClassNameToPageName(field.getType()) : pageName;
 
-        builder.end();
+        ComponentValueProvider<FieldValueConduit> provider = new ComponentValueProvider<FieldValueConduit>()
+        {
+            public FieldValueConduit get(ComponentResources resources)
+            {
+                return new InjectedPageConduit(resources, fieldName, injectedPageName);
+            }
+        };
 
-        transformation.addMethod(sig, builder.toString());
-        transformation.replaceReadAccess(fieldName, methodName);
-        transformation.makeReadOnly(fieldName);
-        transformation.removeField(fieldName);
+        field.replaceAccess(provider);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterConduit.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterConduit.java?rev=904043&r1=904042&r2=904043&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterConduit.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ParameterConduit.java Thu Jan 28 11:35:54 2010
@@ -18,13 +18,19 @@
 import org.apache.tapestry5.annotations.Parameter;
 import org.apache.tapestry5.internal.InternalComponentResources;
 import org.apache.tapestry5.internal.bindings.LiteralBinding;
+import org.apache.tapestry5.ioc.services.FieldValueConduit;
+import org.apache.tapestry5.ioc.services.TypeCoercer;
 import org.apache.tapestry5.runtime.Component;
-import org.apache.tapestry5.services.FieldValueConduit;
 
 /**
  * A facade around {@link Binding} and {@link InternalComponentResources} that is used to instrument
  * fields with the {@link Parameter} annotation. Extends {@link FieldValueConduit} so that
  * the get() method implicitly coerces the value to the field's type.
+ * <p>
+ * {@link #get()} will read from the underlying {@link Binding} and used the {@link TypeCoercer} coerce the value to the
+ * parameter field's type. get() also includes a null value check (as per {@link Parameter#allowNull()}.
+ * <p>
+ * {@link #set(Object)} pushes the value into the binding.
  * 
  * @since 5.2.0
  */
@@ -49,8 +55,7 @@
     boolean isBound();
 
     /**
-     * Resets the conduit, clearing any <em>temporarily</em> cached data (from a non-invariant
-     * {@link Binding}).
+     * Resets the conduit, clearing any <em>temporarily</em> cached data (from a non-invariant {@link Binding}).
      */
     void reset();
 

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ReadOnlyFieldValueConduit.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ReadOnlyFieldValueConduit.java?rev=904043&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ReadOnlyFieldValueConduit.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ReadOnlyFieldValueConduit.java Thu Jan 28 11:35:54 2010
@@ -0,0 +1,49 @@
+// Copyright 2010 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.tapestry5.internal.transform;
+
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.ioc.services.FieldValueConduit;
+
+/**
+ * An implementation of {@link FieldValueConduit} for a read-only component field. Subclasses
+ * provide an implementation of the {@link #get()} method.
+ * 
+ * @since 5.2.0
+ */
+public abstract class ReadOnlyFieldValueConduit implements FieldValueConduit
+{
+    private final String qualifiedFieldName;
+
+    public ReadOnlyFieldValueConduit(String qualifiedFieldName)
+    {
+        this.qualifiedFieldName = qualifiedFieldName;
+    }
+
+    public ReadOnlyFieldValueConduit(String className, String fieldName)
+    {
+        this(String.format("%s.%s", className, fieldName));
+    }
+
+    public ReadOnlyFieldValueConduit(ComponentResources resources, String fieldName)
+    {
+        this(resources.getComponentModel().getComponentClassName(), fieldName);
+    }
+
+    public final void set(Object newValue)
+    {
+        throw new RuntimeException(String.format("Field %s is read only.", qualifiedFieldName));
+    }
+}

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ReadOnlyFieldValueConduit.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/runtime/PageLifecycleAdapter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/runtime/PageLifecycleAdapter.java?rev=904043&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/runtime/PageLifecycleAdapter.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/runtime/PageLifecycleAdapter.java Thu Jan 28 11:35:54 2010
@@ -0,0 +1,38 @@
+// Copyright 2010 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.tapestry5.runtime;
+
+/**
+ * Empty implementation of the {@link PageLifecycleListener} interface.
+ */
+public class PageLifecycleAdapter implements PageLifecycleListener
+{
+    public void containingPageDidAttach()
+    {
+    }
+
+    public void containingPageDidDetach()
+    {
+    }
+
+    public void containingPageDidLoad()
+    {
+    }
+
+    public void restoreStateBeforePageAttach()
+    {
+    }
+
+}

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/runtime/PageLifecycleAdapter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java?rev=904043&r1=904042&r2=904043&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java Thu Jan 28 11:35:54 2010
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.services;
 
 import org.apache.tapestry5.ioc.AnnotationProvider;
+import org.apache.tapestry5.ioc.services.FieldValueConduit;
 
 /**
  * A field defined by (or created within) a {@link ClassTransformation},
@@ -74,6 +75,15 @@
     void replaceAccess(TransformField conduitField);
 
     /**
+     * Replaces reand and write field access with a conduit. A new field is created for the conduit instance,
+     * and the original field is deleted.
+     * 
+     * @param conduit
+     *            used to replace read and write access to the field
+     */
+    void replaceAccess(FieldValueConduit conduit);
+
+    /**
      * Extends the indicated method to add an assignment of the field with
      * the value obtained by the provider. This is used when a value
      * to be provided can not be provided from within the transformed class'

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/InternalClassTransformationImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/InternalClassTransformationImplTest.java?rev=904043&r1=904042&r2=904043&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/InternalClassTransformationImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/InternalClassTransformationImplTest.java Thu Jan 28 11:35:54 2010
@@ -14,7 +14,22 @@
 
 package org.apache.tapestry5.internal.services;
 
-import javassist.*;
+import static java.lang.Thread.currentThread;
+import static java.util.Arrays.asList;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Target;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.Map;
+
+import javassist.CtClass;
+import javassist.CtMethod;
+import javassist.Loader;
+import javassist.LoaderClassPath;
+import javassist.NotFoundException;
+
 import org.apache.tapestry5.annotations.Meta;
 import org.apache.tapestry5.annotations.OnEvent;
 import org.apache.tapestry5.annotations.Retain;
@@ -44,15 +59,6 @@
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
-import static java.lang.Thread.currentThread;
-import java.lang.annotation.Documented;
-import java.lang.annotation.Target;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import static java.util.Arrays.asList;
-import java.util.List;
-import java.util.Map;
-
 /**
  * The tests share a number of resources, and so are run sequentially.
  */

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/ApplicationStateWorkerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/ApplicationStateWorkerTest.java?rev=904043&r1=904042&r2=904043&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/ApplicationStateWorkerTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/ApplicationStateWorkerTest.java Thu Jan 28 11:35:54 2010
@@ -18,10 +18,14 @@
 import javassist.Loader;
 import javassist.LoaderClassPath;
 import javassist.NotFoundException;
-import org.apache.tapestry5.annotations.ApplicationState;
-import org.apache.tapestry5.annotations.SessionState;
+
 import org.apache.tapestry5.internal.InternalComponentResources;
-import org.apache.tapestry5.internal.services.*;
+import org.apache.tapestry5.internal.services.ComponentClassCache;
+import org.apache.tapestry5.internal.services.Instantiator;
+import org.apache.tapestry5.internal.services.InternalClassTransformation;
+import org.apache.tapestry5.internal.services.InternalClassTransformationImpl;
+import org.apache.tapestry5.internal.services.InternalClassTransformationImplTest;
+import org.apache.tapestry5.internal.services.SimpleASO;
 import org.apache.tapestry5.internal.test.InternalBaseTestCase;
 import org.apache.tapestry5.internal.transform.pages.MaybeStateHolder;
 import org.apache.tapestry5.internal.transform.pages.StateHolder;
@@ -32,8 +36,6 @@
 import org.apache.tapestry5.ioc.services.PropertyAccess;
 import org.apache.tapestry5.model.MutableComponentModel;
 import org.apache.tapestry5.services.ApplicationStateManager;
-import org.apache.tapestry5.services.ClassTransformation;
-import org.apache.tapestry5.services.ComponentClassTransformWorker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.annotations.AfterClass;
@@ -90,25 +92,6 @@
         access = null;
     }
 
-    @Test
-    public void no_fields_with_annotation()
-    {
-        ApplicationStateManager manager = mockApplicationStateManager();
-        ClassTransformation ct = mockClassTransformation();
-        MutableComponentModel model = mockMutableComponentModel();
-
-        train_findFieldsWithAnnotation(ct, ApplicationState.class);
-        train_findFieldsWithAnnotation(ct, SessionState.class);
-
-        replay();
-
-        ComponentClassTransformWorker worker = new ApplicationStateWorker(manager, null);
-
-        worker.transform(ct, model);
-
-        verify();
-    }
-
     @SuppressWarnings("unchecked")
     @Test
     public void field_read_and_write() throws Exception

Copied: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/FieldValueConduit.java (from r903976, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldValueConduit.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/FieldValueConduit.java?p2=tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/FieldValueConduit.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldValueConduit.java&r1=903976&r2=904043&rev=904043&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldValueConduit.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/FieldValueConduit.java Thu Jan 28 11:35:54 2010
@@ -12,13 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry5.services;
+package org.apache.tapestry5.ioc.services;
 
-import org.apache.tapestry5.Binding;
-import org.apache.tapestry5.ioc.services.TypeCoercer;
 
 /**
- * A callback object that is used to replace storage of a value inside a component field.
+ * Used as a replacement for a field.
  * 
  * @since 5.2.0
  */
@@ -26,20 +24,17 @@
 {
 
     /**
-     * Reads the current value of the parameter (via the {@link Binding}) and uses the
-     * {@link TypeCoercer} to convert the actual value to one assignable to the underlying field.
-     * The actual read value may be cached.
+     * Reads the current value of the field.
      * 
-     * @throws RuntimeException
-     *             if the parameter does not allow null but the current value is null
      * @return current value (possibly null)
      */
     Object get();
 
     /**
-     * Sets the value of the parameter, pushing it through the {@link Binding}.
+     * Sets the value of the field
      * 
      * @param newValue
+     *            to be captured
      */
     void set(Object newValue);
 

Propchange: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/FieldValueConduit.java
------------------------------------------------------------------------------
    svn:eol-style = native