You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2007/04/17 01:31:54 UTC

svn commit: r529445 [2/3] - in /tapestry/tapestry5: tapestry-core/trunk/.settings/ tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ tapestry-hibernate/trunk/src/mai...

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ConstructorServiceCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ConstructorServiceCreator.java?view=auto&rev=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ConstructorServiceCreator.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ConstructorServiceCreator.java Mon Apr 16 16:31:50 2007
@@ -0,0 +1,80 @@
+// 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;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
+
+import org.apache.tapestry.ioc.ServiceBuilderResources;
+import org.apache.tapestry.ioc.internal.util.InternalUtils;
+
+/**
+ * A service creator based on an implementation class' constructor, rather than a service builder
+ * method.
+ */
+public class ConstructorServiceCreator extends AbstractServiceCreator
+{
+    private final Constructor _constructor;
+
+    public ConstructorServiceCreator(ServiceBuilderResources resources, String creatorDescription,
+            Constructor constructor)
+    {
+        super(resources, creatorDescription);
+
+        _constructor = constructor;
+    }
+
+    public Object createObject()
+    {
+        Throwable failure = null;
+
+        try
+        {
+            Object[] parameters = InternalUtils.calculateParametersForConstructor(
+                    _constructor,
+                    _resources,
+                    getParameterDefaultsWithConfigurations());
+
+            if (_log.isDebugEnabled())
+                _log.debug(IOCMessages.invokingConstructor(_creatorDescription));
+
+            return _constructor.newInstance(parameters);
+        }
+        catch (InvocationTargetException ite)
+        {
+            failure = ite.getTargetException();
+        }
+        catch (Exception ex)
+        {
+            failure = ex;
+        }
+
+        throw new RuntimeException(IOCMessages.constructorError(
+                _creatorDescription,
+                _serviceId,
+                failure), failure);
+    }
+
+    /**
+     * Returns a map that includes (possibly) an additional mapping containing the collected
+     * configuration data. This involves scanning the constructor's parameters.
+     */
+    private Map<Class, Object> getParameterDefaultsWithConfigurations()
+    {
+        return getParameterDefaultsWithConfiguration(_constructor.getParameterTypes(), _constructor
+                .getGenericParameterTypes());
+    }
+}

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java Mon Apr 16 16:31:50 2007
@@ -24,7 +24,9 @@
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newSet;
 
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Map;
@@ -34,7 +36,10 @@
 import org.apache.tapestry.ioc.Configuration;
 import org.apache.tapestry.ioc.IOCConstants;
 import org.apache.tapestry.ioc.MappedConfiguration;
+import org.apache.tapestry.ioc.ObjectCreator;
 import org.apache.tapestry.ioc.OrderedConfiguration;
+import org.apache.tapestry.ioc.ServiceBinder;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
 import org.apache.tapestry.ioc.annotations.EagerLoad;
 import org.apache.tapestry.ioc.annotations.Scope;
 import org.apache.tapestry.ioc.annotations.Match;
@@ -51,7 +56,7 @@
  * methods), decorators (service decorator methods) and (not yet implemented) contributions (service
  * contributor methods).
  */
-public class DefaultModuleDefImpl implements ModuleDef
+public class DefaultModuleDefImpl implements ModuleDef, ServiceDefAccumulator
 {
     /** The prefix used to identify service builder methods. */
     private static final String BUILD_METHOD_NAME_PREFIX = "build";
@@ -99,6 +104,7 @@
         _classFactory = classFactory;
 
         grind();
+        bind();
     }
 
     /** Identified the module builder class and a list of service ids within the module. */
@@ -269,9 +275,8 @@
     }
 
     /** Invoked for public methods that have the proper prefix. */
-    private void addServiceDef(Method method)
+    private void addServiceDef(final Method method)
     {
-        // TODO: Methods named just "build"
         String serviceId = stripMethodPrefix(method, BUILD_METHOD_NAME_PREFIX);
 
         // If the method name was just "build()", then work from the return type.
@@ -279,13 +284,6 @@
         if (serviceId.equals(""))
             serviceId = InternalUtils.lastTerm(method.getReturnType().getName());
 
-        ServiceDef existing = _serviceDefs.get(serviceId);
-        if (existing != null)
-        {
-            _log.warn(buildMethodConflict(method, existing.toString()), null);
-            return;
-        }
-
         // Any number of parameters is fine, we'll adapt. Eventually we have to check
         // that we can satisfy the parameters requested. Thrown exceptions of the method
         // will be caught and wrapped, so we don't need to check those. But we do need a proper
@@ -299,18 +297,48 @@
             return;
         }
 
-        String lifecycle = extractLifecycle(method);
+        String scope = extractServiceScope(method);
         boolean eagerLoad = method.isAnnotationPresent(EagerLoad.class);
 
-        _serviceDefs.put(serviceId, new ServiceDefImpl(serviceId, lifecycle, method, eagerLoad,
-                _classFactory));
+        ObjectCreatorSource source = new ObjectCreatorSource()
+        {
+            public ObjectCreator constructCreator(ServiceBuilderResources resources)
+            {
+                return new ServiceBuilderMethodInvoker(resources, getDescription(), method);
+            }
+
+            public String getDescription()
+            {
+                return InternalUtils.asString(method, _classFactory);
+            }
+        };
+
+        ServiceDefImpl serviceDef = new ServiceDefImpl(returnType, serviceId, scope, eagerLoad,
+                source);
+
+        addServiceDef(serviceDef);
+    }
+
+    public void addServiceDef(ServiceDef serviceDef)
+    {
+        String serviceId = serviceDef.getServiceId();
+
+        ServiceDef existing = _serviceDefs.get(serviceId);
+
+        if (existing != null)
+        {
+            _log.warn(buildMethodConflict(serviceDef.toString(), existing.toString()), null);
+            return;
+        }
+
+        _serviceDefs.put(serviceId, serviceDef);
     }
 
-    private String extractLifecycle(Method method)
+    private String extractServiceScope(Method method)
     {
         Scope scope = method.getAnnotation(Scope.class);
 
-        return scope != null ? scope.value() : IOCConstants.DEFAULT_LIFECYCLE;
+        return scope != null ? scope.value() : IOCConstants.DEFAULT_SCOPE;
     }
 
     public Set<DecoratorDef> getDecoratorDefs()
@@ -328,4 +356,54 @@
         return _builderClass.getName();
     }
 
+    /** See if the build class defined a bind method and invoke it. */
+    private void bind()
+    {
+        Throwable failure = null;
+        Method bindMethod = null;
+
+        try
+        {
+            bindMethod = _builderClass.getMethod("bind", ServiceBinder.class);
+
+            if (!Modifier.isStatic(bindMethod.getModifiers()))
+            {
+                _log.error(IOCMessages.bindMethodMustBeStatic(InternalUtils.asString(
+                        bindMethod,
+                        _classFactory)));
+
+                return;
+            }
+
+            ServiceBinderImpl binder = new ServiceBinderImpl(this, _classFactory);
+
+            bindMethod.invoke(null, binder);
+
+            binder.finish();
+
+            return;
+        }
+        catch (NoSuchMethodException ex)
+        {
+            // No problem! Many modules will not have such a method.
+
+            return;
+        }
+        catch (IllegalArgumentException ex)
+        {
+            failure = ex;
+        }
+        catch (IllegalAccessException ex)
+        {
+            failure = ex;
+        }
+        catch (InvocationTargetException ex)
+        {
+            failure = ex.getTargetException();
+        }
+
+        String methodId = InternalUtils.asString(bindMethod, _classFactory);
+
+        throw new RuntimeException(IOCMessages.errorInBindMethod(methodId, failure), failure);
+    }
 }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/IOCInternalTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/IOCInternalTestCase.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/IOCInternalTestCase.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/IOCInternalTestCase.java Mon Apr 16 16:31:50 2007
@@ -122,4 +122,14 @@
         return newMock(Module.class);
     }
 
+    protected final ObjectCreatorSource newObjectCreatorSource()
+    {
+        return newMock(ObjectCreatorSource.class);
+    }
+
+    protected final void train_getDescription(ObjectCreatorSource source, String description)
+    {
+        expect(source.getDescription()).andReturn(description).atLeastOnce();
+    }
+
 }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/IOCMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/IOCMessages.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/IOCMessages.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/IOCMessages.java Mon Apr 16 16:31:50 2007
