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 2007/09/25 02:06:34 UTC

svn commit: r579020 [1/2] - in /tapestry/tapestry5/trunk: tapestry-core/src/main/java/org/apache/tapestry/internal/services/ tapestry-core/src/main/java/org/apache/tapestry/services/ tapestry-core/src/main/java/org/apache/tapestry/test/ tapestry-core/s...

Author: hlship
Date: Mon Sep 24 17:06:31 2007
New Revision: 579020

URL: http://svn.apache.org/viewvc?rev=579020&view=rev
Log:
TAPESTRY-1731: @Inject @Symbol does not work inside a component

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/BlockInjectionProvider.java
      - copied, changed from r578523, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectBlockWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultInjectWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultInjectionProvider.java
      - copied, changed from r578523, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java
      - copied, changed from r578523, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectResourcesWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServiceInjectionProvider.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/BlockInjectionProviderTest.java
      - copied, changed from r578523, tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectBlockWorkerTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/DefaultInjectionProviderTest.java
      - copied, changed from r578523, tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java
      - copied, changed from r578523, tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectResourcesWorkerTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/MasterObjectProviderImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/services/
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/services/MasterObjectProvider.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/MasterObjectProviderImplTest.java
Removed:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectBlockWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectResourcesWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectBlockWorkerTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectResourcesWorkerTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/transform/pages/FindFieldClass.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetInjectionProvider.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CommonResourcesInjectionProvider.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentResourcesInjectionProvider.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ClassTransformation.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/InjectionProvider.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/InjectDemo.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/AppModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/AssetInjectionProviderTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectDemo.html
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ObjectProvider.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetInjectionProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetInjectionProvider.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetInjectionProvider.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetInjectionProvider.java Mon Sep 24 17:06:31 2007
@@ -40,7 +40,7 @@
         _assetSource = assetSource;
     }
 
