You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2006/09/05 20:14:55 UTC

svn commit: r440425 - in /tapestry/tapestry5/tapestry-core/trunk/src: main/java/org/apache/tapestry/annotations/ main/java/org/apache/tapestry/internal/bindings/ main/java/org/apache/tapestry/internal/ioc/services/ main/java/org/apache/tapestry/interna...

Author: hlship
Date: Tue Sep  5 11:14:53 2006
New Revision: 440425

URL: http://svn.apache.org/viewvc?view=rev&rev=440425
Log:
Add initial support for the @Inject annotation.

Added:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectionProvider.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/WriteWebRequest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InjectPage.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectPage.html
Modified:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryClassPool.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformer.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.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/ServicesMessages.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/BaseTestCase.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
    tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
    tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml
    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/integration/app1/components/Loop.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/MerryChristmas.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.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/ParameterWorkerTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ReadOnlyBean.java

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java Tue Sep  5 11:14:53 2006
@@ -0,0 +1,40 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Allows injection of various objects into a component class.
+ * 
+ * @author Howard M. Lewis Ship
+ * @see org.apache.tapestry.internal.services.InjectionProvider
+ */
+@Target(FIELD)
+@Documented
+@Retention(RUNTIME)
+public @interface Inject {
+
+    /**
+     * Identifies the value to be injected, when the type by itself is insufficient. Omitted in many
+     * cases.
+     */
+    String value() default "";
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java Tue Sep  5 11:14:53 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.internal.bindings;
 
 import org.apache.tapestry.Location;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java Tue Sep  5 11:14:53 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.internal.bindings;
 
 import java.lang.reflect.Constructor;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryClassPool.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryClassPool.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryClassPool.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryClassPool.java Tue Sep  5 11:14:53 2006
@@ -56,9 +56,9 @@
     /**
      * Convienience method for adding to the ClassPath for a particular class loader.
      * <p>
-     * TODO: This code assumes that ClassLoaders are structured as a "line" not a proper "tree". That
-     * is, if the ClassLoader hiearchy actually does have branches, rather than a straight line from
-     * root to leaf, it may not work.
+     * TODO: This code assumes that ClassLoaders are structured as a "line" not a proper "tree".
+     * That is, if the ClassLoader hiearchy actually does have branches, rather than a straight line
+     * from root to leaf, it may not work.
      * 
      * @param loader
      *            the class loader to add (derived from a loaded class, and may be null for some
@@ -87,6 +87,11 @@
         }
 
         _loader = loader;
+    }
+
+    public ClassLoader getLoader()
+    {
+        return _loader;
     }
 
     /**

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformer.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformer.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformer.java Tue Sep  5 11:14:53 2006
@@ -29,8 +29,14 @@
 {
     /**
      * Performs a transformation on the class, accessing the class from the class pool.
+     * 
+     * @param ctClass
+     *            compile time class to be transformed
+     * @param classLoader
+     *            class loader used to resolve references to other classes (both transformed and
+     *            not)
      */
-    void transformComponentClass(CtClass ctClass);
+    void transformComponentClass(CtClass ctClass, ClassLoader classLoader);
 
     /** Creates a new instantiator instance. */
     Instantiator createInstantiator(Class componentClass);

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassTransformerImpl.java Tue Sep  5 11:14:53 2006
@@ -75,7 +75,7 @@
     }
 
     @Concurrent.Write
-    public void transformComponentClass(CtClass ctClass)
+    public void transformComponentClass(CtClass ctClass, ClassLoader classLoader)
     {
         String classname = ctClass.getName();
 
@@ -99,8 +99,8 @@
         // TODO: Check that the name is not already in the map.
 
         InternalClassTransformation transformation = parentTransformation == null ? new InternalClassTransformationImpl(
-                ctClass)
-                : new InternalClassTransformationImpl(ctClass, parentTransformation);
+                ctClass, classLoader)
+                : new InternalClassTransformationImpl(ctClass, parentTransformation, classLoader);
 
         // Not all classes in the packages are components. That's not just sloppy coding by
         // application developers, it also represents inner classes (including anonymous classes).

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java Tue Sep  5 11:14:53 2006
@@ -160,7 +160,7 @@
 
             // Do the transformations here
 