@@ -34,9 +34,9 @@
 {
     private static final Messages MESSAGES = MessagesImpl.forClass(IOCMessages.class);
 
-    static String buildMethodConflict(Method conflict, String existing)
+    static String buildMethodConflict(String conflict, String existing)
     {
-        return MESSAGES.format("build-method-conflict", asString(conflict), existing);
+        return MESSAGES.format("build-method-conflict", conflict, existing);
     }
 
     static String buildMethodWrongReturnType(Method method)
@@ -76,6 +76,11 @@
         return MESSAGES.format("builder-method-error", methodId, serviceId, cause);
     }
 
+    static String constructorError(String creatorDescription, String serviceId, Throwable cause)
+    {
+        return MESSAGES.format("constructor-error", creatorDescription, serviceId, cause);
+    }
+
     static String decoratorMethodError(Method method, String serviceId, Throwable cause)
     {
         return MESSAGES.format("decorator-method-error", asString(method), serviceId, cause);
@@ -140,6 +145,11 @@
         return MESSAGES.format("invoking-method", methodId);
     }
 
+    static String invokingConstructor(String creatorDescription)
+    {
+        return MESSAGES.format("invoking-constructor", creatorDescription);
+    }
+
     static String invokingMethod(ContributionDef def)
     {
         // The toString() of a contribution def is the name of the method.
@@ -268,5 +278,20 @@
     static String serviceIdConflict(String serviceId, ServiceDef existing, ServiceDef conflicting)
     {
         return MESSAGES.format("service-id-conflict", serviceId, existing, conflicting);
+    }
+
+    static String noConstructor(Class implementationClass, String serviceId)
+    {
+        return MESSAGES.format("no-constructor", implementationClass.getName(), serviceId);
+    }
+
+    static String bindMethodMustBeStatic(String methodId)
+    {
+        return MESSAGES.format("bind-method-must-be-static", methodId);
+    }
+
+    static String errorInBindMethod(String methodId, Throwable cause)
+    {
+        return MESSAGES.format("error-in-bind-method", methodId, cause);
     }
 }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/LifecycleWrappedServiceCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/LifecycleWrappedServiceCreator.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/LifecycleWrappedServiceCreator.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/LifecycleWrappedServiceCreator.java Mon Apr 16 16:31:50 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,42 +12,41 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.ioc.internal;