-    public boolean provideInjection(String fieldName, String fieldType, ObjectLocator locator,
+    public boolean provideInjection(String fieldName, Class fieldType, ObjectLocator locator,
             ClassTransformation transformation, MutableComponentModel componentModel)
     {
         Path path = transformation.getFieldAnnotation(fieldName, Path.class);
@@ -58,7 +58,7 @@
         String statement = format(
                 "%s = (%s) %s.findAsset(%s.getBaseResource(), \"%s\", %s.getLocale());",
                 fieldName,
-                fieldType,
+                fieldType.getName(),
                 sourceFieldName,
                 resourcesFieldName,
                 expanded,

Copied: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/BlockInjectionProvider.java (from r578523, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectBlockWorker.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/BlockInjectionProvider.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/BlockInjectionProvider.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectBlockWorker.java&r1=578523&r2=579020&rev=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectBlockWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/BlockInjectionProvider.java Mon Sep 24 17:06:31 2007
@@ -14,70 +14,49 @@
 
 package org.apache.tapestry.internal.services;
 
-import java.util.List;
-
 import org.apache.tapestry.Block;
 import org.apache.tapestry.annotations.Id;
 import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.ioc.ObjectLocator;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
-import org.apache.tapestry.ioc.util.BodyBuilder;
 import org.apache.tapestry.model.MutableComponentModel;
 import org.apache.tapestry.services.ClassTransformation;
-import org.apache.tapestry.services.ComponentClassTransformWorker;
+import org.apache.tapestry.services.InjectionProvider;
 import org.apache.tapestry.services.TransformConstants;
 
 /**
  * Identifies fields of type {@link Block} that have the {@link Inject} annotation and converts them
  * into read-only fields containing the injected Block from the template. The annotation's value is
- * the id of the block to inject; if ommitted, the block id is deduced from the field id.
+ * the id of the block to inject; if omitted, the block id is deduced from the field id.
  * <p>
- * Must be scheduled before {@link InjectWorker} because it uses the same annotation, Inject, with a
- * different interpretation.
+ * Must be scheduled before {@link DefaultInjectionProvider} because it uses the same annotation,
+ * Inject, with a different interpretation.
  */
-public class InjectBlockWorker implements ComponentClassTransformWorker
+public class BlockInjectionProvider implements InjectionProvider
 {
-    static final String BLOCK_TYPE_NAME = Block.class.getName();
 
-    public void transform(ClassTransformation transformation, MutableComponentModel model)
+    public boolean provideInjection(String fieldName, Class fieldType, ObjectLocator locator,
+            ClassTransformation transformation, MutableComponentModel componentModel)
     {
-        List<String> fieldNames = transformation.findFieldsOfType(BLOCK_TYPE_NAME);
-
-        if (fieldNames.isEmpty()) return;
-
-        BodyBuilder builder = new BodyBuilder();
-        builder.begin();
-
-        int count = 0;
+        if (!fieldType.equals(Block.class)) return false;
 
         String resourcesFieldName = transformation.getResourcesFieldName();
 
-        for (String fieldName : fieldNames)
-        {
-            Inject injectAnnotation = transformation.getFieldAnnotation(fieldName, Inject.class);
-
-            if (injectAnnotation == null) continue;
-
-            Id annotation = transformation.getFieldAnnotation(fieldName, Id.class);
-
-            String blockId = getBlockId(fieldName, annotation);
-
-            builder.addln("%s = %s.getBlock(\"%s\");", fieldName, resourcesFieldName, blockId);
-
-            transformation.makeReadOnly(fieldName);
-
-            transformation.claimField(fieldName, injectAnnotation);
+        Id annotation = transformation.getFieldAnnotation(fieldName, Id.class);
 
-            count++;
-        }
+        String blockId = getBlockId(fieldName, annotation);
 
-        // Fields yes, but no annotations, so nothing to really do.
+        transformation.makeReadOnly(fieldName);
 
-        if (count == 0) return;
+        String body = String.format(
+                "%s = %s.getBlock(\"%s\");",
+                fieldName,
+                resourcesFieldName,
+                blockId);
 
-        builder.end();
+        transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, body);
 
-        transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, builder
-                .toString());
+        return true; // claim the field
     }
 
     private String getBlockId(String fieldName, Id annotation)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CommonResourcesInjectionProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CommonResourcesInjectionProvider.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CommonResourcesInjectionProvider.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CommonResourcesInjectionProvider.java Mon Sep 24 17:06:31 2007
@@ -31,7 +31,7 @@
  */
 public class CommonResourcesInjectionProvider implements InjectionProvider
 {
-    private static final Map<String, String> _configuration = newMap();
+    private static final Map<Class, String> _configuration = newMap();
 
     public CommonResourcesInjectionProvider()
     {
@@ -43,16 +43,15 @@
 
     private void add(Class fieldType, String methodName)
     {
-        _configuration.put(fieldType.getName(), methodName);
+        _configuration.put(fieldType, methodName);
     }
 
-    public boolean provideInjection(String fieldName, String fieldType, ObjectLocator locator,
+    public boolean provideInjection(String fieldName, Class fieldType, ObjectLocator locator,
             ClassTransformation transformation, MutableComponentModel componentModel)
     {
         String implementationMethodName = _configuration.get(fieldType);
 
-        if (implementationMethodName == null)
-            return false;
+        if (implementationMethodName == null) return false;
 
         String resourcesField = transformation.getResourcesFieldName();
 
@@ -68,5 +67,4 @@
 
         return true;
     }
-
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentResourcesInjectionProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentResourcesInjectionProvider.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentResourcesInjectionProvider.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentResourcesInjectionProvider.java Mon Sep 24 17:06:31 2007
@@ -27,12 +27,10 @@
  */
 public class ComponentResourcesInjectionProvider implements InjectionProvider
 {
-    private static final String COMPONENT_RESOURCES_CLASS_NAME = ComponentResources.class.getName();
-
-    public boolean provideInjection(String fieldName, String fieldType, ObjectLocator locator,
+    public boolean provideInjection(String fieldName, Class fieldType, ObjectLocator locator,
             ClassTransformation transformation, MutableComponentModel componentModel)
     {
-        if (fieldType.equals(COMPONENT_RESOURCES_CLASS_NAME))
+        if (fieldType.equals(ComponentResources.class))
         {
             String body = format("%s = %s;", fieldName, transformation.getResourcesFieldName());
 

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultInjectWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultInjectWorker.java?rev=579020&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultInjectWorker.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultInjectWorker.java Mon Sep 24 17:06:31 2007
@@ -0,0 +1,70 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.ioc.ObjectLocator;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassTransformWorker;
+
+/**
+ * Worker triggered by {@link Inject} annotation after all other injection related works have had a
+ * chance. This implementation is just a wrapper around {@link ObjectLocator#getService(Class)}.
+ */
+public class DefaultInjectWorker implements ComponentClassTransformWorker
+{
+    private final ObjectLocator _locator;
+
+    public DefaultInjectWorker(ObjectLocator locator)
+    {
+        _locator = locator;
+    }
+
+    public void transform(ClassTransformation transformation, MutableComponentModel model)
+    {
+        for (String fieldName : transformation.findFieldsWithAnnotation(Inject.class))
+        {
+            Inject annotation = transformation.getFieldAnnotation(fieldName, Inject.class);
+
+            inject(fieldName, transformation, model);
+
+            transformation.claimField(fieldName, annotation);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void inject(String fieldName, ClassTransformation transformation,
+            MutableComponentModel model)
+    {
+        String fieldType = transformation.getFieldType(fieldName);
+
+        Class type = transformation.toClass(fieldType);
+
+        try
+        {
+            Object inject = _locator.getService(type);
+
+            transformation.injectField(fieldName, inject);
+        }
+        catch (Exception ex)
+        {
+            throw new RuntimeException(ServicesMessages.fieldInjectionError(transformation
+                    .getClassName(), fieldName, ex), ex);
+        }
+
+    }
+
+}

Copied: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultInjectionProvider.java (from r578523, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultInjectionProvider.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultInjectionProvider.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java&r1=578523&r2=579020&rev=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultInjectionProvider.java Mon Sep 24 17:06:31 2007
@@ -16,55 +16,37 @@
 
 import java.lang.annotation.Annotation;
 
-import org.apache.tapestry.annotations.Inject;
 import org.apache.tapestry.ioc.AnnotationProvider;
-import org.apache.tapestry.ioc.ObjectProvider;
 import org.apache.tapestry.ioc.ObjectLocator;
 import org.apache.tapestry.model.MutableComponentModel;
 import org.apache.tapestry.services.ClassTransformation;
-import org.apache.tapestry.services.ComponentClassTransformWorker;
+import org.apache.tapestry.services.InjectionProvider;
+import org.apache.tapestry.services.MasterObjectProvider;
 
 /**
  * Worker for the {@link org.apache.tapestry.annotations.Inject} annotation that delegates out to
- * the master {@link ObjectProvider} to access the value. This worker must be scheduled after
+ * the master {@link MasterObjectProvier} to access the value. This worker must be scheduled after
  * certain other workers, such as {@link InjectBlockWorker} (which is keyed off a combination of
  * type and the Inject annotation).
  * 
- * @see ObjectProvider
+ * @see MasterObjectProvier
  */
-public class InjectWorker implements ComponentClassTransformWorker
+public class DefaultInjectionProvider implements InjectionProvider
 {
-    private final ObjectProvider _objectProvider;
+    private final MasterObjectProvider _masterObjectProvider;
 
     private final ObjectLocator _locator;
 
-    public InjectWorker(ObjectProvider objectProvider, ObjectLocator locator)
+    public DefaultInjectionProvider(MasterObjectProvider masterObjectProvider, ObjectLocator locator)
     {
-        _objectProvider = objectProvider;
+        _masterObjectProvider = masterObjectProvider;
         _locator = locator;
     }
 
-    public void transform(ClassTransformation transformation, MutableComponentModel model)
-    {
-        for (String fieldName : transformation.findFieldsWithAnnotation(Inject.class))
-        {
-            Inject annotation = transformation.getFieldAnnotation(fieldName, Inject.class);
-
-            inject(fieldName, transformation, model);
-
-            transformation.claimField(fieldName, annotation);
-        }
-
-    }
-
     @SuppressWarnings("unchecked")
-    private void inject(final String fieldName, final ClassTransformation transformation,
-            MutableComponentModel model)
+    public boolean provideInjection(final String fieldName, Class fieldType, ObjectLocator locator,
+            final ClassTransformation transformation, MutableComponentModel componentModel)
     {
-        String fieldType = transformation.getFieldType(fieldName);
-
-        Class type = transformation.toClass(fieldType);
-
         AnnotationProvider annotationProvider = new AnnotationProvider()
         {
             public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
@@ -73,19 +55,22 @@
             }
         };
 
-        Object inject = null;
+        Object inject = _masterObjectProvider.provide(
+                fieldType,
+                annotationProvider,
+                _locator,
+                false);
+
+        // Null means that no ObjectProvider could provide the value. We have set up the chain of
+        // command so that InjectResources can give it a try next. Later, we'll try to match against
+        // a service.
 
-        try
+        if (inject != null)
         {
-            inject = _objectProvider.provide(type, annotationProvider, _locator);
-        }
-        catch (Exception ex)
-        {
-            throw new RuntimeException(ServicesMessages.fieldInjectionError(transformation
-                    .getClassName(), fieldName, ex), ex);
+            transformation.injectField(fieldName, inject);
+            return true;
         }
 
-        transformation.injectField(fieldName, inject);
+        return false;
     }
-
 }

Copied: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java (from r578523, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectResourcesWorker.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectResourcesWorker.java&r1=578523&r2=579020&rev=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectResourcesWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java Mon Sep 24 17:06:31 2007
@@ -22,14 +22,12 @@
 import org.apache.tapestry.services.InjectionProvider;
 
 /**
- * Performs injection of resources, for the cases where a field is labled with the {@link Inject}
- * annotation, but no specific value was provided. This worker must be scheduled <em>before</em>
- * {@link InjectWorker}.
+ * Performs injection triggered by any field annotated with the {@link Inject} annotation.
  * <p>
  * The implementation of this worker mostly delegates to a chain of command of
  * {@link InjectionProvider}s.
  */
-public class InjectResourcesWorker implements ComponentClassTransformWorker
+public class InjectWorker implements ComponentClassTransformWorker
 {
     private final ObjectLocator _locator;
 
@@ -37,33 +35,40 @@
 
     private final InjectionProvider _injectionProvider;
 
-    public InjectResourcesWorker(final ObjectLocator locator,
+    public InjectWorker(final ObjectLocator locator,
             final InjectionProvider injectionProvider)
     {
         _locator = locator;
         _injectionProvider = injectionProvider;
     }
 
-    public void transform(ClassTransformation transformation, MutableComponentModel model)
+    public final void transform(ClassTransformation transformation, MutableComponentModel model)
     {
         for (String fieldName : transformation.findFieldsWithAnnotation(Inject.class))
         {
             Inject annotation = transformation.getFieldAnnotation(fieldName, Inject.class);
 
-            String fieldType = transformation.getFieldType(fieldName);
+            try
+            {
+                String fieldType = transformation.getFieldType(fieldName);
+
+                Class type = transformation.toClass(fieldType);
+
+                boolean success = _injectionProvider.provideInjection(
+                        fieldName,
+                        type,
+                        _locator,
+                        transformation,
+                        model);
+
+                if (success) transformation.claimField(fieldName, annotation);
+            }
+            catch (RuntimeException ex)
+            {
+                throw new RuntimeException(ServicesMessages.fieldInjectionError(transformation
+                        .getClassName(), fieldName, ex), ex);
+            }
 
-            boolean result = _injectionProvider.provideInjection(
-                    fieldName,
-                    fieldType,
-                    _locator,
-                    transformation,
-                    model);
-
-            // If true, claim the field; otherwise ignore it (it will be handled by a later
-            // worker and an exception will be thrown if it ultimately can't be satisfied.
-
-            if (result) transformation.claimField(fieldName, annotation);
         }
     }
-
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java Mon Sep 24 17:06:31 2007
@@ -151,8 +151,9 @@
                 "resources",
                 null);
 
-        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PUBLIC | Modifier.FINAL,
-                ComponentResources.class.getName(), "getComponentResources", null, null);
+        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PUBLIC
+                | Modifier.FINAL, ComponentResources.class.getName(), "getComponentResources",
+                null, null);
 
         addMethod(sig, "return " + _resourcesFieldName + ";");
     }
@@ -816,19 +817,6 @@
         return result;
     }
 
-    public List<String> findFieldsOfType(final String type)
-    {
-        FieldFilter filter = new FieldFilter()
-        {
-            public boolean accept(String fieldName, String fieldType)
-            {
-                return type.equals(fieldType);
-            }
-        };
-
-        return findFields(filter);
-    }
-
     public List<TransformMethodSignature> findMethodsWithAnnotation(
             Class<? extends Annotation> annotationClass)
     {
@@ -881,8 +869,8 @@
                 String[] parameters = toTypeNames(method.getParameterTypes());
                 String[] exceptions = toTypeNames(method.getExceptionTypes());
 
-                result = new TransformMethodSignature(method.getModifiers(), type, method.getName(),
-                        parameters, exceptions);
+                result = new TransformMethodSignature(method.getModifiers(), type,
+                        method.getName(), parameters, exceptions);
 
                 _methodSignatures.put(method, result);
             }
@@ -1331,8 +1319,8 @@
 
         String fieldType = getFieldType(fieldName);
 
-        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PRIVATE, "void", methodName,
-                new String[]
+        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PRIVATE, "void",
+                methodName, new String[]
                 { fieldType }, null);
 
         String message = ServicesMessages.readOnlyField(_ctClass.getName(), fieldName);

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServiceInjectionProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServiceInjectionProvider.java?rev=579020&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServiceInjectionProvider.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServiceInjectionProvider.java Mon Sep 24 17:06:31 2007
@@ -0,0 +1,52 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.ioc.ObjectLocator;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.InjectionProvider;
+
+/**
+ * A very late worker related to the {@link Inject} annotation that, when all other forms of
+ * injection have failed, matches the field type to a service interface.
+ */
+public class ServiceInjectionProvider implements InjectionProvider
+{
+    private final ObjectLocator _locator;
+
+    public ServiceInjectionProvider(ObjectLocator locator)
+    {
+        _locator = locator;
+    }
+
+    @SuppressWarnings("unchecked")
+    public boolean provideInjection(String fieldName, Class fieldType, ObjectLocator locator,
+            ClassTransformation transformation, MutableComponentModel componentModel)
+    {
+        Object inject = _locator.getService(fieldType);
+
+        assert inject != null;
+
+        transformation.injectField(fieldName, inject);
+
+        // If we make it this far without an exception, then we were successful
+        // and should claim the field.
+
+        return true;
+    }
+
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ClassTransformation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ClassTransformation.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ClassTransformation.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/ClassTransformation.java Mon Sep 24 17:06:31 2007
@@ -76,12 +76,6 @@
      */
     List<String> findFieldsWithAnnotation(Class<? extends Annotation> annotationClass);
 
-    /**
-     * Generates a list of the names of declared instance fields that exactly match the specified
-     * type. Only the names of private instance fields are returned. Any
-     * {@link #claimField(String, Object) claimed} fields are excluded.
-     */
-    List<String> findFieldsOfType(String type);
 
     /**
      * Finds all methods defined in the class that are marked with the provided annotation.

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/InjectionProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/InjectionProvider.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/InjectionProvider.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/InjectionProvider.java Mon Sep 24 17:06:31 2007
@@ -12,41 +12,39 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.services;
-
-import org.apache.tapestry.ioc.ObjectLocator;
-import org.apache.tapestry.model.MutableComponentModel;
-
-/**
- * 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}.
- * 
- * 
- */
-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, ObjectLocator locator,
-            ClassTransformation transformation, MutableComponentModel componentModel);
-}
+package org.apache.tapestry.services;
+
+import org.apache.tapestry.ioc.ObjectLocator;
+import org.apache.tapestry.model.MutableComponentModel;
+
+/**
+ * Provides some form of injection when the value for an
+ * {@link org.apache.tapestry.annotations.Inject} annotation is present. 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}.
+ */
+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
+     * @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, Class fieldType, ObjectLocator locator,
+            ClassTransformation transformation, MutableComponentModel componentModel);
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java Mon Sep 24 17:06:31 2007
@@ -80,6 +80,7 @@
 import org.apache.tapestry.internal.services.BeanBlockSourceImpl;
 import org.apache.tapestry.internal.services.BeanModelSourceImpl;
 import org.apache.tapestry.internal.services.BindingSourceImpl;
+import org.apache.tapestry.internal.services.BlockInjectionProvider;
 import org.apache.tapestry.internal.services.ClassResultProcessor;
 import org.apache.tapestry.internal.services.ClasspathAssetAliasManagerImpl;
 import org.apache.tapestry.internal.services.CommonResourcesInjectionProvider;
@@ -97,6 +98,7 @@
 import org.apache.tapestry.internal.services.ContextImpl;
 import org.apache.tapestry.internal.services.CookiesImpl;
 import org.apache.tapestry.internal.services.DefaultDataTypeAnalyzer;
+import org.apache.tapestry.internal.services.DefaultInjectionProvider;
 import org.apache.tapestry.internal.services.DefaultValidationDelegateCommand;
 import org.apache.tapestry.internal.services.DocumentScriptBuilder;
 import org.apache.tapestry.internal.services.DocumentScriptBuilderImpl;
@@ -109,12 +111,11 @@
 import org.apache.tapestry.internal.services.FlashPersistentFieldStrategy;
 import org.apache.tapestry.internal.services.GenericValueEncoderFactory;
 import org.apache.tapestry.internal.services.HeartbeatImpl;
-import org.apache.tapestry.internal.services.InjectBlockWorker;
 import org.apache.tapestry.internal.services.InjectComponentWorker;
 import org.apache.tapestry.internal.services.InjectPageWorker;
-import org.apache.tapestry.internal.services.InjectResourcesWorker;
-import org.apache.tapestry.internal.services.InjectStandardStylesheetCommand;
 import org.apache.tapestry.internal.services.InjectWorker;
+import org.apache.tapestry.internal.services.ServiceInjectionProvider;
+import org.apache.tapestry.internal.services.InjectStandardStylesheetCommand;
 import org.apache.tapestry.internal.services.InternalModule;
 import org.apache.tapestry.internal.services.LinkActionResponseGenerator;
 import org.apache.tapestry.internal.services.LinkFactory;
@@ -386,9 +387,6 @@
 
             ObjectLocator locator,
 
-            @InjectService("MasterObjectProvider")
-            ObjectProvider objectProvider,
-
             InjectionProvider injectionProvider,
 
             Environment environment,
@@ -403,6 +401,8 @@
 
             BindingSource bindingsource,
 
+            MasterObjectProvider masterObjectProvider,
+
             ApplicationStateManager applicationStateManager)
     {
         // TODO: Proper scheduling of all of this. Since a given field or method should
@@ -411,17 +411,8 @@
 
         configuration.add("Meta", new MetaWorker());
         configuration.add("ApplicationState", new ApplicationStateWorker(applicationStateManager));
-        configuration.add("Inject", new InjectWorker(objectProvider, locator));
 
-        // These next two "reinterpret" what @Inject does (in the presence of
-        // a particular field type and must come before the normal Inject annotation
-        // processing.
-
-        configuration.add(
-                "InjectResources",
-                new InjectResourcesWorker(locator, injectionProvider),
-                "before:Inject");
-        configuration.add("InjectBlock", new InjectBlockWorker(), "before:Inject");
+        configuration.add("Inject", new InjectWorker(locator, injectionProvider));
 
         configuration.add("MixinAfter", new MixinAfterWorker());
         configuration.add("Component", new ComponentWorker(resolver));
@@ -470,8 +461,7 @@
         add(configuration, TransformConstants.CLEANUP_RENDER_SIGNATURE, CleanupRender.class, true);
 
         // Ideally, these should be ordered pretty late in the process to make sure there are no
-        // side effects
-        // with other workers that do work inside the page lifecycle methods.
+        // side effects with other workers that do work inside the page lifecycle methods.
 
         add(
                 configuration,
@@ -491,6 +481,10 @@
 
         configuration.add("Retain", new RetainWorker());
         configuration.add("Persist", new PersistWorker());
+
+        // This one is always last. Any additional private fields that aren't annotated will
+        // be converted to clear out at the end of the request.
+
         configuration.add("UnclaimedField", new UnclaimedFieldWorker(), "after:*");
     }
 
@@ -526,8 +520,7 @@
         configuration.add(String.class, "text");
 
         // This may change; as currently implemented, "text" refers more to the edit component
-        // (TextField) than to
-        // the "flavor" of data.
+        // (TextField) than to the "flavor" of data.
 
         configuration.add(Number.class, "text");
         configuration.add(Enum.class, "enum");
@@ -579,24 +572,51 @@
     }
 
     /**
-     * Contributes the elemental providers:
+     * Contributes the base set of injection providers:
      * <ul>
+     * <li>Default -- based on {@link MasterObjectProvider}</li>
+     * <li>Block -- injects fields of type Block</li>
      * <li>ComponentResources -- give component access to its resources</li>
      * <li>CommonResources -- access to properties of resources (log, messages, etc.)</li>
      * <li>Asset -- injection of assets (triggered via {@link Path} annotation), with the path
      * relative to the component class</li>
+     * <li>Service -- ordered last, for use when Inject is present and nothing else works, matches
+     * field type against Tapestry IoC service</li>
      * </ul>
      */
     public static void contributeInjectionProvider(
             OrderedConfiguration<InjectionProvider> configuration,
 
+            MasterObjectProvider masterObjectProvider,
+
+            ObjectLocator locator,
+
             SymbolSource symbolSource,
 
             AssetSource assetSource)
     {
+        configuration.add("Default", new DefaultInjectionProvider(masterObjectProvider, locator));
+
         configuration.add("ComponentResources", new ComponentResourcesInjectionProvider());
-        configuration.add("CommonResources", new CommonResourcesInjectionProvider());
-        configuration.add("Asset", new AssetInjectionProvider(symbolSource, assetSource));
+
+        // This comes after default, to deal with conflicts between injecting a String as the
+        // component id, and injecting a string with @Symbol or @Value.
+
+        configuration.add(
+                "CommonResources",
+                new CommonResourcesInjectionProvider(),
+                "after:Default");
+
+        configuration.add(
+                "Asset",
+                new AssetInjectionProvider(symbolSource, assetSource),
+                "before:Default");
+
+        configuration.add("Block", new BlockInjectionProvider(), "before:Default");
+
+        // This needs to be the last one, since it matches against services
+        // and might blow up if there is no match.
+        configuration.add("Service", new ServiceInjectionProvider(locator), "after:*");
     }
 
     /**
@@ -828,8 +848,8 @@
     }
 
     private static void add(OrderedConfiguration<ComponentClassTransformWorker> configuration,
-            Class<? extends Annotation> annotationClass, TransformMethodSignature lifecycleMethodSignature,
-            String methodAlias)
+            Class<? extends Annotation> annotationClass,
+            TransformMethodSignature lifecycleMethodSignature, String methodAlias)
     {
         ComponentClassTransformWorker worker = new PageLifecycleAnnotationWorker(annotationClass,
                 lifecycleMethodSignature, methodAlias);
@@ -840,7 +860,8 @@
     }
 
     private static void add(OrderedConfiguration<ComponentClassTransformWorker> configuration,
-            TransformMethodSignature signature, Class<? extends Annotation> annotationClass, boolean reverse)
+            TransformMethodSignature signature, Class<? extends Annotation> annotationClass,
+            boolean reverse)
     {
         // make the name match the annotation class name.
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java Mon Sep 24 17:06:31 2007
@@ -86,12 +86,12 @@
 import org.apache.tapestry.services.Heartbeat;
 import org.apache.tapestry.services.InjectionProvider;
 import org.apache.tapestry.services.MethodFilter;
-import org.apache.tapestry.services.TransformMethodSignature;
 import org.apache.tapestry.services.Request;
 import org.apache.tapestry.services.RequestHandler;
 import org.apache.tapestry.services.ResourceDigestGenerator;
 import org.apache.tapestry.services.Response;
 import org.apache.tapestry.services.Session;
+import org.apache.tapestry.services.TransformMethodSignature;
 import org.apache.tapestry.services.ValidationConstraintGenerator;
 import org.apache.tapestry.services.ValidationMessagesSource;
 import org.easymock.EasyMock;
@@ -454,12 +454,6 @@
         expect(source.findAsset(root, path, locale)).andReturn(asset);
     }
 
-    protected final void train_findFieldsOfType(ClassTransformation transformation, String type,
-            String... fieldNames)
-    {
-        expect(transformation.findFieldsOfType(type)).andReturn(Arrays.asList(fieldNames));
-    }
-
     protected final void train_findFieldsWithAnnotation(ClassTransformation transformation,
             Class<? extends Annotation> annotationClass, List<String> fieldNames)
     {
@@ -854,7 +848,7 @@
     }
 
     protected final void train_provideInjection(InjectionProvider provider, String fieldName,
-            String fieldType, ObjectLocator locator, ClassTransformation transformation,
+            Class fieldType, ObjectLocator locator, ClassTransformation transformation,
             MutableComponentModel model, boolean result)
     {
         expect(provider.provideInjection(fieldName, fieldType, locator, transformation, model))

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/InjectDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/InjectDemo.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/InjectDemo.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/InjectDemo.java Mon Sep 24 17:06:31 2007
@@ -18,16 +18,21 @@
 import org.apache.tapestry.annotations.Inject;
 import org.apache.tapestry.annotations.InjectPage;
 import org.apache.tapestry.annotations.OnEvent;
+import org.apache.tapestry.ioc.annotations.Symbol;
 import org.apache.tapestry.services.BindingSource;
 import org.apache.tapestry.services.Request;
 
 public class InjectDemo
 {
     // Named --- now demonstrating case insensitivity
-    // Now vestigal! 
+    // Now vestigial!
     @Inject
     private Request _request;
 
+    @Inject
+    @Symbol("app.injected-symbol")
+    private String _injectedSymbol;
+
     // Via ComponentResourcesInjectionProvider
     @Inject
     private ComponentResources _resources;
@@ -75,5 +80,10 @@
     String clickWilma()
     {
         return "Wilma";
+    }
+
+    public String getInjectedSymbol()
+    {
+        return _injectedSymbol;
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/AppModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/AppModule.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/AppModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/services/AppModule.java Mon Sep 24 17:06:31 2007
@@ -84,6 +84,7 @@
             MappedConfiguration<String, String> configuration)
     {
         configuration.add("tapestry.supported-locales", "en,fr");
+        configuration.add("app.injected-symbol", "Symbol contributed to ApplicationDefaults");
     }
 
     public ToDoDatabase buildToDoDatabase()

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/AssetInjectionProviderTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/AssetInjectionProviderTest.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/AssetInjectionProviderTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/AssetInjectionProviderTest.java Mon Sep 24 17:06:31 2007
@@ -36,7 +36,6 @@
         MutableComponentModel model = mockMutableComponentModel();
 
         String fieldName = "myField";
-        String fieldType = "java.lang.String";
 
         train_getFieldAnnotation(ct, fieldName, Path.class, null);
 
@@ -44,7 +43,7 @@
 
         InjectionProvider provider = new AssetInjectionProvider(symbolSource, assetSource);
 
-        assertFalse(provider.provideInjection(fieldName, fieldType, locator, ct, model));
+        assertFalse(provider.provideInjection(fieldName, String.class, locator, ct, model));
 
         verify();
     }
@@ -60,7 +59,7 @@
         Path annotation = mockPath();
 
         String fieldName = "myField";
-        String fieldType = "java.lang.Object";
+        Class fieldType = Object.class;
         String value = "${foo}";
         String expanded = "foo.gif";
 

Copied: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/BlockInjectionProviderTest.java (from r578523, tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectBlockWorkerTest.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/BlockInjectionProviderTest.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/BlockInjectionProviderTest.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectBlockWorkerTest.java&r1=578523&r2=579020&rev=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectBlockWorkerTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/BlockInjectionProviderTest.java Mon Sep 24 17:06:31 2007
@@ -14,49 +14,30 @@
 
 package org.apache.tapestry.internal.services;
 
+import org.apache.tapestry.Block;
 import org.apache.tapestry.annotations.Id;
-import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.ioc.ObjectLocator;
 import org.apache.tapestry.model.MutableComponentModel;
 import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.InjectionProvider;
 import org.apache.tapestry.services.TransformConstants;
 import org.apache.tapestry.test.TapestryTestCase;
 import org.testng.annotations.Test;
 
-/**
- * Tests a couple of edge cases where there's nothing to inject.
- */
-public class InjectBlockWorkerTest extends TapestryTestCase
+public class BlockInjectionProviderTest extends TapestryTestCase
 {
     @Test
-    public void no_fields_of_type_block()
+    public void not_type_block()
     {
         ClassTransformation ct = mockClassTransformation();
         MutableComponentModel model = mockMutableComponentModel();
-
-        train_findFieldsOfType(ct, InjectBlockWorker.BLOCK_TYPE_NAME);
+        ObjectLocator locator = mockObjectLocator();
 
         replay();
 
-        new InjectBlockWorker().transform(ct, model);
-
-        verify();
-    }
-
-    @Test
-    public void field_missing_annotation()
-    {
-        ClassTransformation ct = mockClassTransformation();
-        MutableComponentModel model = mockMutableComponentModel();
-
-        train_findFieldsOfType(ct, InjectBlockWorker.BLOCK_TYPE_NAME, "fred");
+        InjectionProvider provider = new BlockInjectionProvider();
 
-        train_getResourcesFieldName(ct, "rez");
-
-        train_getFieldAnnotation(ct, "fred", Inject.class, null);
-
-        replay();
-
-        new InjectBlockWorker().transform(ct, model);
+        assertFalse(provider.provideInjection("myfield", Object.class, locator, ct, model));
 
         verify();
     }
@@ -71,51 +52,68 @@
      * generated code is valid and works.
      */
     @Test
-    public void fields_with_annotations()
+    public void explicit_block_id_provided_as_annotation()
     {
         ClassTransformation ct = mockClassTransformation();
         MutableComponentModel model = mockMutableComponentModel();
-        Inject fredAnnotation = mockInject();
-        Inject barneyAnnotation = mockInject();
+        ObjectLocator locator = mockObjectLocator();
         Id barneyId = newId();
 
         String barneyFieldName = "_barneyBlock";
-        String fredFieldName = "fred";
 
-        train_findFieldsOfType(
+        train_getResourcesFieldName(ct, "rez");
+
+        train_getFieldAnnotation(ct, barneyFieldName, Id.class, barneyId);
+
+        train_value(barneyId, "barney");
+
+        ct.makeReadOnly(barneyFieldName);
+
+        train_extendMethod(
                 ct,
-                InjectBlockWorker.BLOCK_TYPE_NAME,
-                fredFieldName,
-                barneyFieldName);
+                TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE,
+                "_barneyBlock = rez.getBlock(\"barney\");");
 
-        train_getResourcesFieldName(ct, "rez");
+        replay();
 
-        train_getFieldAnnotation(ct, fredFieldName, Inject.class, fredAnnotation);
+        assertTrue(new BlockInjectionProvider().provideInjection(
+                barneyFieldName,
+                Block.class,
+                locator,
+                ct,
+                model));
 
-        train_getFieldAnnotation(ct, fredFieldName, Id.class, null);
+        verify();
+    }
 
-        ct.makeReadOnly(fredFieldName);
-        ct.claimField(fredFieldName, fredAnnotation);
+    @Test
+    public void default_id_for_block_from_field_name()
+    {
+        ClassTransformation ct = mockClassTransformation();
+        MutableComponentModel model = mockMutableComponentModel();
+        ObjectLocator locator = mockObjectLocator();
 
-        train_getFieldAnnotation(ct, barneyFieldName, Inject.class, barneyAnnotation);
-        train_getFieldAnnotation(ct, barneyFieldName, Id.class, barneyId);
+        String barneyFieldName = "_barney";
 
-        train_value(barneyId, "barney");
+        train_getResourcesFieldName(ct, "rez");
+
+        train_getFieldAnnotation(ct, barneyFieldName, Id.class, null);
 
         ct.makeReadOnly(barneyFieldName);
-        ct.claimField(barneyFieldName, barneyAnnotation);
 
         train_extendMethod(
                 ct,
                 TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE,
-                "{",
-                "fred = rez.getBlock(\"fred\");",
-                "_barneyBlock = rez.getBlock(\"barney\");",
-                "}");
+                "_barney = rez.getBlock(\"barney\");");
 
         replay();
 
-        new InjectBlockWorker().transform(ct, model);
+        assertTrue(new BlockInjectionProvider().provideInjection(
+                barneyFieldName,
+                Block.class,
+                locator,
+                ct,
+                model));
 
         verify();
     }

Copied: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/DefaultInjectionProviderTest.java (from r578523, tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/DefaultInjectionProviderTest.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/DefaultInjectionProviderTest.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java&r1=578523&r2=579020&rev=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/DefaultInjectionProviderTest.java Mon Sep 24 17:06:31 2007
@@ -17,88 +17,64 @@
 import static org.easymock.EasyMock.eq;
 import static org.easymock.EasyMock.isA;
 
-import org.apache.tapestry.annotations.Inject;
 import org.apache.tapestry.internal.test.InternalBaseTestCase;
 import org.apache.tapestry.ioc.AnnotationProvider;
-import org.apache.tapestry.ioc.ObjectProvider;
 import org.apache.tapestry.ioc.ObjectLocator;
 import org.apache.tapestry.model.MutableComponentModel;
 import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.MasterObjectProvider;
 import org.apache.tapestry.services.Request;
 import org.testng.annotations.Test;
 
-public class InjectWorkerTest extends InternalBaseTestCase
+public class DefaultInjectionProviderTest extends InternalBaseTestCase
 {
-    private static final String WEBREQUEST_CLASS_NAME = Request.class.getName();
-
     @Test
-    public void annotation_has_value()
+    public void object_found()
     {
-        ObjectProvider provider = mockObjectProvider();
+        MasterObjectProvider master = mockMasterObjectProvider();
         ObjectLocator locator = mockObjectLocator();
-        Inject annotation = newMock(Inject.class);
         ClassTransformation ct = mockClassTransformation();
         MutableComponentModel model = mockMutableComponentModel();
         Request injected = mockRequest();
 
-        train_findFieldsWithAnnotation(ct, Inject.class, "myfield");
-        train_getFieldAnnotation(ct, "myfield", Inject.class, annotation);
-
-        train_getFieldType(ct, "myfield", WEBREQUEST_CLASS_NAME);
-        train_toClass(ct, WEBREQUEST_CLASS_NAME, Request.class);
-
-        expect(provider.provide(eq(Request.class), isA(AnnotationProvider.class), eq(locator)))
-                .andReturn(injected);
+        expect(
+                master.provide(
+                        eq(Request.class),
+                        isA(AnnotationProvider.class),
+                        eq(locator),
+                        eq(false))).andReturn(injected);
 
         ct.injectField("myfield", injected);
 
-        ct.claimField("myfield", annotation);
-
         replay();
 
-        InjectWorker worker = new InjectWorker(provider, locator);
+        DefaultInjectionProvider provider = new DefaultInjectionProvider(master, locator);
 
-        worker.transform(ct, model);
+        assertTrue(provider.provideInjection("myfield", Request.class, locator, ct, model));
 
         verify();
     }
 
     @Test
-    public void provide_object_fails()
+    public void object_not_found()
     {
-        ObjectProvider provider = mockObjectProvider();
+        MasterObjectProvider master = mockMasterObjectProvider();
         ObjectLocator locator = mockObjectLocator();
-        Inject annotation = newMock(Inject.class);
         ClassTransformation ct = mockClassTransformation();
         MutableComponentModel model = mockMutableComponentModel();
-        Throwable cause = new RuntimeException("Injection failed.");
-
-        train_findFieldsWithAnnotation(ct, Inject.class, "myfield");
-        train_getFieldAnnotation(ct, "myfield", Inject.class, annotation);
-
-        train_getFieldType(ct, "myfield", WEBREQUEST_CLASS_NAME);
-        train_toClass(ct, WEBREQUEST_CLASS_NAME, Request.class);
 
-        expect(provider.provide(eq(Request.class), isA(AnnotationProvider.class), eq(locator)))
-                .andThrow(cause);
-        train_getClassName(ct, "foo.pages.Bar");
+        expect(
+                master.provide(
+                        eq(Request.class),
+                        isA(AnnotationProvider.class),
+                        eq(locator),
+                        eq(false))).andReturn(null);
 
         replay();
 
-        InjectWorker worker = new InjectWorker(provider, locator);
+        DefaultInjectionProvider provider = new DefaultInjectionProvider(master, locator);
 
-        try
-        {
-            worker.transform(ct, model);
-            unreachable();
-        }
-        catch (RuntimeException ex)
-        {
-            assertEquals(
-                    ex.getMessage(),
-                    "Error obtaining injected value for field foo.pages.Bar.myfield: Injection failed.");
-            assertSame(ex.getCause(), cause);
-        }
+        assertFalse(provider.provideInjection("myfield", Request.class, locator, ct, model));
 
         verify();
     }

Copied: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java (from r578523, tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectResourcesWorkerTest.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectResourcesWorkerTest.java&r1=578523&r2=579020&rev=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectResourcesWorkerTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java Mon Sep 24 17:06:31 2007
@@ -24,31 +24,32 @@
 import org.apache.tapestry.services.Request;
 import org.testng.annotations.Test;
 
-public class InjectResourcesWorkerTest extends InternalBaseTestCase
+public class InjectWorkerTest extends InternalBaseTestCase
 {
-    private static final String WEBREQUEST_CLASS_NAME = Request.class.getName();
+    private static final String REQUEST_CLASS_NAME = Request.class.getName();
 
     @Test
     public void anonymous_injection()
     {
         ObjectLocator locator = mockObjectLocator();
         InjectionProvider ip = newMock(InjectionProvider.class);
-        Inject annotation = newMock(Inject.class);
+        Inject annotation = newInject();
         ClassTransformation ct = mockClassTransformation();
         MutableComponentModel model = mockMutableComponentModel();
 
         train_findFieldsWithAnnotation(ct, Inject.class, "myfield");
         train_getFieldAnnotation(ct, "myfield", Inject.class, annotation);
 
-        train_getFieldType(ct, "myfield", WEBREQUEST_CLASS_NAME);
+        train_getFieldType(ct, "myfield", REQUEST_CLASS_NAME);
+        train_toClass(ct, REQUEST_CLASS_NAME, Request.class);
 
-        train_provideInjection(ip, "myfield", WEBREQUEST_CLASS_NAME, locator, ct, model, true);
+        train_provideInjection(ip, "myfield", Request.class, locator, ct, model, true);
 
         ct.claimField("myfield", annotation);
 
         replay();
 
-        ComponentClassTransformWorker worker = new InjectResourcesWorker(locator, ip);
+        ComponentClassTransformWorker worker = new InjectWorker(locator, ip);
 
         worker.transform(ct, model);
 
@@ -60,25 +61,71 @@
     {
         ObjectLocator locator = mockObjectLocator();
         InjectionProvider ip = newMock(InjectionProvider.class);
-        Inject annotation = newMock(Inject.class);
+        Inject annotation = newInject();
         ClassTransformation ct = mockClassTransformation();
         MutableComponentModel model = mockMutableComponentModel();
 
         train_findFieldsWithAnnotation(ct, Inject.class, "myfield");
         train_getFieldAnnotation(ct, "myfield", Inject.class, annotation);
 
-        train_getFieldType(ct, "myfield", WEBREQUEST_CLASS_NAME);
+        train_getFieldType(ct, "myfield", REQUEST_CLASS_NAME);
+        train_toClass(ct, REQUEST_CLASS_NAME, Request.class);
 
-        train_provideInjection(ip, "myfield", WEBREQUEST_CLASS_NAME, locator, ct, model, false);
+        train_provideInjection(ip, "myfield", Request.class, locator, ct, model, false);
 
         replay();
 
-        ComponentClassTransformWorker worker = new InjectResourcesWorker(locator, ip);
+        ComponentClassTransformWorker worker = new InjectWorker(locator, ip);
 
         // Does the work but doesn't claim the field, since there was no match.
 
         worker.transform(ct, model);
 
         verify();
+    }
+
+    @Test
+    public void injection_provider_threw_exception()
+    {
+        ObjectLocator locator = mockObjectLocator();
+        InjectionProvider ip = newMock(InjectionProvider.class);
+        Inject annotation = newInject();
+        ClassTransformation ct = mockClassTransformation();
+        MutableComponentModel model = mockMutableComponentModel();
+        RuntimeException failure = new RuntimeException("Oops.");
+
+        train_findFieldsWithAnnotation(ct, Inject.class, "myfield");
+        train_getFieldAnnotation(ct, "myfield", Inject.class, annotation);
+
+        train_getFieldType(ct, "myfield", REQUEST_CLASS_NAME);
+        train_toClass(ct, REQUEST_CLASS_NAME, Request.class);
+
+        expect(ip.provideInjection("myfield", Request.class, locator, ct, model)).andThrow(failure);
+
+        train_getClassName(ct, "foo.bar.Baz");
+
+        replay();
+
+        ComponentClassTransformWorker worker = new InjectWorker(locator, ip);
+
+        try
+        {
+            worker.transform(ct, model);
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertEquals(
+                    ex.getMessage(),
+                    "Error obtaining injected value for field foo.bar.Baz.myfield: Oops.");
+            assertSame(ex.getCause(), failure);
+        }
+
+        verify();
+    }
+
+    protected final Inject newInject()
+    {
+        return newMock(Inject.class);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java Mon Sep 24 17:06:31 2007
@@ -45,7 +45,6 @@
 import org.apache.tapestry.internal.transform.pages.ChildClassInheritsAnnotation;
 import org.apache.tapestry.internal.transform.pages.ClaimedFields;
 import org.apache.tapestry.internal.transform.pages.EventHandlerTarget;
-import org.apache.tapestry.internal.transform.pages.FindFieldClass;
 import org.apache.tapestry.internal.transform.pages.MethodIdentifier;
 import org.apache.tapestry.internal.transform.pages.ParentClass;
 import org.apache.tapestry.internal.transform.pages.TargetObject;
@@ -253,23 +252,6 @@
     }
 
     @Test
-    public void find_fields_of_type() throws Exception
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ClassTransformation ct = createClassTransformation(FindFieldClass.class, logger);
-
-        checkFindFields(ct, "boolean", "_booleanValue");
-        checkFindFields(ct, "int[]", "_intArrayValue");
-        checkFindFields(ct, "java.lang.String", "_stringValue");
-        checkFindFields(ct, "java.util.Date[]", "_dateArrayValue");
-
-        verify();
-    }
-
-    @Test
     public void get_field_modifiers() throws Exception
     {
         Logger logger = mockLogger();
@@ -298,29 +280,6 @@
     }
 
     @Test
-    public void find_fields_of_type_excludes_claimed_fields() throws Exception
-    {
-        Logger logger = mockLogger();
-
-        replay();
-
-        ClassTransformation ct = createClassTransformation(FindFieldClass.class, logger);
-
-        ct.claimField("_booleanValue", this);
-
-        checkFindFields(ct, "boolean");
-
-        verify();
-    }
-
-    private void checkFindFields(ClassTransformation ct, String fieldType, String... expectedNames)
-    {
-        List<String> actual = ct.findFieldsOfType(fieldType);
-
-        assertEquals(actual, Arrays.asList(expectedNames));
-    }
-
-    @Test
     public void find_fields_with_annotation_excludes_claimed_files() throws Exception
     {
         Logger logger = mockLogger();
@@ -591,8 +550,8 @@
 
         // This proves the the field is protected and can be used in subclasses.
 
-        ct.addMethod(new TransformMethodSignature(Modifier.PUBLIC, "java.lang.String", "getValue", null,
-                null), "return " + subclassFieldName + ";");
+        ct.addMethod(new TransformMethodSignature(Modifier.PUBLIC, "java.lang.String", "getValue",
+                null, null), "return " + subclassFieldName + ";");
 
         ct.finish();
 
@@ -889,8 +848,8 @@
         String fieldName = "_" + baseName;
         String readMethodName = "_read_" + baseName;
 
-        TransformMethodSignature readMethodSignature = new TransformMethodSignature(Modifier.PRIVATE,
-                STRING_CLASS_NAME, readMethodName, null, null);
+        TransformMethodSignature readMethodSignature = new TransformMethodSignature(
+                Modifier.PRIVATE, STRING_CLASS_NAME, readMethodName, null, null);
 
         ct.addMethod(readMethodSignature, String.format(
                 "throw new RuntimeException(\"read %s\");",
@@ -900,8 +859,8 @@
 
         String writeMethodName = "_write_" + baseName;
 
-        TransformMethodSignature writeMethodSignature = new TransformMethodSignature(Modifier.PRIVATE, "void",
-                writeMethodName, new String[]
+        TransformMethodSignature writeMethodSignature = new TransformMethodSignature(
+                Modifier.PRIVATE, "void", writeMethodName, new String[]
                 { STRING_CLASS_NAME }, null);
         ct.addMethod(writeMethodSignature, String.format(
                 "throw new RuntimeException(\"write %s\");",
@@ -1045,7 +1004,9 @@
 
         ClassTransformation ct = createClassTransformation(EventHandlerTarget.class, logger);
 
-        OnEvent annotation = ct.getMethodAnnotation(new TransformMethodSignature("handler"), OnEvent.class);
+        OnEvent annotation = ct.getMethodAnnotation(
+                new TransformMethodSignature("handler"),
+                OnEvent.class);
 
         // Check that the attributes of the annotation match the expectation.
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectDemo.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectDemo.html?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectDemo.html (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/InjectDemo.html Mon Sep 24 17:06:31 2007
@@ -3,6 +3,7 @@
     <p>WebRequest: ${request}</p>
     <p>ComponentResources: ${resources}</p>
     <p>BindingSource: ${bindingSource}</p>
+    <p>Injected Symbol: ${injectedSymbol}</p>
     
     
     <p>

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ObjectProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ObjectProvider.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ObjectProvider.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ObjectProvider.java Mon Sep 24 17:06:31 2007
@@ -24,8 +24,6 @@
  * <p>
  * In many cases, an object provider searches for additional annotations on the element (usually a
  * parameter, or perhaps a field) for which a value is required.
- * <p>
- * A default ObjectProvider uses {@link ObjectLocator#getService(Class)}.
  */
 public interface ObjectProvider
 {

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java Mon Sep 24 17:06:31 2007
@@ -33,7 +33,6 @@
 import org.apache.tapestry.ioc.LoggerSource;
 import org.apache.tapestry.ioc.MappedConfiguration;
 import org.apache.tapestry.ioc.ObjectLocator;
-import org.apache.tapestry.ioc.ObjectProvider;
 import org.apache.tapestry.ioc.OrderedConfiguration;
 import org.apache.tapestry.ioc.Registry;
 import org.apache.tapestry.ioc.ServiceDecorator;
@@ -56,6 +55,7 @@
 import org.apache.tapestry.ioc.services.SymbolSource;
 import org.apache.tapestry.ioc.services.TapestryIOCModule;
 import org.apache.tapestry.ioc.services.ThreadCleanupHub;
+import org.apache.tapestry.services.MasterObjectProvider;
 import org.slf4j.Logger;
 
 public class RegistryImpl implements Registry, InternalRegistry
@@ -543,14 +543,14 @@
     {
         _lock.check();
 
-        ObjectProvider masterProvider = getService(
+        MasterObjectProvider masterProvider = getService(
                 IOCConstants.MASTER_OBJECT_PROVIDER_SERVICE_ID,
-                ObjectProvider.class);
+                MasterObjectProvider.class);
 
         AnnotationProvider effectiveProvider = annotationProvider != null ? annotationProvider
                 : new NullAnnotationProvider();
 
-        return masterProvider.provide(objectType, effectiveProvider, locator);
+        return masterProvider.provide(objectType, effectiveProvider, locator, true);
     }
 
     public <T> T getObject(Class<T> objectType, AnnotationProvider annotationProvider)

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/MasterObjectProviderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/MasterObjectProviderImpl.java?rev=579020&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/MasterObjectProviderImpl.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/MasterObjectProviderImpl.java Mon Sep 24 17:06:31 2007
@@ -0,0 +1,51 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.ioc.internal.services;
+
+import java.util.List;
+
+import org.apache.tapestry.ioc.AnnotationProvider;
+import org.apache.tapestry.ioc.ObjectLocator;
+import org.apache.tapestry.ioc.ObjectProvider;
+import org.apache.tapestry.services.MasterObjectProvider;
+
+public class MasterObjectProviderImpl implements MasterObjectProvider
+{
+    private final List<ObjectProvider> _configuration;
+
+    public MasterObjectProviderImpl(List<ObjectProvider> configuration)
+    {
+        _configuration = configuration;
+    }
+
+    public <T> T provide(Class<T> objectType, AnnotationProvider annotationProvider,
+            ObjectLocator locator, boolean required)
+    {
+        for (ObjectProvider provider : _configuration)
+        {
+            T result = provider.provide(objectType, annotationProvider, locator);
+
+            if (result != null) return result;
+        }
+
+        // If required, then we must obtain it the hard way, by
+        // seeing if there's a single service that implements the interface.
+
+        if (required) return locator.getService(objectType);
+
+        return null;
+    }
+
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java Mon Sep 24 17:06:31 2007
@@ -24,7 +24,6 @@
 import java.util.List;
 import java.util.Map;
 
-import org.apache.tapestry.ioc.AnnotationProvider;
 import org.apache.tapestry.ioc.Configuration;
 import org.apache.tapestry.ioc.MappedConfiguration;
 import org.apache.tapestry.ioc.ObjectLocator;
@@ -40,6 +39,7 @@
 import org.apache.tapestry.ioc.internal.services.ExceptionTrackerImpl;
 import org.apache.tapestry.ioc.internal.services.LoggingDecoratorImpl;
 import org.apache.tapestry.ioc.internal.services.MapSymbolProvider;
+import org.apache.tapestry.ioc.internal.services.MasterObjectProviderImpl;
 import org.apache.tapestry.ioc.internal.services.PerThreadServiceLifecycle;
 import org.apache.tapestry.ioc.internal.services.PipelineBuilderImpl;
 import org.apache.tapestry.ioc.internal.services.PropertyAccessImpl;
@@ -52,6 +52,7 @@
 import org.apache.tapestry.ioc.internal.services.ThreadLocaleImpl;
 import org.apache.tapestry.ioc.internal.services.TypeCoercerImpl;
 import org.apache.tapestry.ioc.internal.services.ValueObjectProvider;
+import org.apache.tapestry.services.MasterObjectProvider;
 
 /**
  * Defines the base set of services for the Tapestry IOC container.
@@ -75,6 +76,7 @@
         binder.bind(SymbolProvider.class, MapSymbolProvider.class).withId("ApplicationDefaults");
         binder.bind(SymbolProvider.class, MapSymbolProvider.class).withId("FactoryDefaults");
         binder.bind(Runnable.class, RegistryStartup.class).withId("RegistryStartup");
+        binder.bind(MasterObjectProvider.class, MasterObjectProviderImpl.class);
     }
 
     /**
@@ -102,18 +104,6 @@
     }
 
     /**
-     * The master {@link ObjectProvider} is responsible for identifying a particular ObjectProvider
-     * by its prefix, and delegating to that instance.
-     */
-    public static ObjectProvider buildMasterObjectProvider(List<ObjectProvider> configuration,
-
-    @InjectService("ChainBuilder")
-    ChainBuilder chainBuilder)
-    {
-        return chainBuilder.build(ObjectProvider.class, configuration);
-    }
-
-    /**
      * Contributes "DefaultProvider", ordered last, that delegates to
      * {@link ObjectLocator#getService(Class)}.
      * <p>
@@ -125,17 +115,6 @@
 
             ObjectLocator locator)
     {
-        ObjectProvider defaultProvider = new ObjectProvider()
-        {
-
-            public <T> T provide(Class<T> objectType, AnnotationProvider annotationProvider,
-                    ObjectLocator locator)
-            {
-                return locator.getService(objectType);
-            }
-        };
-
-        configuration.add("DefaultProvider", defaultProvider, "after:*");
         configuration.add("Value", locator.autobuild(ValueObjectProvider.class));
         configuration.add("Symbol", locator.autobuild(SymbolObjectProvider.class));
     }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java?rev=579020&r1=579019&r2=579020&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java Mon Sep 24 17:06:31 2007
@@ -45,6 +45,7 @@
 import org.apache.tapestry.ioc.services.SymbolSource;
 import org.apache.tapestry.ioc.services.ThreadLocale;
 import org.apache.tapestry.ioc.services.TypeCoercer;
+import org.apache.tapestry.services.MasterObjectProvider;
 import org.slf4j.Logger;
 
 /** Add factory and trainer methods for the public interfaces of Tapestry IOC. */
@@ -366,5 +367,10 @@
             AnnotationProvider annotationProvider, Class<T> annotationClass, T annotation)
     {
         expect(annotationProvider.getAnnotation(annotationClass)).andReturn(annotation);
+    }
+
+    protected final MasterObjectProvider mockMasterObjectProvider()
+    {
+        return newMock(MasterObjectProvider.class);
     }
 }

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/services/MasterObjectProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/services/MasterObjectProvider.java?rev=579020&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/services/MasterObjectProvider.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/services/MasterObjectProvider.java Mon Sep 24 17:06:31 2007
@@ -0,0 +1,57 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.services;
+
+import org.apache.tapestry.ioc.AnnotationProvider;
+import org.apache.tapestry.ioc.ObjectLocator;
+import org.apache.tapestry.ioc.ObjectProvider;
+
+/**
+ * Rolls up a number of {@link ObjectProvider}, but allows for the case where no object may be
+ * provided.
+ */
+public interface MasterObjectProvider
+{
+    /**
+     * Provides an object based on an expression. The process of providing objects occurs within a
+     * particular <em>context</em>, which will typically be a service builder method, service
+     * contributor method, or service decorator method. The locator parameter provides access to the
+     * services visible <em>to that context</em>.
+     * <p>
+     * When the value is required and no {@link ObjectProvider} provided a non-null value, then
+     * {@link ObjectLocator#getService(Class)} is invoked, to provide a unique matching service, or
+     * throw a failure exception.
+     * 
+     * @param objectType
+     *            the expected object type
+     * @param annotationProvider
+     *            provides access to annotations (typically, the field or parameter to which an
+     *            injection-related annotation is attached); annotations on the field or parameter
+     *            may also be used when resolving the desired object
+     * @param locator
+     *            locator for the <em>context</em> in which the provider is being used
+     * @param required
+     *            if true (normal case) a value must be provided; if false then it is allowed for no
+     *            ObjectProvider to provide a value, and this method may return null to indicate the
+     *            failure
+     * @param <T>
+     * @return the requested object, or null if this object provider can not supply an object
+     * @throws RuntimeException
+     *             if the expression can not be evaluated, or the type of object identified is not
+     *             assignable to the type specified by the objectType parameter
+     */
+    <T> T provide(Class<T> objectType, AnnotationProvider annotationProvider,
+            ObjectLocator locator, boolean required);
+}