-            _transformer.transformComponentClass(ctClass);
+            _transformer.transformComponentClass(ctClass, _loader);
 
             diag = "END";
         }

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java Tue Sep  5 11:14:53 2006
@@ -0,0 +1,95 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.internal.ioc.IOCUtilities;
+import org.apache.tapestry.ioc.ObjectProvider;
+import org.apache.tapestry.ioc.ServiceLocator;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassTransformWorker;
+
+/**
+ * Worker for the {@link org.apache.tapestry.annotations.Inject} annotation.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public class InjectWorker implements ComponentClassTransformWorker
+{
+    private final ObjectProvider _objectProvider;
+
+    private final ServiceLocator _locator;
+
+    // Really, a chain of command
+
+    private final InjectionProvider _injectionProvider;
+
+    public InjectWorker(ObjectProvider objectProvider, ServiceLocator locator,
+            InjectionProvider injectionProvider)
+    {
+        _objectProvider = objectProvider;
+        _locator = locator;
+        _injectionProvider = injectionProvider;
+    }
+
+    public void transform(ClassTransformation transformation, MutableComponentModel model)
+    {
+        for (String fieldName : transformation.findFieldsWithAnnotation(Inject.class))
+        {
+            Inject annotation = transformation.getFieldAnnotation(fieldName, Inject.class);
+
+            String value = annotation.value();
+
+            if (IOCUtilities.isBlank(value))
+                injectAnnonymous(fieldName, transformation, model);
+            else
+                injectNamed(fieldName, value, transformation, model);
+
+            transformation.claimField(fieldName, annotation);
+        }
+
+    }
+
+    @SuppressWarnings("unchecked")
+    private void injectNamed(String fieldName, String value, ClassTransformation transformation,
+            MutableComponentModel model)
+    {
+        String fieldType = transformation.getFieldType(fieldName);
+
+        Class type = transformation.toClass(fieldType);
+
+        Object inject = _objectProvider.provide(value, type, _locator);
+
+        transformation.injectField(fieldName, inject);
+    }
+
+    private void injectAnnonymous(String fieldName, ClassTransformation transformation,
+            MutableComponentModel model)
+    {
+        String fieldType = transformation.getFieldType(fieldName);
+
+        boolean result = _injectionProvider.provideInjection(
+                fieldName,
+                fieldType,
+                _locator,
+                transformation,
+                model);
+
+        if (!result)
+            throw new RuntimeException(ServicesMessages.noInjectionFound(transformation
+                    .getClassName(), fieldName, fieldType));
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectionProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectionProvider.java?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectionProvider.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectionProvider.java Tue Sep  5 11:14:53 2006
@@ -0,0 +1,53 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.ioc.ServiceLocator;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.ClassTransformation;
+
+/**
+ * Provides some form of injection when the value for an
+ * {@link org.apache.tapestry.annotations.Inject} annotation is blank. In this case, the provider is
+ * responsible for determining the value to be injected from the field name and field type.
+ * <p>
+ * This interface will be used as part of a
+ * {@link org.apache.tapestry.ioc.services.ChainBuilder chain of command}.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public interface InjectionProvider
+{
+    /**
+     * Peform the injection, if possible. Most often, this will result in a call to
+     * {@link ClassTransformation#injectField(String, Object)}. The caller is responsible for
+     * invoking {@link ClassTransformation#claimField(String, Object)}.
+     * 
+     * @param fieldName
+     *            the name of the field requesting injection
+     * @param fieldType
+     *            the type of the field (as a string)
+     * @param locator
+     *            allows services to be located
+     * @param transformation
+     *            allows the code for the class to be transformed
+     * @param componentModel
+     *            defines the relevant aspects of the component
+     * @return true if an injection has been made (terminates the command chain), false to continue
+     *         down the chain
+     */
+    boolean provideInjection(String fieldName, String fieldType, ServiceLocator locator,
+            ClassTransformation transformation, MutableComponentModel componentModel);
+}

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=440425&r1=440424&r2=440425
==============================================================================
--- 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 Sep  5 11:14:53 2006
@@ -21,8 +21,8 @@
 import org.apache.tapestry.util.IdAllocator;
 
 /**
- * Extends {@link org.apache.tapestry.services.ClassTransformation} with additional methods that
- * may only be used internally by Tapestry.
+ * Extends {@link org.apache.tapestry.services.ClassTransformation} with additional methods that may
+ * only be used internally by Tapestry.
  * 
  * @author Howard M. Lewis Ship
  */
@@ -35,9 +35,9 @@
     String getResourcesFieldName();
 
     /**
-     * Invoked after all {@link ComponentClassTransformWorker}s have had their chance to work over the
-     * class. This performs any final operations for the class transformation, which includes coming
-     * up with the final constructor method for the class.
+     * Invoked after all {@link ComponentClassTransformWorker}s have had their chance to work over
+     * the class. This performs any final operations for the class transformation, which includes
+     * coming up with the final constructor method for the class.
      */
     void finish();
 

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=440425&r1=440424&r2=440425
==============================================================================
--- 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 Sep  5 11:14:53 2006
@@ -42,6 +42,7 @@
 import org.apache.tapestry.internal.util.InternalUtils;
 import org.apache.tapestry.runtime.ComponentLifecycle;
 import org.apache.tapestry.services.MethodSignature;
+import org.apache.tapestry.services.TransformUtils;
 import org.apache.tapestry.util.CollectionFactory;
 import org.apache.tapestry.util.IdAllocator;
 
@@ -64,7 +65,7 @@
 
     private final CtClass _ctClass;
 
-    private final ClassPool _classPool;
+    private ClassPool _classPool;
 
     private final IdAllocator _idAllocator;
 
@@ -106,14 +107,17 @@
 
     private Formatter _formatter = new Formatter(_description);
 
+    private ClassLoader _loader;
+
     /**
      * This is a constructor for the root class, the class that directly contains the ComponentClass
      * annotation.
      */