-
-import org.apache.tapestry.ioc.ObjectCreator;
-import org.apache.tapestry.ioc.ServiceLifecycle;
-import org.apache.tapestry.ioc.ServiceResources;
-
-/**
- * Wrapper around a lifecycle, a set of resources for a service, and an underlying service creator
- * for a service that allows the service lifecycle to alter the way that the service is created
- * (this is needed for the more advanced, non-singleton types of service lifecycles).
- * 
- * 
- */
-public class LifecycleWrappedServiceCreator implements ObjectCreator
-{
-    private final ServiceLifecycle _lifecycle;
-
-    private final ServiceResources _resources;
-
-    private final ObjectCreator _creator;
-
-    public LifecycleWrappedServiceCreator(ServiceLifecycle lifecycle, ServiceResources resources,
-            ObjectCreator creator)
-    {
-        _lifecycle = lifecycle;
-        _resources = resources;
-        _creator = creator;
-    }
-
-    /**
-     * Passes the resources and the service creator through the
-     * {@link org.apache.tapestry.ioc.ServiceLifecycle}.
-     */
-    public Object createObject()
-    {
-        return _lifecycle.createService(_resources, _creator);
-    }
-
-}
+package org.apache.tapestry.ioc.internal;
+
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceLifecycle;
+import org.apache.tapestry.ioc.ServiceResources;
+
+/**
+ * Wrapper around a lifecycle, a set of resources for a service, and an underlying
+ * {@link ObjectCreator} for a service that allows the service lifecycle to alter the way that the
+ * service is created (this is needed for the more advanced, non-singleton types of service
+ * lifecycles).
+ */
+public class LifecycleWrappedServiceCreator implements ObjectCreator
+{
+    private final ServiceLifecycle _lifecycle;
+
+    private final ServiceResources _resources;
+
+    private final ObjectCreator _creator;
+
+    public LifecycleWrappedServiceCreator(ServiceLifecycle lifecycle, ServiceResources resources,
+            ObjectCreator creator)
+    {
+        _lifecycle = lifecycle;
+        _resources = resources;
+        _creator = creator;
+    }
+
+    /**
+     * Passes the resources and the service creator through the
+     * {@link org.apache.tapestry.ioc.ServiceLifecycle}.
+     */
+    public Object createObject()
+    {
+        return _lifecycle.createService(_resources, _creator);
+    }
+
+}

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/Module.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/Module.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/Module.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/Module.java Mon Apr 16 16:31:50 2007
@@ -46,7 +46,9 @@
     <T> T getService(String serviceId, Class<T> serviceInterface);
 
     /**
-     * Locates the ids of all services that implement the provided service interface.
+     * Locates the ids of all services that implement the provided service interface, or whose
+     * service interface is assignable to the provided service interface (is a super-class or
+     * super-interface).
      * 
      * @param serviceInterface
      *            the interface to search for

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java Mon Apr 16 16:31:50 2007
@@ -129,6 +129,7 @@
         return _registry.findDecoratorsForService(sd);
     }
 
+    @SuppressWarnings("unchecked")
     public Collection<String> findServiceIdsForInterface(Class serviceInterface)
     {
         notNull(serviceInterface, "serviceInterface");
@@ -139,9 +140,7 @@
         {
             ServiceDef def = _moduleDef.getServiceDef(id);
 
-            if (def.getServiceInterface() != serviceInterface) continue;
-
-            result.add(id);
+            if (serviceInterface.isAssignableFrom(def.getServiceInterface())) result.add(id);
         }
 
         return result;
@@ -219,6 +218,14 @@
             // (by the proxy, at a later date).
 
             ObjectCreator creator = def.createServiceCreator(resources);
+
+            Class serviceInterface = def.getServiceInterface();
+
+            // For non-proxyable services, we immediately create the service implementation
+            // and return it. There's no interface to proxy, which throws out the possibility of
+            // deferred instantiation, service lifecycles, and decorators.
+
+            if (!serviceInterface.isInterface()) return creator.createObject();
 
             creator = new LifecycleWrappedServiceCreator(lifecycle, resources, creator);
 

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ObjectCreatorSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ObjectCreatorSource.java?view=auto&rev=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ObjectCreatorSource.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ObjectCreatorSource.java Mon Apr 16 16:31:50 2007
@@ -0,0 +1,38 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.ioc.internal;
+
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
+
+/**
+ * An object which can, when passed a {@link ServiceBuilderResources}, create a corresponding
+ * {@link ObjectCreator}. A secondary responsibility is to provide a description of the creator,
+ * which is usually based on the name of the method or constructor to be invoked, and is ultimately
+ * used in some debugging or error output.
+ */
+public interface ObjectCreatorSource
+{
+    /**
+     * Provides an ObjectCreator that can be used to ultimately instantiate the core service
+     * implementation.
+     */
+    ObjectCreator constructCreator(ServiceBuilderResources resources);
+
+    /**
+     * Returns a description of the method or constructor that creates the service.
+     */
+    String getDescription();
+}

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java Mon Apr 16 16:31:50 2007
@@ -88,12 +88,6 @@
     private final Map<String, ServiceLifecycle> _lifecycles = newCaseInsensitiveMap();
 
     /**
-     * Map from service interface class to list of service ids that implement the interface
-     * (including builtin services).
-     */
-    private final Map<Class, List<String>> _serviceInterfaceToServiceIdList = newMap();
-
-    /**
      * Service implementation overrides, keyed on service id. Service implementations are most
      * useful when perfroming integration tests on services. As one service can bring in another, we
      * have to stop at a certain "bounary" services by provide stub/ mock objects as their
@@ -162,10 +156,6 @@
                             .getServiceDef(serviceId), module.getServiceDef(serviceId)));
 
                 _serviceIdToModule.put(serviceId, module);
-
-                ServiceDef serviceDef = module.getServiceDef(serviceId);
-
-                addServiceImplementer(serviceDef.getServiceInterface(), serviceId);
             }
         }
 
@@ -223,21 +213,6 @@
     {
         _builtinTypes.put(serviceId, serviceInterface);
         _builtinServices.put(serviceId, service);
-
-        addServiceImplementer(serviceInterface, serviceId);
-    }
-
-    private void addServiceImplementer(Class serviceInterface, String serviceId)
-    {
-        List<String> serviceIds = _serviceInterfaceToServiceIdList.get(serviceInterface);
-
-        if (serviceIds == null)
-        {
-            serviceIds = newList();
-            _serviceInterfaceToServiceIdList.put(serviceInterface, serviceIds);
-        }
-
-        serviceIds.add(serviceId);
     }
 
     public synchronized void shutdown()
@@ -479,12 +454,11 @@
         }
     }
 
-    // Seems like something that could be cached.
     public <T> T getService(Class<T> serviceInterface)
     {
         _lock.check();
 
-        List<String> serviceIds = _serviceInterfaceToServiceIdList.get(serviceInterface);
+        List<String> serviceIds = findServiceIdsForInterface(serviceInterface);
 
         if (serviceIds == null) serviceIds = Collections.emptyList();
 
@@ -508,6 +482,23 @@
                         serviceInterface,
                         serviceIds));
         }
+    }
+
+    private List<String> findServiceIdsForInterface(Class serviceInterface)
+    {
+        List<String> result = newList();
+
+        for (Module module : _modules)
+            result.addAll(module.findServiceIdsForInterface(serviceInterface));
+
+        for (Map.Entry<String, Object> entry : _builtinServices.entrySet())
+        {
+            if (serviceInterface.isInstance(entry.getValue())) result.add(entry.getKey());
+        }
+
+        Collections.sort(result);
+
+        return result;
     }
 
     public ServiceLifecycle getServiceLifecycle(String scope)

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java?view=auto&rev=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java Mon Apr 16 16:31:50 2007
@@ -0,0 +1,193 @@
+// 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;
+
+import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
+import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
+
+import java.lang.reflect.Constructor;
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.apache.tapestry.ioc.IOCConstants;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBinder;
+import org.apache.tapestry.ioc.ServiceBindingOptions;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
+import org.apache.tapestry.ioc.annotations.EagerLoad;
+import org.apache.tapestry.ioc.annotations.Scope;
+import org.apache.tapestry.ioc.def.ServiceDef;
+import org.apache.tapestry.ioc.internal.util.OneShotLock;
+import org.apache.tapestry.ioc.services.ClassFactory;
+
+public class ServiceBinderImpl implements ServiceBinder, ServiceBindingOptions
+{
+    private final OneShotLock _lock = new OneShotLock();
+
+    private final ServiceDefAccumulator _accumulator;
+
+    private final ClassFactory _classFactory;
+
+    public ServiceBinderImpl(ServiceDefAccumulator accumulator, ClassFactory classFactory)
+    {
+        _accumulator = accumulator;
+        _classFactory = classFactory;
+    }
+
+    private String _serviceId;
+
+    private Class _serviceInterface;
+
+    private Class _serviceImplementation;
+
+    private boolean _eagerLoad;
+
+    private String _scope;
+
+    public void finish()
+    {
+        _lock.lock();
+
+        flush();
+    }
+
+    protected void flush()
+    {
+        if (_serviceInterface == null) return;
+
+        final Constructor constructor = findConstructor();
+
+        ObjectCreatorSource source = new ObjectCreatorSource()
+        {
+            public ObjectCreator constructCreator(ServiceBuilderResources resources)
+            {
+                return new ConstructorServiceCreator(resources, getDescription(), constructor);
+            }
+
+            public String getDescription()
+            {
+                return _classFactory.getConstructorLocation(constructor);
+            }
+        };
+
+        ServiceDef serviceDef = new ServiceDefImpl(_serviceInterface, _serviceId, _scope,
+                _eagerLoad, source);
+
+        _accumulator.addServiceDef(serviceDef);
+
+        _serviceId = null;
+        _serviceInterface = null;
+        _serviceImplementation = null;
+        _eagerLoad = false;
+        _scope = null;
+    }
+
+    private Constructor findConstructor()
+    {
+        Constructor[] constructors = _serviceImplementation.getConstructors();
+
+        switch (constructors.length)
+        {
+            case 1:
+
+                return constructors[0];
+
+            case 0:
+
+                throw new RuntimeException(IOCMessages.noConstructor(
+                        _serviceImplementation,
+                        _serviceId));
+
+            default:
+                break;
+        }
+
+        // Choose a constructor with the most parameters.
+
+        Comparator<Constructor> comparator = new Comparator<Constructor>()
+        {
+            public int compare(Constructor o1, Constructor o2)
+            {
+                return o2.getParameterTypes().length - o1.getParameterTypes().length;
+            }
+        };
+
+        Arrays.sort(constructors, comparator);
+
+        return constructors[0];
+    }
+
+    public <T> ServiceBindingOptions bind(Class<T> implementationClass)
+    {
+        return bind(implementationClass, implementationClass);
+    }
+
+    public <T> ServiceBindingOptions bind(Class<T> serviceInterface,
+            Class<? extends T> serviceImplementation)
+    {
+        notNull(serviceInterface, "serviceIterface");
+        notNull(serviceImplementation, "serviceImplementation");
+
+        _lock.check();
+
+        flush();
+
+        _serviceInterface = serviceInterface;
+        _serviceImplementation = serviceImplementation;
+
+        // Set defaults for the other properties.
+
+        _eagerLoad = serviceImplementation.getAnnotation(EagerLoad.class) != null;
+        _serviceId = serviceInterface.getSimpleName();
+
+        Scope scope = serviceImplementation.getAnnotation(Scope.class);
+
+        _scope = scope != null ? scope.value() : IOCConstants.DEFAULT_SCOPE;
+
+        return this;
+    }
+
+    public ServiceBindingOptions eagerLoad()
+    {
+        _lock.check();
+
+        _eagerLoad = true;
+
+        return this;
+    }
+
+    public ServiceBindingOptions withId(String id)
+    {
+        notBlank(id, "id");
+
+        _lock.check();
+
+        _serviceId = id;
+
+        return this;
+    }
+
+    public ServiceBindingOptions scope(String scope)
+    {
+        notBlank(scope, "scope");
+
+        _lock.check();
+
+        _scope = scope;
+
+        return this;
+    }
+
+}

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceBuilderMethodInvoker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceBuilderMethodInvoker.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceBuilderMethodInvoker.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceBuilderMethodInvoker.java Mon Apr 16 16:31:50 2007
@@ -14,221 +14,39 @@
 
 package org.apache.tapestry.ioc.internal;
 
-import static org.apache.tapestry.ioc.internal.ConfigurationType.MAPPED;
-import static org.apache.tapestry.ioc.internal.ConfigurationType.ORDERED;
-import static org.apache.tapestry.ioc.internal.ConfigurationType.UNORDERED;
-import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
-
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Collection;
-import java.util.List;
 import java.util.Map;
 
-import org.apache.commons.logging.Log;
-import org.apache.tapestry.ioc.ObjectCreator;
 import org.apache.tapestry.ioc.ServiceBuilderResources;
-import org.apache.tapestry.ioc.ServiceResources;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
-import org.apache.tapestry.ioc.services.ClassFactory;
 
 /**
  * Basic implementation of {@link org.apache.tapestry.ioc.ObjectCreator} that handles invoking a
  * method on the module builder, and figures out the correct parameters to pass into the annotated
  * method.
  */
-public class ServiceBuilderMethodInvoker implements ObjectCreator
+public class ServiceBuilderMethodInvoker extends AbstractServiceCreator
 {
-    private final String _serviceId;
-
-    private final Map<Class, Object> _parameterDefaults = newMap();
-
-    private final ServiceBuilderResources _resources;
-
     private final Method _builderMethod;
 
-    private final Log _log;
-
-    private final ClassFactory _classFactory;
-
-    private final static Map<Class, ConfigurationType> PARAMETER_TYPE_TO_CONFIGURATION_TYPE = newMap();
-
-    static
+    public ServiceBuilderMethodInvoker(ServiceBuilderResources resources,
+            String creatorDescription, Method method)
     {
-        PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(Collection.class, UNORDERED);
-        PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(List.class, ORDERED);
-        PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(Map.class, MAPPED);
-    }
+        super(resources, creatorDescription);
 
-    public ServiceBuilderMethodInvoker(Method method, ServiceBuilderResources resources,
-            ClassFactory classFactory)
-    {
-        _serviceId = resources.getServiceId();
         _builderMethod = method;
-        _resources = resources;
-        _log = resources.getServiceLog();
-        _classFactory = classFactory;
-
-        _parameterDefaults.put(String.class, _serviceId);
-        _parameterDefaults.put(ServiceResources.class, resources);
-        _parameterDefaults.put(Log.class, _log);
-        _parameterDefaults.put(Class.class, resources.getServiceInterface());
-    }
-
-    private String methodId()
-    {
-        return InternalUtils.asString(_builderMethod, _classFactory);
     }
 
     /**
-     * Returns a map (based on _parameterDefaults) that includes (possibly) an additional mapping
-     * containing the collected configuration data. This involves scanning the builder method's
-     * parameters
+     * Returns a map that includes (possibly) an additional mapping containing the collected
+     * configuration data. This involves scanning the builder method's parameters.
      */
     private Map<Class, Object> getParameterDefaultsWithConfigurations()
     {
-        Map<Class, Object> result = newMap(_parameterDefaults);
-        ConfigurationType type = null;
-
-        Class[] parameterTypes = _builderMethod.getParameterTypes();
-
-        for (int i = 0; i < parameterTypes.length; i++)
-        {
-            Class parameterType = parameterTypes[i];
-
-            ConfigurationType thisType = PARAMETER_TYPE_TO_CONFIGURATION_TYPE.get(parameterType);
-
-            if (thisType == null) continue;
-
-            if (type != null)
-            {
-                _log.warn(IOCMessages.tooManyConfigurationParameters(methodId()));
-                break;
-            }
-
-            // Remember that we've seen a configuration parameter, in case there
-            // is another.
-
-            type = thisType;
-
-            Type genericType = _builderMethod.getGenericParameterTypes()[i];
-
-            switch (type)
-            {
-
-                case UNORDERED:
-
-                    addUnorderedConfigurationParameter(result, genericType);
-
-                    break;
-
-                case ORDERED:
-
-                    addOrderedConfigurationParameter(result, genericType);
-
-                    break;
-
-                case MAPPED:
-
-                    addMappedConfigurationParameter(result, genericType);
-
-                    break;
-
-            }
-
-        }
-
-        return result;
-    }
-
-    @SuppressWarnings("unchecked")
-    private void addOrderedConfigurationParameter(Map<Class, Object> parameterDefaults,
-            Type genericType)
-    {
-        Class valueType = findParameterizedTypeFromGenericType(genericType);
-        List configuration = _resources.getOrderedConfiguration(valueType);
-
-        parameterDefaults.put(List.class, configuration);
-    }
-
-    @SuppressWarnings("unchecked")
-    private void addUnorderedConfigurationParameter(Map<Class, Object> parameterDefaults,
-            Type genericType)
-    {
-        Class valueType = findParameterizedTypeFromGenericType(genericType);
-        Collection configuration = _resources.getUnorderedConfiguration(valueType);
-
-        parameterDefaults.put(Collection.class, configuration);
-    }
-
-    @SuppressWarnings("unchecked")
-    private void addMappedConfigurationParameter(Map<Class, Object> parameterDefaults,
-            Type genericType)
-    {
-        Class keyType = findParameterizedTypeFromGenericType(genericType, 0);
-        Class valueType = findParameterizedTypeFromGenericType(genericType, 1);
-
-        if (keyType == null || valueType == null)
-            throw new IllegalArgumentException(IOCMessages.genericTypeNotSupported(genericType));
-
-        Map configuration = _resources.getMappedConfiguration(keyType, valueType);
-
-        parameterDefaults.put(Map.class, configuration);
-    }
-
-    /**
-     * Extracts from a generic type the underlying parameterized type. I.e., for List<Runnable>,
-     * will return Runnable. This is limited to simple parameterized types, not the more complex
-     * cases involving wildcards and upper/lower boundaries.
-     * 
-     * @param type
-     *            the genetic type of the parameter, i.e., List<Runnable>
-     * @return the parameterize type (i.e. Runnable.class if type represents List<Runnable>).
-     */
-
-    // package private for testing
-    static Class findParameterizedTypeFromGenericType(Type type)
-    {
-        Class result = findParameterizedTypeFromGenericType(type, 0);
-
-        if (result == null)
-            throw new IllegalArgumentException(IOCMessages.genericTypeNotSupported(type));
-
-        return result;
-    }
-
-    /**
-     * "Sniffs" a generic type to find the underlying parameterized type. If the Type is a class,
-     * then Object.class is returned. Otherwise, the type must be a ParameterizedType. We check to
-     * make sure it has the correct number of a actual types (1 for a Collection or List, 2 for a
-     * Map). The actual types must be classes (wildcards just aren't supported)
-     * 
-     * @param type
-     *            a Class or ParameterizedType to inspect
-     * @param typeIndex
-     *            the index within the ParameterizedType to extract
-     * @return the actual type, or Object.class if the input type is not generic, or null if any
-     *         other pre-condition is not met
-     */
-    private static Class findParameterizedTypeFromGenericType(Type type, int typeIndex)
-    {
-        // For a raw Class type, it means the parameter is not parameterized (i.e. Collection, not
-        // Collection<Foo>), so we can return Object.class to allow no restriction.
-
-        if (type instanceof Class) return Object.class;
-
-        if (!(type instanceof ParameterizedType)) return null;
-
-        ParameterizedType pt = (ParameterizedType) type;
-
-        Type[] types = pt.getActualTypeArguments();
-
-        Type actualType = types[typeIndex];
-
-        return actualType instanceof Class ? (Class) actualType : null;
-
+        return getParameterDefaultsWithConfiguration(
+                _builderMethod.getParameterTypes(),
+                _builderMethod.getGenericParameterTypes());
     }
 
     /**
@@ -252,7 +70,7 @@
                     _resources,
                     getParameterDefaultsWithConfigurations());
 
-            if (_log.isDebugEnabled()) _log.debug(IOCMessages.invokingMethod(methodId()));
+            if (_log.isDebugEnabled()) _log.debug(IOCMessages.invokingMethod(_creatorDescription));
 
             result = _builderMethod.invoke(moduleBuilder, parameters);
         }
@@ -267,14 +85,15 @@
 
         if (failure != null)
             throw new RuntimeException(IOCMessages.builderMethodError(
-                    methodId(),
+                    _creatorDescription,
                     _serviceId,
                     failure), failure);
 
         if (result == null)
-            throw new RuntimeException(IOCMessages
-                    .builderMethodReturnedNull(methodId(), _serviceId));
+            throw new RuntimeException(IOCMessages.builderMethodReturnedNull(
+                    _creatorDescription,
+                    _serviceId));
 
         return result;
     }
-}
+}
\ No newline at end of file

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceDefAccumulator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceDefAccumulator.java?view=auto&rev=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceDefAccumulator.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceDefAccumulator.java Mon Apr 16 16:31:50 2007
@@ -0,0 +1,22 @@
+// 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;
+
+import org.apache.tapestry.ioc.def.ServiceDef;
+
+public interface ServiceDefAccumulator
+{
+    void addServiceDef(ServiceDef serviceDef);
+}

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceDefImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceDefImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceDefImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceDefImpl.java Mon Apr 16 16:31:50 2007
@@ -14,17 +14,13 @@
 
 package org.apache.tapestry.ioc.internal;
 
-import java.lang.reflect.Method;
-
 import org.apache.tapestry.ioc.ObjectCreator;
 import org.apache.tapestry.ioc.ServiceBuilderResources;
 import org.apache.tapestry.ioc.def.ServiceDef;
-import org.apache.tapestry.ioc.internal.util.InternalUtils;
-import org.apache.tapestry.ioc.services.ClassFactory;
 
 public class ServiceDefImpl implements ServiceDef
 {
-    private final Method _builderMethod;
+    private final Class _serviceInterface;
 
     private final String _serviceId;
 
@@ -32,32 +28,27 @@
 
     private final boolean _eagerLoad;
 
-    private final ClassFactory _classFactory;
+    private final ObjectCreatorSource _source;
 
-    ServiceDefImpl(String serviceId, String scope, Method builderMethod, boolean eagerLoad,
-            ClassFactory classFactory)
+    ServiceDefImpl(Class serviceInterface, String serviceId, String scope, boolean eagerLoad,
+            ObjectCreatorSource source)
     {
+        _serviceInterface = serviceInterface;
         _serviceId = serviceId;
         _scope = scope;
-        _builderMethod = builderMethod;
         _eagerLoad = eagerLoad;
-        _classFactory = classFactory;
+        _source = source;
     }
 
     @Override
     public String toString()
     {
-        return InternalUtils.asString(_builderMethod, _classFactory);
-    }
-
-    Method getBuilderMethod()
-    {
-        return _builderMethod;
+        return _source.getDescription();
     }
 
     public ObjectCreator createServiceCreator(ServiceBuilderResources resources)
     {
-        return new ServiceBuilderMethodInvoker(_builderMethod, resources, _classFactory);
+        return _source.constructCreator(resources);
     }
 
     public String getServiceId()
@@ -67,7 +58,7 @@
 
     public Class getServiceInterface()
     {
-        return _builderMethod.getReturnType();
+        return _serviceInterface;
     }
 
     public String getServiceScope()

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceResourcesImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceResourcesImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceResourcesImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ServiceResourcesImpl.java Mon Apr 16 16:31:50 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,92 +12,88 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.ioc.internal;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.tapestry.ioc.ServiceBuilderResources;
-import org.apache.tapestry.ioc.def.ServiceDef;
-
-/**
- * Implementation of {@link org.apache.tapestry.ioc.ServiceBuilderResources}. We just have one
- * implementation that fills the purposes of methods that need a
- * {@link org.apache.tapestry.ioc.ServiceResources} (which includes service decorator methods) as
- * well as methods that need a {@link org.apache.tapestry.ioc.ServiceBuilderResources} (which is
- * just service builder methods). Since it is most commonly used for the former, we'll just leave
- * the name as ServiceResourcesImpl.
- * 
- * 
- */
-public class ServiceResourcesImpl extends ServiceLocatorImpl implements ServiceBuilderResources
-{
-    private final ServiceDef _serviceDef;
-
-    private Log _log;
-
-    public ServiceResourcesImpl(InternalRegistry registry, Module module, ServiceDef serviceDef,
-            Log log)
-    {
-        super(registry, module);
-        _serviceDef = serviceDef;
-        _log = log;
-    }
-
-    public String getServiceId()
-    {
-        return _serviceDef.getServiceId();
-    }
-
-    public Class getServiceInterface()
-    {
-        return _serviceDef.getServiceInterface();
-    }
-
-    public Log getServiceLog()
-    {
-        return _log;
-    }
-
-    public <T> Collection<T> getUnorderedConfiguration(Class<T> valueType)
-    {
-        Collection<T> result = getRegistry().getUnorderedConfiguration(_serviceDef, valueType);
-
-        logConfiguration(result);
-
-        return result;
-    }
-
-    private void logConfiguration(Collection configuration)
-    {
-        if (_log.isDebugEnabled())
-            _log.debug(IOCMessages.constructedConfiguration(configuration));
-    }
-
-    public <T> List<T> getOrderedConfiguration(Class<T> valueType)
-    {
-        List<T> result = getRegistry().getOrderedConfiguration(_serviceDef, valueType);
-
-        logConfiguration(result);
-
-        return result;
-    }
-
-    public <K, V> Map<K, V> getMappedConfiguration(Class<K> keyType, Class<V> valueType)
-    {
-        Map<K, V> result = getRegistry().getMappedConfiguration(_serviceDef, keyType, valueType);
-
-        if (_log.isDebugEnabled())
-            _log.debug(IOCMessages.constructedConfiguration(result));
-
-        return result;
-    }
-
-    public Object getModuleBuilder()
-    {
-        return getModule().getModuleBuilder();
-    }
-
-}
+package org.apache.tapestry.ioc.internal;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
+import org.apache.tapestry.ioc.def.ServiceDef;
+
+/**
+ * Implementation of {@link org.apache.tapestry.ioc.ServiceBuilderResources}. We just have one
+ * implementation that fills the purposes of methods that need a
+ * {@link org.apache.tapestry.ioc.ServiceResources} (which includes service decorator methods) as
+ * well as methods that need a {@link org.apache.tapestry.ioc.ServiceBuilderResources} (which is
+ * just service builder methods). Since it is most commonly used for the former, we'll just leave
+ * the name as ServiceResourcesImpl.
+ */
+public class ServiceResourcesImpl extends ServiceLocatorImpl implements ServiceBuilderResources
+{
+    private final ServiceDef _serviceDef;
+
+    private final Log _log;
+
+    public ServiceResourcesImpl(InternalRegistry registry, Module module, ServiceDef serviceDef,
+            Log log)
+    {
+        super(registry, module);
+        _serviceDef = serviceDef;
+        _log = log;
+    }
+
+    public String getServiceId()
+    {
+        return _serviceDef.getServiceId();
+    }
+
+    public Class getServiceInterface()
+    {
+        return _serviceDef.getServiceInterface();
+    }
+
+    public Log getServiceLog()
+    {
+        return _log;
+    }
+
+    public <T> Collection<T> getUnorderedConfiguration(Class<T> valueType)
+    {
+        Collection<T> result = getRegistry().getUnorderedConfiguration(_serviceDef, valueType);
+
+        logConfiguration(result);
+
+        return result;
+    }
+
+    private void logConfiguration(Collection configuration)
+    {
+        if (_log.isDebugEnabled()) _log.debug(IOCMessages.constructedConfiguration(configuration));
+    }
+
+    public <T> List<T> getOrderedConfiguration(Class<T> valueType)
+    {
+        List<T> result = getRegistry().getOrderedConfiguration(_serviceDef, valueType);
+
+        logConfiguration(result);
+
+        return result;
+    }
+
+    public <K, V> Map<K, V> getMappedConfiguration(Class<K> keyType, Class<V> valueType)
+    {
+        Map<K, V> result = getRegistry().getMappedConfiguration(_serviceDef, keyType, valueType);
+
+        if (_log.isDebugEnabled()) _log.debug(IOCMessages.constructedConfiguration(result));
+
+        return result;
+    }
+
+    public Object getModuleBuilder()
+    {
+        return getModule().getModuleBuilder();
+    }
+
+}

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ChainBuilderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ChainBuilderImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ChainBuilderImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ChainBuilderImpl.java Mon Apr 16 16:31:50 2007
@@ -22,6 +22,7 @@
 import java.util.List;
 import java.util.Map;
 
+import org.apache.tapestry.ioc.annotations.InjectService;
 import org.apache.tapestry.ioc.services.ChainBuilder;
 import org.apache.tapestry.ioc.services.ClassFab;
 import org.apache.tapestry.ioc.services.ClassFabUtils;
@@ -40,7 +41,8 @@
 
     private Map<Class, Class> _cache = newConcurrentMap();
 
-    public ChainBuilderImpl(ClassFactory classFactory)
+    public ChainBuilderImpl(@InjectService("ClassFactory")
+    ClassFactory classFactory)
     {
         _classFactory = classFactory;
     }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryImpl.java Mon Apr 16 16:31:50 2007
@@ -16,9 +16,11 @@
 
 import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
 
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 
 import javassist.CtClass;
+import javassist.CtConstructor;
 import javassist.CtMethod;
 
 import org.apache.commons.logging.Log;
@@ -147,4 +149,52 @@
         }
     }
 