-    public InternalClassTransformationImpl(CtClass ctClass)
+    public InternalClassTransformationImpl(CtClass ctClass, ClassLoader loader)
     {
         _ctClass = ctClass;
         _classPool = _ctClass.getClassPool();
+        _loader = loader;
 
         _idAllocator = new IdAllocator();
 
@@ -135,10 +139,12 @@
     }
 
     public InternalClassTransformationImpl(CtClass ctClass,
-            InternalClassTransformation parentTransformation)
+            InternalClassTransformation parentTransformation, ClassLoader loader)
     {
         _ctClass = ctClass;
         _classPool = _ctClass.getClassPool();
+        _loader = loader;
+
         _resourcesFieldName = parentTransformation.getResourcesFieldName();
 
         _idAllocator = parentTransformation.getIdAllocator();
@@ -186,6 +192,9 @@
         _fieldWriteTransforms = null;
         _constructor = null;
         _formatter = null;
+        _loader = null;
+        // _ctClass = null; -- needed by toString()
+        _classPool = null;
     }
 
     public String getResourcesFieldName()
@@ -661,6 +670,8 @@
 
     public List<String> findFieldsWithAnnotation(Class<? extends Annotation> annotationClass)
     {
+        failIfFrozen();
+
         List<String> result = newList();
 
         for (CtField field : _ctClass.getDeclaredFields())
@@ -693,6 +704,8 @@
     public List<MethodSignature> findMethodsWithAnnotation(
             Class<? extends Annotation> annotationClass)
     {
+        failIfFrozen();
+
         List<MethodSignature> result = newList();
 
         for (CtMethod method : _ctClass.getDeclaredMethods())
@@ -781,13 +794,20 @@
 
     public String getFieldType(String fieldName)
     {
+        failIfFrozen();
+
+        CtClass type = getFieldCtType(fieldName);
+
+        return type.getName();
+    }
+
+    private CtClass getFieldCtType(String fieldName)
+    {
         try
         {
             CtField field = _ctClass.getDeclaredField(fieldName);
 
-            CtClass type = field.getType();
-
-            return type.getName();
+            return field.getType();
         }
         catch (NotFoundException ex)
         {
@@ -849,11 +869,41 @@
 
         String fieldName = addField(Modifier.PROTECTED, type.getName(), suggestedName);
 
-        _constructorArgs.add(new ConstructorArg(ctType, value));
+        addInjectToConstructor(fieldName, ctType, value);
+
+        return fieldName;
+    }
+
+    /**
+     * Adds a parameter to the constructor for the class; the parameter is used to initialize the
+     * value for a field.
+     * 
+     * @param fieldName
+     *            name of field to inject
+     * @param fieldType
+     *            Javassist type of the field (and corresponding parameter)
+     * @param value
+     *            the value to be injected (which will in unusual cases be null)
+     */
+    private void addInjectToConstructor(String fieldName, CtClass fieldType, Object value)
+    {
+        _constructorArgs.add(new ConstructorArg(fieldType, value));
 
         _constructor.append(format("  %s = $%d;\n", fieldName, _constructorArgs.size()));
+    }
 
-        return fieldName;
+    @SuppressNullCheck
+    public void injectField(String fieldName, Object value)
+    {
+        notNull(fieldName, "fieldName");
+
+        failIfFrozen();
+
+        CtClass type = getFieldCtType(fieldName);
+
+        addInjectToConstructor(fieldName, type, value);
+
+        makeReadOnly(fieldName);
     }
 
     private CtClass convertNameToCtType(String type) throws NotFoundException
@@ -1128,4 +1178,28 @@
             throw new RuntimeException(ex);
         }
     }
+
+    public Class toClass(String type)
+    {
+        failIfFrozen();
+
+        // No reason why this can't be allowed to work after freezing.
+
+        String finalType = TransformUtils.getWrapperType(type);
+
+        try
+        {
+            return Class.forName(finalType, true, _loader);
+        }
+        catch (ClassNotFoundException ex)
+        {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    public String getClassName()
+    {
+        return _ctClass.getName();
+    }
+
 }

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=440425&r1=440424&r2=440425
==============================================================================
--- 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 Sep  5 11:14:53 2006
@@ -14,19 +14,11 @@
 
 package org.apache.tapestry.internal.services;
 
-import java.lang.annotation.Annotation;
-
 import org.apache.commons.logging.Log;
-import org.apache.tapestry.annotations.BeforeRenderBody;
-import org.apache.tapestry.annotations.BeginRender;
-import org.apache.tapestry.annotations.CleanupRender;
-import org.apache.tapestry.annotations.AfterRender;
-import org.apache.tapestry.annotations.SetupRender;
 import org.apache.tapestry.events.InvalidationEvent;
 import org.apache.tapestry.events.InvalidationListener;
 import org.apache.tapestry.internal.InternalConstants;
 import org.apache.tapestry.internal.bindings.PropBindingFactory;
-import org.apache.tapestry.ioc.IOCUtilities;
 import org.apache.tapestry.ioc.LogSource;
 import org.apache.tapestry.ioc.OrderedConfiguration;
 import org.apache.tapestry.ioc.annotations.Contribute;
@@ -46,8 +38,6 @@
 import org.apache.tapestry.services.ComponentClassResolver;
 import org.apache.tapestry.services.ComponentClassTransformWorker;
 import org.apache.tapestry.services.MarkupWriterFactory;
-import org.apache.tapestry.services.MethodSignature;
-import org.apache.tapestry.services.TransformConstants;
 import org.apache.tapestry.services.WebContext;
 import org.apache.tapestry.services.WebRequestFilter;
 
@@ -167,49 +157,6 @@
     public UpdateListenerHub buildUpdateListenerHub()
     {
         return new UpdateListenerHubImpl();
-    }
-
-    /**
-     * Adds a number of standard workers:
-     * <ul>
-     * <li>Retain -- allows fields to retain their values between requests</li>
-     * <li>Parameter</li> -- identifies parameters based on the Parameter annotation</li>
-     * <li>UnclaimedField</li> -- identifies unclaimed fields and resets them to null/0/false at
-     * the end of the request</li>
-     * <li>SetupRender, BeginRender, etc. -- correspond to component render phases and annotations</li>
-     * </ul>
-     * 
-     * @param configuration
-     */
-    @Contribute("tapestry.ComponentClassTransformWorker")
-    public void contributeInternalWorkers(
-            OrderedConfiguration<ComponentClassTransformWorker> configuration)
-    {
-        // TODO: Proper scheduling of all of this.
-
-        configuration.add("Parameter", new ParameterWorker());
-
-        // Workers for the component rendering state machine methods; this is in typical
-        // execution order.
-
-        add(configuration, TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class);
-        add(configuration, TransformConstants.BEGIN_RENDER_SIGNATURE, BeginRender.class);
-        add(configuration, TransformConstants.BEFORE_RENDER_BODY_SIGNATURE, BeforeRenderBody.class);
-        add(configuration, TransformConstants.AFTER_RENDER_SIGNATURE, AfterRender.class);
-        add(configuration, TransformConstants.CLEANUP_RENDER_SIGNATURE, CleanupRender.class);
-
-        configuration.add("Retain", new RetainWorker());
-        configuration.add("UnclaimedField", new UnclaimedFieldWorker(), "after:*.*");
-    }
-
-    private void add(OrderedConfiguration<ComponentClassTransformWorker> configuration,
-            MethodSignature signature, Class<? extends Annotation> annotationClass)
-    {
-        // make the name match the annotation class name.
-
-        String name = IOCUtilities.toSimpleId(annotationClass.getName());
-
-        configuration.add(name, new ComponentLifecycleMethodWorker(signature, annotationClass));
     }
 
     /**

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java Tue Sep  5 11:14:53 2006
@@ -138,4 +138,9 @@
     {
         return MESSAGES.format("read-only-field", className, fieldName);
     }
+
+    static String noInjectionFound(String className, String fieldName, String fieldType)
+    {
+        return MESSAGES.format("no-injection-found", className, fieldName, fieldType);
+    }
 }

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=440425&r1=440424&r2=440425
==============================================================================
--- 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 Sep  5 11:14:53 2006
@@ -42,6 +42,12 @@
 {
 
     /**
+     * Returns the name of the class being transformed.
+     */
+
+    String getClassName();
+
+    /**
      * Returns the name of a new member (field or method). Ensures that the resulting name does not
      * conflict with any existing member (declared by the underlying class, or inherited from a base
      * class).
@@ -167,6 +173,16 @@
     String addInjectedField(Class type, String suggestedName, Object value);
 
     /**
+     * Converts the field into a read only field whose value is the provided value.
+     * 
+     * @param fieldName
+     *            name of field to convert
+     * @param value
+     *            the value provided by the field
+     */
+    void injectField(String fieldName, Object value);
+
+    /**
      * Transforms the class to implement the indicated interface. If the class (or its super class)
      * does not already implement the interface, then the interface is added, and default
      * implementations of any methods of the interface are added.
@@ -224,4 +240,11 @@
      * {@link #extendMethod(MethodSignature, String)}.
      */
     void replaceWriteAccess(String fieldName, String methodName);
+
+    /**
+     * Converts a type name into a corresponding class (possibly, a transformed class). Primitive
+     * type names are returned as wrapper types.
+     */
+
+    Class toClass(String type);
 }

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=440425&r1=440424&r2=440425
==============================================================================
--- 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 Sep  5 11:14:53 2006
@@ -15,6 +15,7 @@
 package org.apache.tapestry.services;
 
 import java.io.IOException;
+import java.lang.annotation.Annotation;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -25,6 +26,11 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.annotations.AfterRender;
+import org.apache.tapestry.annotations.BeforeRenderBody;
+import org.apache.tapestry.annotations.BeginRender;
+import org.apache.tapestry.annotations.CleanupRender;
+import org.apache.tapestry.annotations.SetupRender;
 import org.apache.tapestry.internal.InternalConstants;
 import org.apache.tapestry.internal.annotations.SuppressNullCheck;
 import org.apache.tapestry.internal.bindings.LiteralBindingFactory;
@@ -33,19 +39,26 @@
 import org.apache.tapestry.internal.services.ComponentClassFactoryImpl;
 import org.apache.tapestry.internal.services.ComponentClassResolverImpl;
 import org.apache.tapestry.internal.services.ComponentInstantiatorSource;
+import org.apache.tapestry.internal.services.ComponentLifecycleMethodWorker;
 import org.apache.tapestry.internal.services.HTMLDispatcher;
 import org.apache.tapestry.internal.services.InfrastructureImpl;
 import org.apache.tapestry.internal.services.InfrastructureManagerImpl;
+import org.apache.tapestry.internal.services.InjectWorker;
+import org.apache.tapestry.internal.services.InjectionProvider;
 import org.apache.tapestry.internal.services.InternalModule;
 import org.apache.tapestry.internal.services.MarkupWriterImpl;
 import org.apache.tapestry.internal.services.PageResponseRenderer;
+import org.apache.tapestry.internal.services.ParameterWorker;
 import org.apache.tapestry.internal.services.RequestGlobalsImpl;
 import org.apache.tapestry.internal.services.RequestPageCache;
+import org.apache.tapestry.internal.services.RetainWorker;
 import org.apache.tapestry.internal.services.StaticFilesFilter;
+import org.apache.tapestry.internal.services.UnclaimedFieldWorker;
 import org.apache.tapestry.internal.services.WebContextImpl;
 import org.apache.tapestry.internal.services.WebRequestImpl;
 import org.apache.tapestry.internal.services.WebResponseImpl;
 import org.apache.tapestry.ioc.Configuration;
+import org.apache.tapestry.ioc.IOCUtilities;
 import org.apache.tapestry.ioc.MappedConfiguration;
 import org.apache.tapestry.ioc.ObjectProvider;
 import org.apache.tapestry.ioc.OrderedConfiguration;
@@ -340,7 +353,7 @@
             @InjectService("Infrastructure")
             Infrastructure infrastructure)
     {
-        configuration.add("service", infrastructure.getObjectProvider());
+        configuration.add("infrastructure", infrastructure.getObjectProvider());
     }
 
     public void contributeMasterDispatcher(OrderedConfiguration<Dispatcher> configuration,
@@ -380,5 +393,63 @@
             ComponentInstantiatorSource source)
     {
         return new ComponentClassFactoryImpl(log, source);
+    }
+
+    /**
+     * A chain of command for providing values for {@link org.apache.tapestry.annotations.Inject}-ed
+     * fields in component classes. The service's configuration can be extended to allow for
+     * different automatic injections (based on some combination of field type and field name).
+     */
+
+    public InjectionProvider buildInjectionProvider(List<InjectionProvider> configuration)
+    {
+        return _chainBuilder.build(InjectionProvider.class, configuration);
+    }
+
+    /**
+     * Adds a number of standard workers:
+     * <ul>
+     * <li>Retain -- allows fields to retain their values between requests</li>
+     * <li>Parameter</li> -- identifies parameters based on the Parameter annotation</li>
+     * <li>UnclaimedField</li> -- identifies unclaimed fields and resets them to null/0/false at
+     * the end of the request</li>
+     * <li>SetupRender, BeginRender, etc. -- correspond to component render phases and annotations</li>
+     * </ul>
+     * 
+     * @param configuration
+     */
+    @Contribute("tapestry.ComponentClassTransformWorker")
+    public void contributeTransformWorkers(
+            OrderedConfiguration<ComponentClassTransformWorker> configuration,
+            ServiceLocator locator, @InjectService("tapestry.ioc.MasterObjectProvider")
+            ObjectProvider objectProvider, @InjectService("InjectionProvider")
+            InjectionProvider injectionProvider)
+    {
+        // TODO: Proper scheduling of all of this.
+
+        configuration.add("Inject", new InjectWorker(objectProvider, locator, injectionProvider));
+        configuration.add("Parameter", new ParameterWorker());
+
+        // Workers for the component rendering state machine methods; this is in typical
+        // execution order.
+
+        add(configuration, TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class);
+        add(configuration, TransformConstants.BEGIN_RENDER_SIGNATURE, BeginRender.class);
+        add(configuration, TransformConstants.BEFORE_RENDER_BODY_SIGNATURE, BeforeRenderBody.class);
+        add(configuration, TransformConstants.AFTER_RENDER_SIGNATURE, AfterRender.class);
+        add(configuration, TransformConstants.CLEANUP_RENDER_SIGNATURE, CleanupRender.class);
+
+        configuration.add("Retain", new RetainWorker());
+        configuration.add("UnclaimedField", new UnclaimedFieldWorker(), "after:*.*");
+    }
+
+    private void add(OrderedConfiguration<ComponentClassTransformWorker> configuration,
+            MethodSignature signature, Class<? extends Annotation> annotationClass)
+    {
+        // make the name match the annotation class name.
+
+        String name = IOCUtilities.toSimpleId(annotationClass.getName());
+
+        configuration.add(name, new ComponentLifecycleMethodWorker(signature, annotationClass));
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java Tue Sep  5 11:14:53 2006
@@ -34,6 +34,7 @@
 import org.apache.tapestry.annotations.SetupRender;
 import org.apache.tapestry.annotations.Parameter;
 import org.apache.tapestry.internal.annotations.SuppressNullCheck;
+import org.apache.tapestry.internal.services.InjectionProvider;
 import org.apache.tapestry.ioc.Configuration;
 import org.apache.tapestry.ioc.LogSource;
 import org.apache.tapestry.ioc.MappedConfiguration;
@@ -53,6 +54,7 @@
 import org.apache.tapestry.services.ClassTransformation;
 import org.apache.tapestry.services.ComponentClassResolver;
 import org.apache.tapestry.services.MethodSignature;
+import org.apache.tapestry.services.WebRequest;
 
 import static java.lang.Thread.sleep;
 import static org.apache.tapestry.internal.test.CodeEq.codeEq;
@@ -441,5 +443,22 @@
     {
         tf.findMethodsWithAnnotation(SetupRender.class);
         setReturnValue(sigs);
+    }
+
+    protected final WebRequest newWebRequest()
+    {
+        return newMock(WebRequest.class);
+    }
+
+    protected final void train_provideInjection(InjectionProvider provider, String fieldName, String fieldType, ServiceLocator locator, ClassTransformation transformation, MutableComponentModel model, boolean result)
+    {
+        provider.provideInjection(fieldName, fieldType, locator, transformation, model);
+        setReturnValue(result);
+    }
+
+    protected final void train_toClass(ClassTransformation transformation, String type, Class classForType)
+    {
+        transformation.toClass(type);
+        setReturnValue(classForType);
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties Tue Sep  5 11:14:53 2006
@@ -34,4 +34,6 @@
 may-not-nest-elements-inside-body=Element '%s' is nested within a Tapestry body element, which is not allowed.
 method-compile-error=Error compiling method %s (%s): %s
 render-queue-error=Render queue error in %s: %s
-read-only-field=Field %s.%s is read-only.
\ No newline at end of file
+read-only-field=Field %s.%s is read-only.
+no-injection-found=Could not find a suitable object to inject into %s.%s (type %s). \
+  Use the value attribute of the @Inject annotation to identify exactly what should be injected into this field.
\ No newline at end of file

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=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html Tue Sep  5 11:14:53 2006
@@ -2,26 +2,23 @@
     <head>
         <title>Tapestry 5 Integration Application 1</title>
     </head>
-    
     <body>
-        
         <p>
             <em>This page is static.</em>
         </p>
-        <p>
-            Tapestry 5 Integration Application 1:
-
-            <ul>
-                <a href="Start.html">Start Page</a>
-                <a href="MerryChristmas.html">Loop Page</a>
+        <p> Tapestry 5 Integration Application 1: <ul>
+                <li>
+                    <a href="Start.html">Start Page</a>
+                </li>
+                <li>
+                    <a href="MerryChristmas.html">Loop Page</a>
+                </li>
+                <li>
+                    <a href="InjectPage.html">Inject Page</a>
+                </li>
             </ul>
         </p>
-        
-        
-        <p>
-            Feast your eyes:            
-        </p>
-        
+        <p> Feast your eyes: </p>
         <img src="render-states1_1.png" alt="Component Render States"/>
     </body>
-</html>
\ No newline at end of file
+</html>

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml Tue Sep  5 11:14:53 2006
@@ -14,6 +14,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
+
 <suite name="Tapestry" parallel="true" thread-count="10" annotations="1.5" verbose="2">
   <test name="Tapestry Core">
     <packages>

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=440425&r1=440424&r2=440425
==============================================================================
--- 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 Sep  5 11:14:53 2006
@@ -116,6 +116,19 @@
         // Selenium is nice enough to remove the elements and excess whitespace.
 
         assertTrue(body.contains("Ho! Ho! Ho!"));
+
+        _selenium.open(BASE_URL);
+
+        _selenium.click("link=Inject Page");
+        _selenium.waitForPageToLoad(PAGE_LOAD_TIMEOUT);
+
+        body = _selenium.getBodyText();
+
+        // This is the output from the proxy for the WebRequest service, which is what's injected
+        // into and output by, the component.
+
+        assertTrue(body
+                .contains("<Proxy for tapestry.WebRequest(org.apache.tapestry.services.WebRequest)>"));
     }
 
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Loop.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Loop.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Loop.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Loop.java Tue Sep  5 11:14:53 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.integration.app1.components;
 
 import org.apache.tapestry.annotations.ComponentClass;

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/WriteWebRequest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/WriteWebRequest.java?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/WriteWebRequest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/WriteWebRequest.java Tue Sep  5 11:14:53 2006
@@ -0,0 +1,39 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.integration.app1.components;
+
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.annotations.BeginRender;
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.services.WebRequest;
+
+/**
+ * This will go away once we implement output expressions in templates.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+@ComponentClass
+public class WriteWebRequest
+{
+    @Inject("infrastructure:request")
+    private WebRequest _request;
+
+    @BeginRender
+    void writeRequest(MarkupWriter writer)
+    {
+        writer.write(_request.toString());
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InjectPage.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InjectPage.java?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InjectPage.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InjectPage.java Tue Sep  5 11:14:53 2006
@@ -0,0 +1,23 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.integration.app1.pages;
+
+import org.apache.tapestry.annotations.ComponentClass;
+
+@ComponentClass
+public class InjectPage
+{
+
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/MerryChristmas.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/MerryChristmas.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/MerryChristmas.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/MerryChristmas.java Tue Sep  5 11:14:53 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.integration.app1.pages;
 
 import org.apache.tapestry.annotations.ComponentClass;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/DefaultComponentLifecyle.java Tue Sep  5 11:14:53 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.internal.bindings;
 
 import org.apache.tapestry.ComponentResources;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java Tue Sep  5 11:14:53 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.internal.bindings;
 
 import org.apache.tapestry.Binding;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java Tue Sep  5 11:14:53 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.internal.bindings;
 
 public class TargetBean extends DefaultComponentLifecyle

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java Tue Sep  5 11:14:53 2006
@@ -0,0 +1,150 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.ioc.ObjectProvider;
+import org.apache.tapestry.ioc.ServiceLocator;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.WebRequest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public class InjectWorkerTest extends InternalBaseTestCase
+{
+
+    private static final String WEBREQUEST_CLASS_NAME = WebRequest.class.getName();
+
+    @Test
+    public void annotation_has_value()
+    {
+        ObjectProvider provider = newObjectProvider();
+        ServiceLocator locator = newServiceLocator();
+        InjectionProvider ip = newMock(InjectionProvider.class);
+        Inject annotation = newMock(Inject.class);
+        ClassTransformation ct = newClassTransformation();
+        MutableComponentModel model = newMutableComponentModel();
+        WebRequest injected = newWebRequest();
+
+        train_findFieldsWithAnnotation(ct, Inject.class, "myfield");
+        train_getFieldAnnotation(ct, "myfield", Inject.class, annotation);
+
+        train_value(annotation, "foo:Bar");
+
+        train_getFieldType(ct, "myfield", WEBREQUEST_CLASS_NAME);
+        train_toClass(ct, WEBREQUEST_CLASS_NAME, WebRequest.class);
+
+        train_provide(provider, "foo:Bar", WebRequest.class, locator, injected);
+
+        ct.injectField("myfield", injected);
+
+        ct.claimField("myfield", annotation);
+
+        replay();
+
+        InjectWorker worker = new InjectWorker(provider, locator, ip);
+
+        worker.transform(ct, model);
+
+        verify();
+    }
+
+    @Test
+    public void no_value_for_annotation()
+    {
+        ObjectProvider provider = newObjectProvider();
+        ServiceLocator locator = newServiceLocator();
+        InjectionProvider ip = newMock(InjectionProvider.class);
+        Inject annotation = newMock(Inject.class);
+        ClassTransformation ct = newClassTransformation();
+        MutableComponentModel model = newMutableComponentModel();
+
+        train_findFieldsWithAnnotation(ct, Inject.class, "myfield");
+        train_getFieldAnnotation(ct, "myfield", Inject.class, annotation);
+
+        train_value(annotation, "");
+
+        train_getFieldType(ct, "myfield", WEBREQUEST_CLASS_NAME);
+
+        train_provideInjection(ip, "myfield", WEBREQUEST_CLASS_NAME, locator, ct, model, true);
+
+        ct.claimField("myfield", annotation);
+
+        replay();
+
+        InjectWorker worker = new InjectWorker(provider, locator, ip);
+
+        worker.transform(ct, model);
+
+        verify();
+    }
+
+    @Test
+    public void anonymous_injection_not_provided()
+    {
+        ObjectProvider provider = newObjectProvider();
+        ServiceLocator locator = newServiceLocator();
+        InjectionProvider ip = newMock(InjectionProvider.class);
+        Inject annotation = newMock(Inject.class);
+        ClassTransformation ct = newClassTransformation();
+        MutableComponentModel model = newMutableComponentModel();
+
+        train_findFieldsWithAnnotation(ct, Inject.class, "myfield");
+        train_getFieldAnnotation(ct, "myfield", Inject.class, annotation);
+
+        train_value(annotation, "");
+
+        train_getFieldType(ct, "myfield", WEBREQUEST_CLASS_NAME);
+
+        train_provideInjection(ip, "myfield", WEBREQUEST_CLASS_NAME, locator, ct, model, false);
+
+        train_getClassName(ct, "foo.Baz");
+
+        replay();
+
+        InjectWorker worker = new InjectWorker(provider, locator, ip);
+
+        try
+        {
+            worker.transform(ct, model);
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertEquals(ex.getMessage(), ServicesMessages.noInjectionFound(
+                    "foo.Baz",
+                    "myfield",
+                    WEBREQUEST_CLASS_NAME));
+        }
+
+        verify();
+    }
+
+    protected void train_getClassName(ClassTransformation transformation, String className)
+    {
+        transformation.getClassName();
+        setReturnValue(className);
+    }
+
+    private void train_value(Inject annotation, String value)
+    {
+        annotation.value();
+        setReturnValue(value);
+    }
+}

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=440425&r1=440424&r2=440425
==============================================================================
--- 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 Sep  5 11:14:53 2006
@@ -19,6 +19,7 @@
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
 import javassist.ClassPool;
 import javassist.CtClass;
@@ -111,7 +112,7 @@
             throws NotFoundException
     {
         CtClass ctClass = findCtClass(targetClass);
-        return new InternalClassTransformationImpl(ctClass);
+        return new InternalClassTransformationImpl(ctClass, _contextClassLoader);
     }
 
     @Test
@@ -316,7 +317,7 @@
     }
 
     @Test
-    public void inject_field() throws Exception
+    public void add_injected_field() throws Exception
     {
         InternalComponentResources resources = newInternalComponentResources();
 
@@ -324,7 +325,11 @@
 
         CtClass targetObjectCtClass = findCtClass(TargetObject.class);
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass,
+                _contextClassLoader);
+
+        // Default behavior is to add an injected field for the InternalComponentResources object,
+        // so we'll just check that.
 
         ct.finish();
 
@@ -344,7 +349,8 @@
 
         CtClass ctClass = findCtClass(BasicComponent.class);
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(ctClass);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(ctClass,
+                _contextClassLoader);
 
         _classPool.toClass(ctClass, childLoader);
 
@@ -383,7 +389,8 @@
 
         CtClass targetObjectCtClass = findCtClass(TargetObject.class);
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass,
+                _contextClassLoader);
 
         ct.addImplementedInterface(FooInterface.class);
         ct.addImplementedInterface(GetterMethodsInterface.class);
@@ -428,7 +435,8 @@
 
         CtClass targetObjectCtClass = findCtClass(ReadOnlyBean.class);
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass,
+                _contextClassLoader);
 
         ct.makeReadOnly("_value");
 
@@ -457,6 +465,49 @@
         verify();
     }
 
+    @Test
+    public void inject_field() throws Exception
+    {
+        InternalComponentResources resources = newInternalComponentResources();
+
+        replay();
+
+        ClassLoader childLoader = newLoader();
+
+        CtClass targetObjectCtClass = findCtClass(ReadOnlyBean.class);
+
+        InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass,
+                _contextClassLoader);
+
+        ct.injectField("_value", "Tapestry");
+
+        ct.finish();
+
+        Class transformed = _classPool.toClass(targetObjectCtClass, childLoader);
+
+        Object target = ct.createInstantiator(transformed).newInstance(resources);
+
+        PropertyAccess access = new PropertyAccessImpl();
+
+        assertEquals(access.get(target, "value"), "Tapestry");
+
+        try
+        {
+            access.set(target, "value", "anything");
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            // The PropertyAccess layer adds a wrapper exception around the real one.
+
+            assertEquals(
+                    ex.getCause().getMessage(),
+                    "Field org.apache.tapestry.internal.services.ReadOnlyBean._value is read-only.");
+        }
+
+        verify();
+    }
+
     /**
      * Tests the basic functionality of overriding read and write; also tests the case for multiple
      * field read/field write substitions.
@@ -472,7 +523,8 @@
 
         CtClass targetObjectCtClass = findCtClass(FieldAccessBean.class);
 
-        InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass);
+        InternalClassTransformation ct = new InternalClassTransformationImpl(targetObjectCtClass,
+                _contextClassLoader);
 
         replaceAccessToField(ct, "foo");
         replaceAccessToField(ct, "bar");
@@ -568,5 +620,21 @@
         // Check up on no match.
 
         assertTrue(ct.findFieldsWithAnnotation(Deprecated.class).isEmpty());
+    }
+
+    @Test
+    public void to_class_with_primitive_type() throws Exception
+    {
+        ClassTransformation ct = createClassTransformation(AnnotatedPage.class);
+
+        assertSame(ct.toClass("float"), Float.class);
+    }
+
+    @Test
+    public void to_class_with_object_type() throws Exception
+    {
+        ClassTransformation ct = createClassTransformation(AnnotatedPage.class);
+
+        assertSame(ct.toClass("java.util.Map"), Map.class);
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ParameterWorkerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ParameterWorkerTest.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ParameterWorkerTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ParameterWorkerTest.java Tue Sep  5 11:14:53 2006
@@ -33,6 +33,8 @@
  */
 public class ParameterWorkerTest extends InternalBaseTestCase
 {
+    private final ClassLoader _contextClassLoader = Thread.currentThread().getContextClassLoader();
+
     private PropertyAccess _access = new PropertyAccessImpl();
 
     @AfterClass
@@ -342,7 +344,8 @@
         loader.delegateLoadingOf("org.apache.tapestry.");
 
         CtClass ctClass = pool.get(ParameterComponent.class.getName());
-        InternalClassTransformation transformation = new InternalClassTransformationImpl(ctClass);
+        InternalClassTransformation transformation = new InternalClassTransformationImpl(ctClass,
+                _contextClassLoader);
 
         MutableComponentModel model = newMutableComponentModel();
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ReadOnlyBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ReadOnlyBean.java?view=diff&rev=440425&r1=440424&r2=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ReadOnlyBean.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ReadOnlyBean.java Tue Sep  5 11:14:53 2006
@@ -1,3 +1,17 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.internal.services;
 
 import org.apache.tapestry.internal.annotations.SuppressNullCheck;

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectPage.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectPage.html?view=auto&rev=440425
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectPage.html (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectPage.html Tue Sep  5 11:14:53 2006
@@ -0,0 +1,4 @@
+<t:comp id="border" type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+    <p> Demonstrates the use of the @Inject annotation. </p>
+    <p>WebRequest: <t:comp id="request" type="WriteWebRequest"/></p>
+</t:comp>