+    public String getConstructorLocation(Constructor constructor)
+    {
+        notNull(constructor, "constructor");
+
+        StringBuilder builder = new StringBuilder();
+
+        Class declaringClass = constructor.getDeclaringClass();
+
+        builder.append(declaringClass.getName());
+        builder.append("(");
+
+        CtClass ctClass = _classSource.getCtClass(declaringClass);
+
+        StringBuilder descripton = new StringBuilder("(");
+
+        Class[] parameterTypes = constructor.getParameterTypes();
+        for (int i = 0; i < parameterTypes.length; i++)
+        {
+            Class parameterType = parameterTypes[i];
+
+            if (i > 0) builder.append(", ");
+
+            builder.append(parameterType.getSimpleName());
+
+            descripton.append(ClassFabUtils.getTypeCode(parameterType));
+        }
+
+        builder.append(")");
+
+        // A constructor resembles a method of type void
+        descripton.append(")V");
+
+        try
+        {
+            CtConstructor ctConstructor = ctClass.getConstructor(descripton.toString());
+
+            int lineNumber = ctConstructor.getMethodInfo().getLineNumber(0);
+
+            String sourceFile = ctConstructor.getDeclaringClass().getClassFile2().getSourceFile();
+
+            builder.append(String.format(" (at %s:%d)", sourceFile, lineNumber));
+        }
+        catch (Exception ex)
+        {
+        }
+
+        return builder.toString();
+    }
 }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/DefaultImplementationBuilderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/DefaultImplementationBuilderImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/DefaultImplementationBuilderImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/DefaultImplementationBuilderImpl.java Mon Apr 16 16:31:50 2007
@@ -12,89 +12,90 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.ioc.internal.services;
-
-import static java.lang.String.format;
+package org.apache.tapestry.ioc.internal.services;
+
+import static java.lang.String.format;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newConcurrentMap;
-
-import java.util.Map;
-
-import org.apache.tapestry.ioc.services.ClassFab;
-import org.apache.tapestry.ioc.services.ClassFactory;
-import org.apache.tapestry.ioc.services.DefaultImplementationBuilder;
-import org.apache.tapestry.ioc.services.MethodIterator;
-import org.apache.tapestry.ioc.services.MethodSignature;
-
-/**
- * 
- */
-public class DefaultImplementationBuilderImpl implements DefaultImplementationBuilder
-{
-    private final Map<Class, Object> _cache = newConcurrentMap();
-
-    private final ClassFactory _classFactory;
-
-    public DefaultImplementationBuilderImpl(ClassFactory classFactory)
-    {
-        _classFactory = classFactory;
-    }
-
-    public <S> S createDefaultImplementation(Class<S> serviceInterface)
-    {
-        S instance = serviceInterface.cast(_cache.get(serviceInterface));
-
-        if (instance == null)
-        {
-            instance = createInstance(serviceInterface);
-            _cache.put(serviceInterface, instance);
-        }
-
-        return instance;
-    }
-
-    /**
-     * Creates a class and an instance of that class. Updates the cache and returns the instance.
-     */
-    private <S> S createInstance(Class<S> serviceInterface)
-    {
-        // In rare race conditions, we may end up creating two (or more)
-        // NOOP class/instance pairs for the same interface. You need multiple threads
-        // asking for a NOOP class for the same interface pretty much simulataneously.
-        // We just let this happen.
-
-        Class<S> noopClass = createClass(serviceInterface);
-
-        try
-        {
-            S instance = noopClass.newInstance();
-
-            _cache.put(serviceInterface, instance);
-
-            return instance;
-        }
-        catch (Exception ex)
-        {
-            throw new RuntimeException(ex);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private <S> Class<S> createClass(Class<S> serviceInterface)
-    {
-        ClassFab cf = _classFactory.newClass(serviceInterface);
-
-        MethodIterator mi = new MethodIterator(serviceInterface);
-
-        while (mi.hasNext())
-        {
-            MethodSignature sig = mi.next();
-
-            cf.addNoOpMethod(sig);
-        }
-
-        if (!mi.getToString())
-            cf.addToString(format("<NoOp %s>", serviceInterface.getName()));
-
-        return cf.createClass();
-    }
+
+import java.util.Map;
+
+import org.apache.tapestry.ioc.annotations.InjectService;
+import org.apache.tapestry.ioc.services.ClassFab;
+import org.apache.tapestry.ioc.services.ClassFactory;
+import org.apache.tapestry.ioc.services.DefaultImplementationBuilder;
+import org.apache.tapestry.ioc.services.MethodIterator;
+import org.apache.tapestry.ioc.services.MethodSignature;
+
+/**
+ * 
+ */
+public class DefaultImplementationBuilderImpl implements DefaultImplementationBuilder
+{
+    private final Map<Class, Object> _cache = newConcurrentMap();
+
+    private final ClassFactory _classFactory;
+
+    public DefaultImplementationBuilderImpl(@InjectService("ClassFactory")
+    ClassFactory classFactory)
+    {
+        _classFactory = classFactory;
+    }
+
+    public <S> S createDefaultImplementation(Class<S> serviceInterface)
+    {
+        S instance = serviceInterface.cast(_cache.get(serviceInterface));
+
+        if (instance == null)
+        {
+            instance = createInstance(serviceInterface);
+            _cache.put(serviceInterface, instance);
+        }
+
+        return instance;
+    }
+
+    /**
+     * Creates a class and an instance of that class. Updates the cache and returns the instance.
+     */
+    private <S> S createInstance(Class<S> serviceInterface)
+    {
+        // In rare race conditions, we may end up creating two (or more)
+        // NOOP class/instance pairs for the same interface. You need multiple threads
+        // asking for a NOOP class for the same interface pretty much simulataneously.
+        // We just let this happen.
+
+        Class<S> noopClass = createClass(serviceInterface);
+
+        try
+        {
+            S instance = noopClass.newInstance();
+
+            _cache.put(serviceInterface, instance);
+
+            return instance;
+        }
+        catch (Exception ex)
+        {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private <S> Class<S> createClass(Class<S> serviceInterface)
+    {
+        ClassFab cf = _classFactory.newClass(serviceInterface);
+
+        MethodIterator mi = new MethodIterator(serviceInterface);
+
+        while (mi.hasNext())
+        {
+            MethodSignature sig = mi.next();
+
+            cf.addNoOpMethod(sig);
+        }
+
+        if (!mi.getToString()) cf.addToString(format("<NoOp %s>", serviceInterface.getName()));
+
+        return cf.createClass();
+    }
 }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ExceptionAnalyzerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ExceptionAnalyzerImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ExceptionAnalyzerImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ExceptionAnalyzerImpl.java Mon Apr 16 16:31:50 2007
@@ -23,6 +23,7 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.tapestry.ioc.annotations.Inject;
 import org.apache.tapestry.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry.ioc.services.ClassPropertyAdapter;
 import org.apache.tapestry.ioc.services.ExceptionAnalysis;
@@ -36,7 +37,8 @@
 
     private final Set<String> _throwableProperties;
 
-    public ExceptionAnalyzerImpl(PropertyAccess propertyAccess)
+    public ExceptionAnalyzerImpl(@Inject
+    PropertyAccess propertyAccess)
     {
         _propertyAccess = propertyAccess;
 

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ExceptionTrackerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ExceptionTrackerImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ExceptionTrackerImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ExceptionTrackerImpl.java Mon Apr 16 16:31:50 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,27 +12,26 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.ioc.internal.services;
-
+package org.apache.tapestry.ioc.internal.services;
+
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newSet;
-
-import java.util.Set;
-
-import org.apache.tapestry.ioc.services.ExceptionTracker;
-
-/**
- * 
- */
-public class ExceptionTrackerImpl implements ExceptionTracker
-{
-    private final Set<Throwable> _exceptions = newSet();
-
-    public boolean exceptionLogged(Throwable exception)
-    {
-        boolean result = _exceptions.contains(exception);
-
-        _exceptions.add(exception);
-
-        return result;
-    }
-}
+
+import java.util.Set;
+
+import org.apache.tapestry.ioc.annotations.Scope;
+import org.apache.tapestry.ioc.services.ExceptionTracker;
+
+@Scope("perthread")
+public class ExceptionTrackerImpl implements ExceptionTracker
+{
+    private final Set<Throwable> _exceptions = newSet();
+
+    public boolean exceptionLogged(Throwable exception)
+    {
+        boolean result = _exceptions.contains(exception);
+
+        _exceptions.add(exception);
+
+        return result;
+    }
+}

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/LoggingDecoratorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/LoggingDecoratorImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/LoggingDecoratorImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/LoggingDecoratorImpl.java Mon Apr 16 16:31:50 2007
@@ -22,6 +22,7 @@
 import java.lang.reflect.Modifier;
 
 import org.apache.commons.logging.Log;
+import org.apache.tapestry.ioc.annotations.InjectService;
 import org.apache.tapestry.ioc.services.ClassFab;
 import org.apache.tapestry.ioc.services.ClassFactory;
 import org.apache.tapestry.ioc.services.ExceptionTracker;
@@ -36,7 +37,10 @@
 
     private final ExceptionTracker _exceptionTracker;
 
-    public LoggingDecoratorImpl(ClassFactory classFactory, ExceptionTracker exceptionTracker)
+    public LoggingDecoratorImpl(@InjectService("ClassFactory")
+    ClassFactory classFactory,
+
+    ExceptionTracker exceptionTracker)
     {
         _classFactory = classFactory;
         _exceptionTracker = exceptionTracker;

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PipelineBuilderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PipelineBuilderImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PipelineBuilderImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PipelineBuilderImpl.java Mon Apr 16 16:31:50 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,63 +12,64 @@
 // 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.commons.logging.Log;
-import org.apache.tapestry.ioc.services.ClassFactory;
-import org.apache.tapestry.ioc.services.DefaultImplementationBuilder;
-import org.apache.tapestry.ioc.services.PipelineBuilder;
-
-/**
- * 
- */
-public class PipelineBuilderImpl implements PipelineBuilder
-{
-    private final ClassFactory _classFactory;
-
-    private final DefaultImplementationBuilder _defaultImplementationBuilder;
-
-    public PipelineBuilderImpl(ClassFactory classFactory,
-            DefaultImplementationBuilder defaultImplementationBuilder)
-    {
-        _classFactory = classFactory;
-        _defaultImplementationBuilder = defaultImplementationBuilder;
-    }
-
-    public <S, F> S build(Log log, Class<S> serviceInterface, Class<F> filterInterface,
-            List<F> filters)
-    {
-        S terminator = _defaultImplementationBuilder.createDefaultImplementation(serviceInterface);
-
-        return build(log, serviceInterface, filterInterface, filters, terminator);
-    }
-
-    public <S, F> S build(Log log, Class<S> serviceInterface, Class<F> filterInterface,
-            List<F> filters, S terminator)
-    {
-        if (filters.isEmpty())
-            return terminator;
-
-        BridgeBuilder<S, F> bb = new BridgeBuilder<S, F>(log, serviceInterface, filterInterface,
-                _classFactory);
-
-        // The first bridge will point to the terminator.
-        // Like service decorators, we work deepest (last)
-        // to shallowest (first)
-
-        S next = terminator;
-        int count = filters.size();
-
-        for (int i = count - 1; i >= 0; i--)
-        {
-            F filter = filters.get(i);
-
-            next = bb.instantiateBridge(next, filter);
-        }
-
-        return next;
-    }
-
-}
+package org.apache.tapestry.ioc.internal.services;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.ioc.annotations.Inject;
+import org.apache.tapestry.ioc.annotations.InjectService;
+import org.apache.tapestry.ioc.services.ClassFactory;
+import org.apache.tapestry.ioc.services.DefaultImplementationBuilder;
+import org.apache.tapestry.ioc.services.PipelineBuilder;
+
+public class PipelineBuilderImpl implements PipelineBuilder
+{
+    private final ClassFactory _classFactory;
+
+    private final DefaultImplementationBuilder _defaultImplementationBuilder;
+
+    public PipelineBuilderImpl(@InjectService("ClassFactory")
+    ClassFactory classFactory,
+
+    @Inject
+    DefaultImplementationBuilder defaultImplementationBuilder)
+    {
+        _classFactory = classFactory;
+        _defaultImplementationBuilder = defaultImplementationBuilder;
+    }
+
+    public <S, F> S build(Log log, Class<S> serviceInterface, Class<F> filterInterface,
+            List<F> filters)
+    {
+        S terminator = _defaultImplementationBuilder.createDefaultImplementation(serviceInterface);
+
+        return build(log, serviceInterface, filterInterface, filters, terminator);
+    }
+
+    public <S, F> S build(Log log, Class<S> serviceInterface, Class<F> filterInterface,
+            List<F> filters, S terminator)
+    {
+        if (filters.isEmpty()) return terminator;
+
+        BridgeBuilder<S, F> bb = new BridgeBuilder<S, F>(log, serviceInterface, filterInterface,
+                _classFactory);
+
+        // The first bridge will point to the terminator.
+        // Like service decorators, we work deepest (last)
+        // to shallowest (first)
+
+        S next = terminator;
+        int count = filters.size();
+
+        for (int i = count - 1; i >= 0; i--)
+        {
+            F filter = filters.get(i);
+
+            next = bb.instantiateBridge(next, filter);
+        }
+
+        return next;
+    }
+
+}

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyShadowBuilderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyShadowBuilderImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyShadowBuilderImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyShadowBuilderImpl.java Mon Apr 16 16:31:50 2007
@@ -19,6 +19,8 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Modifier;
 
+import org.apache.tapestry.ioc.annotations.Inject;
+import org.apache.tapestry.ioc.annotations.InjectService;
 import org.apache.tapestry.ioc.services.ClassFab;
 import org.apache.tapestry.ioc.services.ClassFactory;
 import org.apache.tapestry.ioc.services.MethodSignature;
@@ -32,7 +34,11 @@
 
     private final PropertyAccess _propertyAccess;
 
-    public PropertyShadowBuilderImpl(ClassFactory classFactory, PropertyAccess propertyAccess)
+    public PropertyShadowBuilderImpl(@InjectService("ClassFactory")
+    ClassFactory classFactory,
+
+    @Inject
+    PropertyAccess propertyAccess)
     {
         _classFactory = classFactory;
         _propertyAccess = propertyAccess;

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/StrategyBuilderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/StrategyBuilderImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/StrategyBuilderImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/StrategyBuilderImpl.java Mon Apr 16 16:31:50 2007
@@ -16,6 +16,7 @@
 
 import java.lang.reflect.Modifier;
 
+import org.apache.tapestry.ioc.annotations.InjectService;
 import org.apache.tapestry.ioc.services.ClassFab;
 import org.apache.tapestry.ioc.services.ClassFactory;
 import org.apache.tapestry.ioc.services.MethodIterator;
@@ -28,7 +29,8 @@
 {
     private final ClassFactory _classFactory;
 
-    public StrategyBuilderImpl(ClassFactory classFactory)
+    public StrategyBuilderImpl(@InjectService("ClassFactory")
+    ClassFactory classFactory)
     {
         _classFactory = classFactory;
     }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ThreadLocaleImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ThreadLocaleImpl.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ThreadLocaleImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ThreadLocaleImpl.java Mon Apr 16 16:31:50 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -18,8 +18,10 @@
 
 import java.util.Locale;
 
+import org.apache.tapestry.ioc.annotations.Scope;
 import org.apache.tapestry.ioc.services.ThreadLocale;
 
+@Scope("perthread")
 public class ThreadLocaleImpl implements ThreadLocale
 {
     private Locale _locale = Locale.getDefault();

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ValueObjectProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ValueObjectProvider.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ValueObjectProvider.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ValueObjectProvider.java Mon Apr 16 16:31:50 2007
@@ -17,6 +17,7 @@
 import org.apache.tapestry.ioc.AnnotationProvider;
 import org.apache.tapestry.ioc.ObjectProvider;
 import org.apache.tapestry.ioc.ServiceLocator;
+import org.apache.tapestry.ioc.annotations.InjectService;
 import org.apache.tapestry.ioc.annotations.Value;
 import org.apache.tapestry.ioc.services.SymbolSource;
 import org.apache.tapestry.ioc.services.TypeCoercer;
@@ -27,7 +28,11 @@
 
     private final TypeCoercer _typeCoercer;
 
-    public ValueObjectProvider(final SymbolSource symbolSource, final TypeCoercer typeCoercer)
+    public ValueObjectProvider(@InjectService("SymbolSource")
+    SymbolSource symbolSource,
+
+    @InjectService("TypeCoercer")
+    TypeCoercer typeCoercer)
     {
         _symbolSource = symbolSource;
         _typeCoercer = typeCoercer;

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/InternalUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/InternalUtils.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/InternalUtils.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/InternalUtils.java Mon Apr 16 16:31:50 2007
@@ -18,6 +18,7 @@
 import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
 
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Collection;
@@ -91,9 +92,7 @@
 
             String name = method.getParameterTypes()[i].getSimpleName();
 
-            int dotx = name.lastIndexOf('.');
-
-            buffer.append(name.substring(dotx + 1));
+            buffer.append(name);
         }
 
         return buffer.append(")").toString();
@@ -224,11 +223,16 @@
         Class[] parameterTypes = method.getParameterTypes();
         Annotation[][] annotations = method.getParameterAnnotations();
 
-        return InternalUtils.calculateParameters(
-                locator,
-                parameterDefaults,
-                parameterTypes,
-                annotations);
+        return calculateParameters(locator, parameterDefaults, parameterTypes, annotations);
+    }
+
+    public static Object[] calculateParametersForConstructor(Constructor constructor,
+            ServiceLocator locator, Map<Class, Object> parameterDefaults)
+    {
+        Class[] parameterTypes = constructor.getParameterTypes();
+        Annotation[][] annotations = constructor.getParameterAnnotations();
+
+        return calculateParameters(locator, parameterDefaults, parameterTypes, annotations);
     }
 
     public static Object[] calculateParameters(ServiceLocator locator,

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFactory.java Mon Apr 16 16:31:50 2007
@@ -14,6 +14,7 @@
 
 package org.apache.tapestry.ioc.services;
 
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 
 /**
@@ -65,4 +66,10 @@
      * @return the location, or null if the necessary information is not available
      */
     MethodLocation getMethodLocation(Method method);
+
+    /**
+     * Return a string representation fo the constructor (including class and parameters) and (if
+     * available) file name and line number.
+     */
+    String getConstructorLocation(Constructor constructor);
 }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java Mon Apr 16 16:31:50 2007
@@ -27,6 +27,7 @@
 import org.apache.tapestry.ioc.MappedConfiguration;
 import org.apache.tapestry.ioc.ObjectProvider;
 import org.apache.tapestry.ioc.OrderedConfiguration;
+import org.apache.tapestry.ioc.ServiceBinder;
 import org.apache.tapestry.ioc.ServiceLifecycle;
 import org.apache.tapestry.ioc.ServiceLocator;
 import org.apache.tapestry.ioc.annotations.InjectService;
@@ -57,26 +58,29 @@
 {
     private final ClassFactory _classFactory;
 
-    private final PropertyAccess _propertyAccess;
-
     public TapestryIOCModule(@InjectService("ClassFactory")
-    ClassFactory classFactory,
-
-    @InjectService("PropertyAccess")
-    PropertyAccess propertyAccess)
+    ClassFactory classFactory)
     {
         _classFactory = classFactory;
-        _propertyAccess = propertyAccess;
     }
 
-    /**
-     * The LoggingDecorator service is used to decorate a service implementation so that it logs
-     * method entry and exit (at level debug).
-     */
-    public LoggingDecorator build(@InjectService("ExceptionTracker")
-    ExceptionTracker exceptionTracker)
+    public static void bind(ServiceBinder binder)
     {
-        return new LoggingDecoratorImpl(_classFactory, exceptionTracker);
+        binder.bind(LoggingDecorator.class, LoggingDecoratorImpl.class);
+        binder.bind(ChainBuilder.class, ChainBuilderImpl.class);
+        binder.bind(PropertyAccess.class, PropertyAccessImpl.class);
+        binder.bind(StrategyBuilder.class, StrategyBuilderImpl.class);
+        binder.bind(PropertyShadowBuilder.class, PropertyShadowBuilderImpl.class);
+        binder.bind(PipelineBuilder.class, PipelineBuilderImpl.class);
+        binder.bind(DefaultImplementationBuilder.class, DefaultImplementationBuilderImpl.class);
+        binder.bind(ObjectProvider.class, ValueObjectProvider.class).withId("ValueObjectProvider");
+        binder.bind(ExceptionTracker.class, ExceptionTrackerImpl.class);
+        binder.bind(ExceptionAnalyzer.class, ExceptionAnalyzerImpl.class);
+        binder.bind(TypeCoercer.class, TypeCoercerImpl.class);
+        binder.bind(ThreadLocale.class, ThreadLocaleImpl.class);
+        binder.bind(SymbolSource.class, SymbolSourceImpl.class);
+        binder.bind(SymbolProvider.class, MapSymbolProvider.class).withId("ApplicationDefaults");
+        binder.bind(SymbolProvider.class, MapSymbolProvider.class).withId("FactoryDefaults");
     }
 
     /**
@@ -106,57 +110,6 @@
     }
 
     /**
-     * A service that implements the chain of command pattern, creating an efficient implementation
-     * of a chain of command for an arbitrary interface.
-     */
-    public ChainBuilder buildChainBuilder()
-    {
-        return new ChainBuilderImpl(_classFactory);
-    }
-
-    /**
-     * A service that implements the strategy pattern, around a {@link StrategyRegistry}.
-     */
-    public StrategyBuilder buildStrategyBuilder()
-    {
-        return new StrategyBuilderImpl(_classFactory);
-    }
-
-    /**
-     * Services that provides read/write access to JavaBean properties. Encapsulates JavaBean
-     * introspection, including serializing access to the non-thread-safe Introspector object.
-     */
-    public static PropertyAccess buildPropertyAccess()
-    {
-        return new PropertyAccessImpl();
-    }
-
-    /**
-     * Builder that creates a shadow, a projection of a property of some other object.
-     */
-    public PropertyShadowBuilder buildPropertyShadowBuilder()
-    {
-        return new PropertyShadowBuilderImpl(_classFactory, _propertyAccess);
-    }
-
-    /**
-     * Builder that creates a filter pipeline around a simple service interface.
-     */
-    public PipelineBuilder build(@InjectService("DefaultImplementationBuilder")
-    DefaultImplementationBuilder builder)
-    {
-        return new PipelineBuilderImpl(_classFactory, builder);
-    }
-
-    /**
-     * Builder that creates a default implementation of an interface.
-     */
-    public DefaultImplementationBuilder buildDefaultImplementationBuilder()
-    {
-        return new DefaultImplementationBuilderImpl(_classFactory);
-    }
-
-    /**
      * The master {@link ObjectProvider} is responsible for identifying a particular ObjectProvider
      * by its prefix, and delegating to that instance.
      */
@@ -194,35 +147,6 @@
         configuration.add("Value", valueObjectProvider);
     }
 
-    public static ObjectProvider buildValueObjectProvider(@InjectService("TypeCoercer")
-    TypeCoercer typeCoercer,
-
-    @InjectService("SymbolSource")
-    SymbolSource symbolSource)
-    {
-        return new ValueObjectProvider(symbolSource, typeCoercer);
-    }
-
-    /** Used by the {@link org.apache.tapestry.ioc.services.LoggingDecorator} service. */
-    @Scope("perthread")
-    public static ExceptionTracker buildExceptionTracker()
-    {
-        return new ExceptionTrackerImpl();
-    }
-
-    public ExceptionAnalyzer buildExceptionAnalyzer()
-    {
-        return new ExceptionAnalyzerImpl(_propertyAccess);
-    }
-
-    /**
-     * Returns the service that can coerce between different types.
-     */
-    public static TypeCoercer build(Collection<CoercionTuple> configuration)
-    {
-        return new TypeCoercerImpl(configuration);
-    }
-
     /**
      * Contributes a set of standard type coercions:
      * <ul>
@@ -448,17 +372,6 @@
         configuration.add(tuple);
     }
 
-    @Scope("perthread")
-    public static ThreadLocale buildThreadLocale()
-    {
-        return new ThreadLocaleImpl();
-    }
-
-    public static SymbolSource build(List<SymbolProvider> configuration)
-    {
-        return new SymbolSourceImpl(configuration);
-    }
-
     public static void contributeSymbolSource(OrderedConfiguration<SymbolProvider> configuration,
             @InjectService("ApplicationDefaults")
             SymbolProvider applicationDefaults, @InjectService("FactoryDefaults")
@@ -467,15 +380,5 @@
         configuration.add("SystemProperties", new SystemPropertiesSymbolProvider());
         configuration.add("ApplicationDefaults", applicationDefaults, "after:SystemProperties");
         configuration.add("FactoryDefaults", factoryDefaults, "after:ApplicationDefaults");
-    }
-
-    public static SymbolProvider buildApplicationDefaults(Map<String, String> configuration)
-    {
-        return new MapSymbolProvider(configuration);
-    }
-
-    public static SymbolProvider buildFactoryDefaults(Map<String, String> configuration)
-    {
-        return new MapSymbolProvider(configuration);
     }
 }

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java?view=diff&rev=529445&r1=529444&r2=529445
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java Mon Apr 16 16:31:50 2007
@@ -180,7 +180,7 @@
         expect(decorator.createInterceptor(coreObject)).andReturn(interceptor);
     }
 
-    protected final ServiceBuilderResources newServiceCreatorResources()
+    protected final ServiceBuilderResources newServiceBuilderResources()
     {
         return newMock(ServiceBuilderResources.class);
     }