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

svn commit: r431064 [1/2] - in /tapestry/tapestry5/tapestry-core/trunk/src: main/java/org/apache/tapestry/ main/java/org/apache/tapestry/internal/ioc/ main/java/org/apache/tapestry/internal/ioc/services/ main/java/org/apache/tapestry/internal/pageload/...

Author: hlship
Date: Sat Aug 12 11:24:17 2006
New Revision: 431064

URL: http://svn.apache.org/viewvc?rev=431064&view=rev
Log:
Add support for parameter injection into module class constructors (as a way to cache common services).
Rename ServiceCreator to ObjectCreator.
Change some method signatures to support deferring the creation of the module builder instance until just as needed.

Added:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectCreator.java
      - copied, changed from r428940, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceBuilderResources.java
      - copied, changed from r428940, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ComponentNameExpander.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ExtraPublicConstructorsModule.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/PrivateConstructorModule.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/RecursiveConstructorModule.java
Removed:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java
Modified:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InterceptorStackBuilder.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/OneShotServiceCreator.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceCreator.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceLifecycle.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/PageLoaderImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/provider.apt
    tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/service.apt
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/InterceptorStackBuilderTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/OneShortServiceCreatorTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvokerTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycleTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java Sat Aug 12 11:24:17 2006
@@ -21,5 +21,9 @@
  */
 public interface ComponentResources
 {
-
+    /**
+     * Returns the id of the component. The id will be unique within the component's immediate
+     * container. For a page's root component, the value null is returned.
+     */
+    String getId();
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java Sat Aug 12 11:24:17 2006
@@ -14,6 +14,7 @@
 
 package org.apache.tapestry.internal.ioc;
 
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
 import java.util.List;
@@ -242,5 +243,27 @@
     static String errorBuildingService(String serviceId, ServiceDef serviceDef, Throwable cause)
     {
         return MESSAGES.format("error-building-service", serviceId, serviceDef, cause);
+    }
+
+    static String noPublicConstructors(String moduleId, Class moduleBuilderClass)
+    {
+        return MESSAGES.format("no-public-constructors", moduleId, moduleBuilderClass.getName());
+    }
+
+    static String tooManyPublicConstructors(String moduleId, Class moduleBuilderClass,
+            Constructor constructor)
+    {
+        return MESSAGES.format("too-many-public-constructors", moduleId, moduleBuilderClass
+                .getName(), constructor);
+    }
+
+    static String recursiveModuleConstructor(String moduleId, Class builderClass,
+            Constructor constructor)
+    {
+        return MESSAGES.format(
+                "recursive-module-constructor",
+                moduleId,
+                builderClass.getName(),
+                constructor);
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java Sat Aug 12 11:24:17 2006
@@ -26,7 +26,8 @@
 import org.apache.tapestry.ioc.ServiceLocator;
 import org.apache.tapestry.ioc.annotations.Inject;
 import org.apache.tapestry.ioc.annotations.InjectService;
-import org.apache.tapestry.util.CollectionFactory;
+
+import static org.apache.tapestry.util.CollectionFactory.newList;
 
 /**
  * Contains static methods used within this package.
@@ -100,6 +101,14 @@
     {
         Class[] parameterTypes = method.getParameterTypes();
         Annotation[][] annotations = method.getParameterAnnotations();
+
+        return calculateParameters(locator, parameterDefaults, parameterTypes, annotations);
+    }
+
+    public static Object[] calculateParameters(ServiceLocator locator,
+            Map<Class, Object> parameterDefaults, Class[] parameterTypes,
+            Annotation[][] parameterAnnotations)
+    {
         int parameterCount = parameterTypes.length;
 
         Object[] parameters = new Object[parameterCount];
@@ -108,7 +117,7 @@
         {
             parameters[i] = calculateParameterValue(
                     parameterTypes[i],
-                    annotations[i],
+                    parameterAnnotations[i],
                     locator,
                     parameterDefaults);
         }
@@ -138,7 +147,7 @@
     /** Creates a sorted copy of the provided elements, then turns that into a comma separated list. */
     public static String joinSorted(Collection<String> elements)
     {
-        List<String> list = CollectionFactory.newList(elements);
+        List<String> list = newList(elements);
 
         Collections.sort(list);
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InterceptorStackBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InterceptorStackBuilder.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InterceptorStackBuilder.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InterceptorStackBuilder.java Sat Aug 12 11:24:17 2006
@@ -17,7 +17,7 @@
 import java.util.Collections;
 import java.util.List;
 
-import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ObjectCreator;
 import org.apache.tapestry.ioc.ServiceDecorator;
 
 /**
@@ -26,11 +26,11 @@
  * 
  * @author Howard M. Lewis Ship
  */
-public class InterceptorStackBuilder implements ServiceCreator
+public class InterceptorStackBuilder implements ObjectCreator
 {
     private final String _serviceId;
 
-    private final ServiceCreator _coreServiceCreator;
+    private final ObjectCreator _coreServiceCreator;
 
     private final Module _module;
 
@@ -44,16 +44,16 @@
      *            interceptors
      */
     public InterceptorStackBuilder(Module module, String serviceId,
-            ServiceCreator coreServiceCreator)
+            ObjectCreator coreServiceCreator)
     {
         _module = module;
         _serviceId = serviceId;
         _coreServiceCreator = coreServiceCreator;
     }
 
-    public Object createService()
+    public Object createObject()
     {
-        Object current = _coreServiceCreator.createService();
+        Object current = _coreServiceCreator.createObject();
 
         List<ServiceDecorator> decorators = _module.findDecoratorsForService(_serviceId);
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java Sat Aug 12 11:24:17 2006
@@ -14,7 +14,7 @@
 
 package org.apache.tapestry.internal.ioc;
 
-import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ObjectCreator;
 import org.apache.tapestry.ioc.ServiceLifecycle;
 import org.apache.tapestry.ioc.ServiceResources;
 
@@ -25,16 +25,16 @@
  * 
  * @author Howard M. Lewis Ship
  */
-public class LifecycleWrappedServiceCreator implements ServiceCreator
+public class LifecycleWrappedServiceCreator implements ObjectCreator
 {
     private final ServiceLifecycle _lifecycle;
 
     private final ServiceResources _resources;
 
-    private final ServiceCreator _creator;
+    private final ObjectCreator _creator;
 
     public LifecycleWrappedServiceCreator(ServiceLifecycle lifecycle, ServiceResources resources,
-            ServiceCreator creator)
+            ObjectCreator creator)
     {
         _lifecycle = lifecycle;
         _resources = resources;
@@ -45,7 +45,7 @@
      * Passes the resources and the service creator through the
      * {@link org.apache.tapestry.ioc.ServiceLifecycle}.
      */
-    public Object createService()
+    public Object createObject()
     {
         return _lifecycle.createService(_resources, _creator);
     }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java Sat Aug 12 11:24:17 2006
@@ -14,6 +14,8 @@
 
 package org.apache.tapestry.internal.ioc;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Modifier;
 import java.util.Collection;
 import java.util.List;
@@ -22,10 +24,11 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.tapestry.internal.annotations.SuppressNullCheck;
-import org.apache.tapestry.ioc.ServiceCreator;
-import org.apache.tapestry.ioc.ServiceCreatorResources;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
 import org.apache.tapestry.ioc.ServiceDecorator;
 import org.apache.tapestry.ioc.ServiceLifecycle;
+import org.apache.tapestry.ioc.ServiceLocator;
 import org.apache.tapestry.ioc.ServiceResources;
 import org.apache.tapestry.ioc.def.ContributionDef;
 import org.apache.tapestry.ioc.def.DecoratorDef;
@@ -51,14 +54,23 @@
 
     private final ModuleDef _moduleDef;
 
+    private final Log _log;
+
     private Object _moduleBuilder;
 
     private final static String INTERNAL_MODULE_ID = "tapestry.ioc";
 
-    public ModuleImpl(InternalRegistry registry, ModuleDef moduleDef)
+    // Set to true when invoking the module constructor. Used to
+    // detect endless loops caused by irresponsible dependencies into
+    // the constructor.
+
+    private boolean _insideConstructor;
+
+    public ModuleImpl(InternalRegistry registry, ModuleDef moduleDef, Log log)
     {
         _registry = registry;
         _moduleDef = moduleDef;
+        _log = log;
     }
 
     /** Keyed on fully qualified service id; values are instantiated services (proxies). */
@@ -114,7 +126,6 @@
         return def.isPrivate() && this != module;
     }
 
-    /** TODO: Returns an empty list currently. */
     public List<ServiceDecorator> findDecoratorsForService(String serviceId)
     {
         ServiceDef sd = _moduleDef.getServiceDef(serviceId);
@@ -185,12 +196,12 @@
         {
             ServiceLifecycle lifecycle = _registry.getServiceLifecycle(def.getServiceLifeycle());
 
-            ServiceCreatorResources resources = new ServiceResourcesImpl(_registry, this, def, log);
+            ServiceBuilderResources resources = new ServiceResourcesImpl(_registry, this, def, log);
 
             // Build up a stack of operations that will be needed to instantiate the service
             // (by the proxy, at a later date).
 
-            ServiceCreator creator = def.createServiceCreator(getModuleBuilder(), resources);
+            ObjectCreator creator = def.createServiceCreator(resources);
 
             creator = new LifecycleWrappedServiceCreator(lifecycle, resources, creator);
 
@@ -199,13 +210,11 @@
             if (!getModuleId().equals(INTERNAL_MODULE_ID))
                 creator = new InterceptorStackBuilder(this, serviceId, creator);
 
-            Object service = null;
-
             // Add a wrapper that makes sure that it only gets created once.
 
             creator = new OneShotServiceCreator(def, creator);
 
-            service = createProxy(resources, creator);
+            Object service = createProxy(resources, creator);
 
             _services.put(serviceId, service);
 
@@ -217,37 +226,78 @@
         }
     }
 
-    private synchronized void ensureModuleBuilderExists()
+    public synchronized Object getModuleBuilder()
     {
-        if (_moduleBuilder != null)
-            return;
+        if (_moduleBuilder == null)
+            _moduleBuilder = instantiateModuleBuilder();
+
+        return _moduleBuilder;
+    }
 
+    private Object instantiateModuleBuilder()
+    {
         Class builderClass = _moduleDef.getBuilderClass();
 
-        // TODO: Support additional constructors (beyond no arguments constructor)?
+        Constructor[] constructors = builderClass.getConstructors();
+
+        if (constructors.length == 0)
+            throw new RuntimeException(IOCMessages.noPublicConstructors(
+                    _moduleDef.getModuleId(),
+                    builderClass));
+
+        // Use the first one.
+
+        Constructor constructor = constructors[0];
+
+        if (constructors.length > 1)
+            _log.warn(IOCMessages.tooManyPublicConstructors(
+                    _moduleDef.getModuleId(),
+                    builderClass,
+                    constructor));
+
+        if (_insideConstructor)
+            throw new RuntimeException(IOCMessages.recursiveModuleConstructor(_moduleDef
+                    .getModuleId(), builderClass, constructor));
+
+        ServiceLocator locator = new ServiceLocatorImpl(_registry, this);
+        Map<Class, Object> parameterDefaults = newMap();
+
+        parameterDefaults.put(Log.class, _log);
+        parameterDefaults.put(String.class, _moduleDef.getModuleId());
+        parameterDefaults.put(ServiceLocator.class, locator);
+
+        Throwable fail = null;
 
         try
         {
-            _moduleBuilder = builderClass.newInstance();
+            _insideConstructor = true;
+
+            Object[] parameterValues = IOCUtilities.calculateParameters(
+                    locator,
+                    parameterDefaults,
+                    constructor.getParameterTypes(),
+                    constructor.getParameterAnnotations());
+
+            return constructor.newInstance(parameterValues);
+        }
+        catch (InvocationTargetException ex)
+        {
+            fail = ex.getTargetException();
         }
         catch (Exception ex)
         {
-            throw new RuntimeException(IOCMessages.instantiateBuilderError(builderClass, _moduleDef
-                    .getModuleId(), ex), ex);
+            fail = ex;
+        }
+        finally
+        {
+            _insideConstructor = false;
         }
-    }
-
-    public Object getModuleBuilder()
-    {
-        // Pretty sure that in the situations where this method is invoked, the MB will already have
-        // been instantiated, but just to be safe.
-
-        ensureModuleBuilderExists();
 
-        return _moduleBuilder;
+        throw new RuntimeException(IOCMessages.instantiateBuilderError(builderClass, _moduleDef
+                .getModuleId(), fail), fail);
     }
 
-    private Object createProxy(ServiceResources resources, ServiceCreator creator)
+    private Object createProxy(ServiceResources resources, ObjectCreator creator)
     {
         String serviceId = resources.getServiceId();
         Class serviceInterface = resources.getServiceInterface();
@@ -257,7 +307,7 @@
         return createProxyInstance(creator, serviceId, serviceInterface, toString);
     }
 
-    private Object createProxyInstance(ServiceCreator creator, String serviceId,
+    private Object createProxyInstance(ObjectCreator creator, String serviceId,
             Class serviceInterface, String description)
     {
         Class proxyClass = createProxyClass(serviceId, serviceInterface, description);
@@ -278,11 +328,11 @@
     {
         ClassFab cf = _registry.newClass(serviceInterface);
 
-        cf.addField("_creator", ServiceCreator.class);
+        cf.addField("_creator", ObjectCreator.class);
         cf.addField("_delegate", serviceInterface);
 
         cf.addConstructor(new Class[]
-        { ServiceCreator.class }, null, "_creator = $1;");
+        { ObjectCreator.class }, null, "_creator = $1;");
 
         addDelegateGetter(cf, serviceInterface);
 
@@ -300,7 +350,7 @@
 
         builder.addln("if (_delegate == null)");
         builder.begin();
-        builder.addln("_delegate = (%s) _creator.createService();", serviceInterface.getName());
+        builder.addln("_delegate = (%s) _creator.createObject();", serviceInterface.getName());
         builder.addln("_creator = null;");
         builder.end();
 
@@ -333,4 +383,5 @@
 
         return result;
     }
+
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/OneShotServiceCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/OneShotServiceCreator.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/OneShotServiceCreator.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/OneShotServiceCreator.java Sat Aug 12 11:24:17 2006
@@ -14,11 +14,11 @@
 
 package org.apache.tapestry.internal.ioc;
 
-import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ObjectCreator;
 import org.apache.tapestry.ioc.def.ServiceDef;
 
 /**
- * Decorator for {@link org.apache.tapestry.ioc.ServiceCreator} that ensures the service is only
+ * Decorator for {@link org.apache.tapestry.ioc.ObjectCreator} that ensures the service is only
  * created once. This detects a situation where the service builder for a service directly or
  * indirectly invokes methods on the service itself. This would show up as a second call up the
  * ServiceCreator stack injected into the proxy.
@@ -28,15 +28,15 @@
  * 
  * @author Howard M. Lewis Ship
  */
-public class OneShotServiceCreator implements ServiceCreator
+public class OneShotServiceCreator implements ObjectCreator
 {
     private final ServiceDef _serviceDef;
 
-    private final ServiceCreator _delegate;
+    private final ObjectCreator _delegate;
 
     private boolean _locked;
 
-    public OneShotServiceCreator(ServiceDef serviceDef, ServiceCreator delegate)
+    public OneShotServiceCreator(ServiceDef serviceDef, ObjectCreator delegate)
     {
         _serviceDef = serviceDef;
         _delegate = delegate;
@@ -46,14 +46,14 @@
      * We could make this method synchronized, but in the context of creating a service for a proxy,
      * it will already be synchronized (inside the proxy).
      */
-    public Object createService()
+    public Object createObject()
     {
         if (_locked)
             throw new IllegalStateException(IOCMessages.recursiveServiceBuild(_serviceDef));
 
         _locked = true;
 
-        return _delegate.createService();
+        return _delegate.createObject();
     }
 
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java Sat Aug 12 11:24:17 2006
@@ -64,6 +64,8 @@
      */
     static final String CLASS_FACTORY_SERVICE_ID = "tapestry.ioc.ClassFactory";
 
+    static final String LOG_SOURCE_SERVICE_ID = "tapestry.ioc.LogSource";
+
     private final Map<String, Object> _builtinServices = newMap();
 
     private final Map<String, Class> _builtinTypes = newMap();
@@ -102,9 +104,14 @@
 
         for (ModuleDef def : moduleDefs)
         {
-            Module module = new ModuleImpl(this, def);
+            Log log = _logSource.getLog(def.getModuleId());
+
+            Module module = new ModuleImpl(this, def, log);
+
             _modules.put(def.getModuleId(), module);
         }
+
+        addBuiltin(LOG_SOURCE_SERVICE_ID, LogSource.class, _logSource);
 
         Log log = _logSource.getLog(RegistryImpl.CLASS_FACTORY_SERVICE_ID);
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java Sat Aug 12 11:24:17 2006
@@ -23,8 +23,8 @@
 import java.util.Map;
 
 import org.apache.commons.logging.Log;
-import org.apache.tapestry.ioc.ServiceCreator;
-import org.apache.tapestry.ioc.ServiceCreatorResources;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
 import org.apache.tapestry.ioc.ServiceResources;
 
 import static org.apache.tapestry.internal.ioc.ConfigurationType.MAPPED;
@@ -34,21 +34,19 @@
 import static org.apache.tapestry.util.CollectionFactory.newMap;
 
 /**
- * Basic implementation of {@link org.apache.tapestry.ioc.ServiceCreator} that handles invoking a
+ * 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.
  * 
  * @author Howard M. Lewis Ship
  */
-public class ServiceBuilderMethodInvoker implements ServiceCreator
+public class ServiceBuilderMethodInvoker implements ObjectCreator
 {
-    private final Object _moduleBuilder;
-
     private final String _serviceId;
 
     private final Map<Class, Object> _parameterDefaults = newMap();
 
-    private final ServiceCreatorResources _resources;
+    private final ServiceBuilderResources _resources;
 
     private final Method _builderMethod;
 
@@ -63,12 +61,10 @@
         PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(Map.class, MAPPED);
     }
 
-    public ServiceBuilderMethodInvoker(Method method, Object moduleBuilder,
-            ServiceCreatorResources resources)
+    public ServiceBuilderMethodInvoker(Method method, ServiceBuilderResources resources)
     {
         _serviceId = resources.getServiceId();
         _builderMethod = method;
-        _moduleBuilder = moduleBuilder;
         _resources = resources;
         _log = resources.getServiceLog();
 
@@ -233,8 +229,12 @@
     /**
      * Invoked from the proxy to create the actual service implementation.
      */
-    public Object createService()
+    public Object createObject()
     {
+        // Defer getting (and possibly instantitating) the module builder until the last possible
+        // moment.
+
+        Object moduleBuilder = _resources.getModuleBuilder();
 
         if (_log.isDebugEnabled())
             _log.debug(IOCMessages.invokingMethod(_builderMethod));
@@ -249,7 +249,7 @@
                     _resources,
                     getParameterDefaultsWithConfigurations());
 
-            result = _builderMethod.invoke(_moduleBuilder, parameters);
+            result = _builderMethod.invoke(moduleBuilder, parameters);
         }
         catch (InvocationTargetException ite)
         {

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java Sat Aug 12 11:24:17 2006
@@ -17,8 +17,8 @@
 import java.lang.reflect.Method;
 
 import org.apache.tapestry.internal.util.InternalUtils;
-import org.apache.tapestry.ioc.ServiceCreator;
-import org.apache.tapestry.ioc.ServiceCreatorResources;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
 import org.apache.tapestry.ioc.def.ServiceDef;
 
 /**
@@ -53,9 +53,9 @@
         return _builderMethod;
     }
 
-    public ServiceCreator createServiceCreator(Object moduleBuilder, ServiceCreatorResources resources)
+    public ObjectCreator createServiceCreator(ServiceBuilderResources resources)
     {
-        return new ServiceBuilderMethodInvoker(_builderMethod, moduleBuilder, resources);
+        return new ServiceBuilderMethodInvoker(_builderMethod, resources);
     }
 
     public String getServiceId()

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java?rev=431064&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java Sat Aug 12 11:24:17 2006
@@ -0,0 +1,66 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.ioc;
+
+import org.apache.tapestry.ioc.ServiceLocator;
+
+import static org.apache.tapestry.ioc.IOCUtilities.toQualifiedId;
+
+/**
+ * Base service locator class used when only the module is known (i.e., when instantiating a module
+ * builder class).
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public class ServiceLocatorImpl extends Object implements ServiceLocator
+{
+    private final InternalRegistry _registry;
+
+    private final Module _module;
+
+    public ServiceLocatorImpl(InternalRegistry registry, Module module)
+    {
+        _registry = registry;
+        _module = module;
+    }
+
+    public <T> T getService(String serviceId, Class<T> serviceInterface)
+    {
+        return _registry.getService(
+                toQualifiedId(_module.getModuleId(), serviceId),
+                serviceInterface,
+                _module);
+    }
+
+    public <T> T getService(Class<T> serviceInterface)
+    {
+        return _registry.getService(serviceInterface, _module);
+    }
+
+    public <T> T getObject(String reference, Class<T> objectType)
+    {
+        return _registry.getObject(reference, objectType, this);
+    }
+
+    protected InternalRegistry getRegistry()
+    {
+        return _registry;
+    }
+
+    protected Module getModule()
+    {
+        return _module;
+    }
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java Sat Aug 12 11:24:17 2006
@@ -19,27 +19,21 @@
 import java.util.Map;
 
 import org.apache.commons.logging.Log;
-import org.apache.tapestry.ioc.ServiceCreatorResources;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
 import org.apache.tapestry.ioc.def.ServiceDef;
 
-import static org.apache.tapestry.ioc.IOCUtilities.toQualifiedId;
-
 /**
- * Implementation of {@link org.apache.tapestry.ioc.ServiceCreatorResources}. We just have one
+ * 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.ServiceCreatorResources} (which is
+ * 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.
  * 
  * @author Howard M. Lewis Ship
  */
-public class ServiceResourcesImpl implements ServiceCreatorResources
+public class ServiceResourcesImpl extends ServiceLocatorImpl implements ServiceBuilderResources
 {
-    private final InternalRegistry _registry;
-
-    private final Module _module;
-
     private final ServiceDef _serviceDef;
 
     private Log _log;
@@ -47,8 +41,7 @@
     public ServiceResourcesImpl(InternalRegistry registry, Module module, ServiceDef serviceDef,
             Log log)
     {
-        _registry = registry;
-        _module = module;
+        super(registry, module);
         _serviceDef = serviceDef;
         _log = log;
     }
@@ -63,19 +56,6 @@
         return _serviceDef.getServiceInterface();
     }
 
-    public <T> T getService(String serviceId, Class<T> serviceInterface)
-    {
-        return _registry.getService(
-                toQualifiedId(_module.getModuleId(), serviceId),
-                serviceInterface,
-                _module);
-    }
-
-    public <T> T getService(Class<T> serviceInterface)
-    {
-        return _registry.getService(serviceInterface, _module);
-    }
-
     public Log getServiceLog()
     {
         return _log;
@@ -83,22 +63,22 @@
 
     public <T> Collection<T> getUnorderedConfiguration(Class<T> valueType)
     {
-        return _registry.getUnorderedConfiguration(_serviceDef, valueType);
+        return getRegistry().getUnorderedConfiguration(_serviceDef, valueType);
     }
 
     public <T> List<T> getOrderedConfiguration(Class<T> valueType)
     {
-        return _registry.getOrderedConfiguration(_serviceDef, valueType);
+        return getRegistry().getOrderedConfiguration(_serviceDef, valueType);
     }
 
     public <K, V> Map<K, V> getMappedConfiguration(Class<K> keyType, Class<V> valueType)
     {
-        return _registry.getMappedConfiguration(_serviceDef, keyType, valueType);
+        return getRegistry().getMappedConfiguration(_serviceDef, keyType, valueType);
     }
 
-    public <T> T getObject(String reference, Class<T> objectType)
+    public Object getModuleBuilder()
     {
-        return _registry.getObject(reference, objectType, this);
+        return getModule().getModuleBuilder();
     }
 
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java Sat Aug 12 11:24:17 2006
@@ -14,20 +14,20 @@
 
 package org.apache.tapestry.internal.ioc;
 
-import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ObjectCreator;
 import org.apache.tapestry.ioc.ServiceLifecycle;
 import org.apache.tapestry.ioc.ServiceResources;
 
 /**
  * The basic implementation of a service lifecycle, which simply uses the
- * {@link org.apache.tapestry.ioc.ServiceCreator} to create an instance of the service when asked.
+ * {@link org.apache.tapestry.ioc.ObjectCreator} to create an instance of the service when asked.
  * 
  * @author Howard M. Lewis Ship
  */
 public class SingletonServiceLifecycle implements ServiceLifecycle
 {
-    public Object createService(ServiceResources resources, ServiceCreator creator)
+    public Object createService(ServiceResources resources, ObjectCreator creator)
     {
-        return creator.createService();
+        return creator.createObject();
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceCreator.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceCreator.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceCreator.java Sat Aug 12 11:24:17 2006
@@ -17,7 +17,7 @@
  */
 package org.apache.tapestry.internal.ioc.services;
 
-import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ObjectCreator;
 import org.apache.tapestry.ioc.services.ThreadCleanupHub;
 import org.apache.tapestry.ioc.services.ThreadCleanupListener;
 
@@ -27,13 +27,13 @@
  * @author Howard M. Lewis Ship
  */
 public class PerThreadServiceCreator extends ThreadLocal implements ThreadCleanupListener,
-        ServiceCreator
+        ObjectCreator
 {
     private final ThreadCleanupHub _threadCleanupHub;
 
-    private final ServiceCreator _delegate;
+    private final ObjectCreator _delegate;
 
-    public PerThreadServiceCreator(ThreadCleanupHub threadCleanupHub, ServiceCreator delegate)
+    public PerThreadServiceCreator(ThreadCleanupHub threadCleanupHub, ObjectCreator delegate)
     {
         _threadCleanupHub = threadCleanupHub;
         _delegate = delegate;
@@ -47,10 +47,10 @@
 
         _threadCleanupHub.addThreadCleanupListener(this);
 
-        return _delegate.createService();
+        return _delegate.createObject();
     }
 
-    public Object createService()
+    public Object createObject()
     {
         // Get (or create) the service.
         return get();

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceLifecycle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceLifecycle.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceLifecycle.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceLifecycle.java Sat Aug 12 11:24:17 2006
@@ -18,7 +18,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Modifier;
 
-import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ObjectCreator;
 import org.apache.tapestry.ioc.ServiceLifecycle;
 import org.apache.tapestry.ioc.ServiceResources;
 import org.apache.tapestry.ioc.services.ClassFab;
@@ -30,7 +30,7 @@
 
 /**
  * Allows a service to exist "per thread" (in each thread). This involves an inner proxy, with a
- * ThreadLocal whose initial value is derived from a {@link org.apache.tapestry.ioc.ServiceCreator}.
+ * ThreadLocal whose initial value is derived from a {@link org.apache.tapestry.ioc.ObjectCreator}.
  * Method invocations are delegated to the per-thread service instance. The proxy also implements
  * {@link org.apache.tapestry.ioc.services.ThreadCleanupListener} so that it can discard the
  * per-thread implementation.
@@ -55,11 +55,11 @@
         _classFactory = classFactory;
     }
 
-    public Object createService(ServiceResources resources, final ServiceCreator creator)
+    public Object createService(ServiceResources resources, final ObjectCreator creator)
     {
         Class proxyClass = createProxyClass(resources);
 
-        ServiceCreator perThreadCreator = new PerThreadServiceCreator(_threadCleanupHub, creator);
+        ObjectCreator perThreadCreator = new PerThreadServiceCreator(_threadCleanupHub, creator);
 
         try
         {
@@ -83,14 +83,14 @@
 
         ClassFab cf = _classFactory.newClass(serviceInterface);
 
-        cf.addField("_creator", ServiceCreator.class);
+        cf.addField("_creator", ObjectCreator.class);
 
         // Constructor takes a ServiceCreator
 
         cf.addConstructor(new Class[]
-        { ServiceCreator.class }, null, "_creator = $1;");
+        { ObjectCreator.class }, null, "_creator = $1;");
 
-        String body = format("return (%s) _creator.createService();", serviceInterface.getName());
+        String body = format("return (%s) _creator.createObject();", serviceInterface.getName());
 
         MethodSignature sig = new MethodSignature(serviceInterface, PER_THREAD_METHOD_NAME, null,
                 null);

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImpl.java Sat Aug 12 11:24:17 2006
@@ -142,5 +142,4 @@
             fireInvalidationEvent();
         }
     }
-
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/PageLoaderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/PageLoaderImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/PageLoaderImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/PageLoaderImpl.java Sat Aug 12 11:24:17 2006
@@ -14,19 +14,24 @@
 
 package org.apache.tapestry.internal.pageload;
 
-import static org.apache.tapestry.util.CollectionFactory.newList;
-
 import java.util.List;
 import java.util.Locale;
 
+import org.apache.tapestry.internal.parser.AttributeToken;
+import org.apache.tapestry.internal.parser.ComponentTemplate;
+import org.apache.tapestry.internal.parser.StartComponentToken;
+import org.apache.tapestry.internal.parser.TemplateToken;
 import org.apache.tapestry.internal.structure.ComponentPageElement;
 import org.apache.tapestry.internal.structure.ComponentPageElementImpl;
+import org.apache.tapestry.internal.structure.MarkupPageElement;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.internal.structure.PageElement;
 import org.apache.tapestry.internal.structure.PageImpl;
 import org.apache.tapestry.internal.transform.ComponentInstantiatorSource;
 import org.apache.tapestry.internal.transform.Instantiator;
 
+import static org.apache.tapestry.util.CollectionFactory.newList;
+
 /**
  * This implementation is not threadsafe.
  * 
@@ -34,12 +39,21 @@
  */
 public class PageLoaderImpl implements PageLoader
 {
-    private ComponentInstantiatorSource _componentInstantiatorSource;
+    private final ComponentInstantiatorSource _componentInstantiatorSource;
+
+    private final ComponentTemplateSource _templateSource;
 
     private Page _page;
 
     private Locale _locale;
 
+    public PageLoaderImpl(ComponentInstantiatorSource componentInstantiatorSource,
+            ComponentTemplateSource templateSource)
+    {
+        _componentInstantiatorSource = componentInstantiatorSource;
+        _templateSource = templateSource;
+    }
+
     /**
      * Stack of elements within the current template, used to determine on which object to invoke
      * {@link ComponentPageElement#addToBody(PageElement)}. Each new element (component or
@@ -87,29 +101,179 @@
     /** Works the component queue, until exausted. */
     private void workComponentQueue()
     {
+        while (!_componentQueue.isEmpty())
+        {
+            ComponentPageElement componentElement = pop(_componentQueue);
 
+            loadTemplateForComponent(componentElement);
+        }
     }
 
-    /** For injection. */
-    public void setComponentInstantiatorSource(ComponentInstantiatorSource source)
+    private void loadTemplateForComponent(ComponentPageElement loadingComponent)
     {
-        _componentInstantiatorSource = source;
+        // Have to do something here, like consult the ComponentModelSource and get a
+        // ComponentModel to guide the process. Lots of moving parts.
+
+        ComponentTemplate template = _templateSource.getTemplate("", _locale);
+
+        // Here's the thing. Stuff in this template is part of element's template unless
+        // it is inside another component, in which case, it is part of the component's
+        // body. template is stuff from the component's own template (if any). body
+        // is stuff from its container's template.
+
+        PageElement activePageElement = loadingComponent;
+        ComponentPageElement activeComponent = loadingComponent;
+        List<PageElement> activePageElementStack = newList();
+        List<ComponentPageElement> activeComponentStack = newList();
+
+        boolean directlyInsideSubcomponent = false;
+
+        for (TemplateToken token : template.getTokens())
+        {
+            switch (token.getTokenType())
+            {
+                case CDATA:
+                case TEXT:
+
+                    add(loadingComponent, activeComponent, new MarkupPageElement(token));
+                    break;
+
+                case START_ELEMENT:
+
+                    // We push onto *both* stacks when starting an element or when
+                    // starting a component, because we can't differentitate cases
+                    // when we hit the end element token.
+
+                    PageElement newElement = new MarkupPageElement(token);
+
+                    add(loadingComponent, activeComponent, newElement);
+
+                    push(activePageElementStack, activePageElement);
+                    push(activeComponentStack, activeComponent);
+
+                    activePageElement = newElement;
+
+                    // Any additional attribute tokens should be directed to
+                    // the activePageElement, and not be directed to
+                    // the the activeComponent.
+
+                    directlyInsideSubcomponent = false;
+
+                    break;
+
+                case END_ELEMENT:
+
+                    add(loadingComponent, activeComponent, new MarkupPageElement(token));
+
+                    activePageElement = pop(activePageElementStack);
+                    activeComponent = pop(activeComponentStack);
+
+                    break;
+
+                case START_COMPONENT:
+
+                    StartComponentToken start = (StartComponentToken) token;
+
+                    // For the moment, we're assuming each component will have an id and a FQCN for
+                    // the type. This will change pretty soon.
+
+                    String id = start.getId();
+
+                    // Determining the component name is really not this easy. We may only specify
+                    // the id in the template, and rely on the component model to provide us with
+                    // the type. And the type in the template may be a local abbreviation that must
+                    // be properly expanded to a FQCN before being passed to the
+                    // component instantiator source.
+
+                    String componentName = start.getType();
+
+                    Instantiator instantiator = _componentInstantiatorSource
+                            .findInstantiator(componentName);
+
+                    // The container for any components is the loading component, regardless of
+                    // how the component elements are nested within the loading component's
+                    // template.
+
+                    ComponentPageElement newComponent = new ComponentPageElementImpl(_page,
+                            loadingComponent, id, instantiator);
+
+                    // Make sure container knows about the new component.
+
+                    loadingComponent.addChild(newComponent);
+
+                    // Remember that we have to load this new component and any of its
+                    // subcomponents, later.
+
+                    push(_componentQueue, newComponent);
+
+                    push(activePageElementStack, activePageElement);
+                    push(activeComponentStack, activeComponent);
+
+                    activePageElement = newComponent;
+                    activeComponent = newComponent;
+
+                    // If we see any attribute tokens immediately following the start
+                    // of a component, they are parameters of the component.
+                    // Remember that attribute token can only directly follow
+                    // start component or start element tokens -- due to the structure of
+                    // XML and SAX, they just can't show up elsewhere.
+
+                    directlyInsideSubcomponent = true;
+
+                    break;
+
+                case ATTRIBUTE:
+
+                    if (directlyInsideSubcomponent)
+                    {
+                        AttributeToken attribute = (AttributeToken) token;
+                        activeComponent.addParameter(attribute);
+                    }
+                    else
+                    {
+                        add(loadingComponent, activeComponent, new MarkupPageElement(token));
+                    }
+
+                default:
+                    throw new IllegalStateException("Just haven't written that stuff yet.");
+            }
+
+        }
+
     }
 
+    private void add(ComponentPageElement loadingComponent, ComponentPageElement activeComponent,
+            PageElement child)
+    {
+        if (loadingComponent == activeComponent)
+            activeComponent.addToTemplate(child);
+        else
+            activeComponent.addToBody(child);
+    }
+
+    /** Peeks at the top element on the stack without changing the stack. */
     static <T> T peek(List<T> stack)
     {
         int size = stack.size();
 
+        if (size == 0)
+            throw new IllegalStateException("Stack is empty.");
+
         return stack.get(size - 1);
     }
 
-    static <T> void pop(List<T> stack)
+    /** Pops the top element off the stack and returns it. */
+    static <T> T pop(List<T> stack)
     {
         int size = stack.size();
 
-        stack.remove(size - 1);
+        if (size == 0)
+            throw new IllegalStateException("Stack is empty.");
+
+        return stack.remove(size - 1);
     }
 
+    /** Pushes a new element onto the top of the stack. */
     static <T> void push(List<T> stack, T element)
     {
         stack.add(element);

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java Sat Aug 12 11:24:17 2006
@@ -15,6 +15,7 @@
 package org.apache.tapestry.internal.structure;
 
 import org.apache.tapestry.internal.InternalComponentResources;
+import org.apache.tapestry.internal.parser.AttributeToken;
 
 /**
  * Extended version of {@link org.apache.tapestry.internal.structure.PageElement} for elements that
@@ -40,8 +41,19 @@
     void addToTemplate(PageElement element);
 
     /**
-     * 
+     * Used during the construction of the page. Adds a page element as part of the body of the
+     * component. The body of a component is defined as the portion of the container's template
+     * directly enclosed by component's start and end elements.
      */
     void addToBody(PageElement element);
 
+    /**
+     * Used during construction of the page to identify a parameter of the component that is bound
+     * via a template attribute. An error is logged if there is a conflict, or if the attribute
+     * doesn't correspond to a parameter of the component.
+     */
+    void addParameter(AttributeToken attribute);
+
+    /** Adds a child component to its container. The child's id must be unique within the container. */
+    void addChild(ComponentPageElement child);
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java Sat Aug 12 11:24:17 2006
@@ -15,10 +15,14 @@
 package org.apache.tapestry.internal.structure;
 
 import java.util.List;
+import java.util.Map;
 
+import org.apache.tapestry.internal.parser.AttributeToken;
 import org.apache.tapestry.internal.transform.Instantiator;
 import org.apache.tapestry.runtime.ComponentLifecycle;
-import org.apache.tapestry.util.CollectionFactory;
+
+import static org.apache.tapestry.util.CollectionFactory.newList;
+import static org.apache.tapestry.util.CollectionFactory.newMap;
 
 /**
  * Implements {@link org.apache.tapestry.internal.structure.PageElement} and
@@ -32,20 +36,31 @@
 {
     private final Page _page;
 
+    private final String _id;
+
     private List<PageElement> _template;
 
     private List<PageElement> _body;
 
     private final ComponentPageElement _container;
 
+    // The user-provided class, with runtime code enhancements.
     private final ComponentLifecycle _component;
 
+    private Map<String, ComponentPageElement> _children;
+
+    // This is likely to change shortly to something more involved; we need to introduce the concept
+    // of parameters as well as a component model for the component.
+
+    private final Map<String, AttributeToken> _parameters = newMap();
+
     /** Constructor for the root component of a page. */
     public ComponentPageElementImpl(Page page, Instantiator instantiator)
     {
         _page = page;
         _container = null;
         _component = instantiator.newInstance(this);
+        _id = null;
     }
 
     /**
@@ -53,11 +68,12 @@
      * the hierarchy.
      */
 
-    public ComponentPageElementImpl(Page page, ComponentPageElement container,
+    public ComponentPageElementImpl(Page page, ComponentPageElement container, String id,
             Instantiator instantiator)
     {
         _page = page;
         _container = container;
+        _id = id;
         _component = instantiator.newInstance(this);
     }
 
@@ -69,7 +85,7 @@
     public void addToBody(PageElement element)
     {
         if (_body == null)
-            _body = CollectionFactory.newList();
+            _body = newList();
 
         _body.add(element);
     }
@@ -77,9 +93,33 @@
     public void addToTemplate(PageElement element)
     {
         if (_template == null)
-            _template = CollectionFactory.newList();
+            _template = newList();
 
         _template.add(element);
+    }
+
+    public void addParameter(AttributeToken attribute)
+    {
+        // TODO: Check for conflicts, etc.
+
+        _parameters.put(attribute.getName(), attribute);
+    }
+
+    public void addChild(ComponentPageElement child)
+    {
+        if (_children == null)
+            _children = newMap();
+
+        String childId = child.getId();
+
+        // TODO: Check for conflicts!
+
+        _children.put(childId, child);
+    }
+
+    public String getId()
+    {
+        return _id;
     }
 
 }

Copied: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectCreator.java (from r428940, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectCreator.java?p2=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectCreator.java&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java&r1=428940&r2=431064&rev=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectCreator.java Sat Aug 12 11:24:17 2006
@@ -15,14 +15,13 @@
 package org.apache.tapestry.ioc;
 
 /**
- * Interface used to encapsulate any strategy used to obtain a service implementation (the real
- * service implementation, not a proxy) on demand.
+ * Interface used to encapsulate any strategy used defer the creation of some object until just as
+ * needed.
  * 
  * @author Howard M. Lewis Ship
- * @see org.apache.tapestry.internal.ioc.SingletonServiceLifecycle
  */
-public interface ServiceCreator
+public interface ObjectCreator
 {
-    /** Create and return the service implementation. */
-    Object createService();
+    /** Create and return the object. */
+    Object createObject();
 }

Copied: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceBuilderResources.java (from r428940, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceBuilderResources.java?p2=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceBuilderResources.java&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java&r1=428940&r2=431064&rev=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceBuilderResources.java Sat Aug 12 11:24:17 2006
@@ -24,8 +24,13 @@
  * 
  * @author Howard M. Lewis Ship
  */
-public interface ServiceCreatorResources extends ServiceResources
+public interface ServiceBuilderResources extends ServiceResources
 {
+    /**
+     * Returns the module builder instance for the module containing the service to be created.
+     */
+    Object getModuleBuilder();
+
     <T> Collection<T> getUnorderedConfiguration(Class<T> valueType);
 
     <T> List<T> getOrderedConfiguration(Class<T> valueType);

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java Sat Aug 12 11:24:17 2006
@@ -34,5 +34,5 @@
      *            around the service's builder method.
      * @return the service or equivalent service proxy
      */
-    Object createService(ServiceResources resources, ServiceCreator creator);
+    Object createService(ServiceResources resources, ObjectCreator creator);
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java Sat Aug 12 11:24:17 2006
@@ -14,8 +14,8 @@
 
 package org.apache.tapestry.ioc.def;
 
-import org.apache.tapestry.ioc.ServiceCreator;
-import org.apache.tapestry.ioc.ServiceCreatorResources;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
 
 /**
  * Service definition derived, by default, from a service builder method.
@@ -25,15 +25,13 @@
 public interface ServiceDef
 {
     /**
-     * Returns a {@link ServiceCreator} that can create the core service implementation.
-     * 
-     * @param moduleBuilder
-     *            the module builder instance for the module containing the service
+     * Returns an {@link ObjectCreator} that can create the core service implementation.
      * @param resources
      *            used to resolve dependencies of the service, or access its configuration
+     * 
      * @return an object that can (later) be used to instantiate the service itself
      */
-    ServiceCreator createServiceCreator(Object moduleBuilder, ServiceCreatorResources resources);
+    ObjectCreator createServiceCreator(ServiceBuilderResources resources);
 
     /** Returns the fully qualified service id, derived from the method name. */
     String getServiceId();

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java Sat Aug 12 11:24:17 2006
@@ -39,14 +39,21 @@
 @Id("tapestry.ioc")
 public final class TapestryIOCModule
 {
+    private final ClassFactory _classFactory;
+
+    public TapestryIOCModule(@InjectService("ClassFactory")
+    ClassFactory classFactory)
+    {
+        _classFactory = classFactory;
+    }
+
     /**
      * The LoggingDecorator service is used to decorate a service implementation so that it logs
      * method entry and exit (at level debug).
      */
-    public LoggingDecorator buildLoggingDecorator(@InjectService("ClassFactory")
-    ClassFactory classFactory)
+    public LoggingDecorator buildLoggingDecorator()
     {
-        return new LoggingDecoratorImpl(classFactory);
+        return new LoggingDecoratorImpl(_classFactory);
     }
 
     /**
@@ -70,22 +77,19 @@
     public void contributeServiceLifecycleSource(
             MappedConfiguration<String, ServiceLifecycle> configuration,
             @InjectService("ThreadCleanupHub")
-            ThreadCleanupHub threadCleanupHub, @InjectService("ClassFactory")
-            ClassFactory classFactory)
+            ThreadCleanupHub threadCleanupHub)
     {
-        configuration.add(
-                "perthread",
-                new PerThreadServiceLifecycle(threadCleanupHub, classFactory));
+        configuration.add("perthread", new PerThreadServiceLifecycle(threadCleanupHub,
+                _classFactory));
     }
 
     /**
      * 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(@InjectService("ClassFactory")
-    ClassFactory classFactory)
+    public ChainBuilder buildChainBuilder()
     {
-        return new ChainBuilderImpl(classFactory);
+        return new ChainBuilderImpl(_classFactory);
     }
 
     /**
@@ -100,31 +104,27 @@
     /**
      * Builder that creates a shadow, a projection of a property of some other object.
      */
-    public PropertyShadowBuilder buildPropertyShadowBuilder(@InjectService("ClassFactory")
-    ClassFactory classFactory, @InjectService("PropertyAccess")
+    public PropertyShadowBuilder buildPropertyShadowBuilder(@InjectService("PropertyAccess")
     PropertyAccess propertyAccess)
     {
-        return new PropertyShadowBuilderImpl(classFactory, propertyAccess);
+        return new PropertyShadowBuilderImpl(_classFactory, propertyAccess);
     }
 
     /**
      * Builder that creates a filter pipeline around a simple service interface.
      */
-    public PipelineBuilder buildPipelineBuilder(@InjectService("ClassFactory")
-    ClassFactory classFactory, @InjectService("DefaultImplementationBuilder")
+    public PipelineBuilder buildPipelineBuilder(@InjectService("DefaultImplementationBuilder")
     DefaultImplementationBuilder builder)
     {
-        return new PipelineBuilderImpl(classFactory, builder);
+        return new PipelineBuilderImpl(_classFactory, builder);
     }
 
     /**
      * Builder that creates a default implementation of an interface.
      */
-    public DefaultImplementationBuilder buildDefaultImplementationBuilder(
-            @InjectService("ClassFactory")
-            ClassFactory classFactory)
+    public DefaultImplementationBuilder buildDefaultImplementationBuilder()
     {
-        return new DefaultImplementationBuilderImpl(classFactory);
+        return new DefaultImplementationBuilderImpl(_classFactory);
     }
 
     /**

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ComponentNameExpander.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ComponentNameExpander.java?rev=431064&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ComponentNameExpander.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ComponentNameExpander.java Sat Aug 12 11:24:17 2006
@@ -0,0 +1,27 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.services;
+
+/**
+ * Invoked by the page loader to convert a component name into a fully qualified component class
+ * name.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public interface ComponentNameExpander
+{
+    /** Expands the component name into a fully qualified class name. */
+    String expandComponentName(String componentName);
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java Sat Aug 12 11:24:17 2006
@@ -20,6 +20,7 @@
 import org.apache.tapestry.internal.InternalModule;
 import org.apache.tapestry.internal.services.InfrastructureImpl;
 import org.apache.tapestry.internal.services.InfrastructureManagerImpl;
+import org.apache.tapestry.ioc.Configuration;
 import org.apache.tapestry.ioc.MappedConfiguration;
 import org.apache.tapestry.ioc.ObjectProvider;
 import org.apache.tapestry.ioc.annotations.Contribute;
@@ -57,5 +58,30 @@
             Infrastructure infrastructure)
     {
         configuration.add("service", infrastructure.getObjectProvider());
+    }
+
+    public void contributeInfrastructure(Configuration<InfrastructureContribution> configuration,
+            @InjectService("ComponentNameExpander")
+            ComponentNameExpander componentNameExpander)
+    {
+        configuration.add(new InfrastructureContribution("componentNameExpander",
+                componentNameExpander));
+    }
+
+    /**
+     * Builds a provisional implementation that assumes the input name already is a fully qualified
+     * class name.
+     */
+    public ComponentNameExpander buildComponentNameExpander()
+    {
+        return new ComponentNameExpander()
+        {
+
+            public String expandComponentName(String componentName)
+            {
+                return componentName;
+            }
+
+        };
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java Sat Aug 12 11:24:17 2006
@@ -34,8 +34,8 @@
 import org.apache.tapestry.ioc.LogSource;
 import org.apache.tapestry.ioc.MappedConfiguration;
 import org.apache.tapestry.ioc.OrderedConfiguration;
-import org.apache.tapestry.ioc.ServiceCreator;
-import org.apache.tapestry.ioc.ServiceCreatorResources;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
 import org.apache.tapestry.ioc.ServiceDecorator;
 import org.apache.tapestry.ioc.ServiceLocator;
 import org.apache.tapestry.ioc.ServiceResources;
@@ -202,15 +202,15 @@
         setReturnValue(service);
     }
 
-    protected final void trainCreateService(ServiceCreator creator, Object service)
+    protected final void trainCreateService(ObjectCreator creator, Object service)
     {
-        creator.createService();
+        creator.createObject();
         setReturnValue(service);
     }
 
-    protected final ServiceCreator newServiceCreator()
+    protected final ObjectCreator newServiceCreator()
     {
-        return newMock(ServiceCreator.class);
+        return newMock(ObjectCreator.class);
     }
 
     protected final void trainGetServiceInterface(ServiceResources resources, Class serviceInterface)
@@ -289,9 +289,9 @@
         return newMock(ContributionDef.class);
     }
 
-    protected final ServiceCreatorResources newServiceCreatorResources()
+    protected final ServiceBuilderResources newServiceCreatorResources()
     {
-        return newMock(ServiceCreatorResources.class);
+        return newMock(ServiceBuilderResources.class);
     }
 
     protected final Module newModule()

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties Sat Aug 12 11:24:17 2006
@@ -66,4 +66,10 @@
   existing contribution (by %s) and has been ignored.
 generic-type-not-supported=Generic type '%s' is not supported. Only simple parameterized lists are \
   supported.
-error-building-service=Error building service proxy for service '%s' (at %s): %s
\ No newline at end of file
+error-building-service=Error building service proxy for service '%s' (at %s): %s
+no-public-constructors=Module builder for module '%s' (class %s) does not contain any public constructors.
+too-many-public-constructors=Module bulider for module '%s' (class %s) contains more than one public constructor. \
+  The first constructor, %s, is being used. \
+  You should change the class to have only a single public constructor.
+recursive-module-constructor=The constructor for module '%s' (class %s) is recursive: it depends on itself in some way. \
+  The constructor, %s, is in some way is triggering a service builder, decorator or contribution method within the class.
\ No newline at end of file

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt Sat Aug 12 11:24:17 2006
@@ -69,6 +69,68 @@
   errors will occur.
   
   
+{Caching Services}
+
+  You will often find yourself in the position of injecting the same services
+  into your service builder or service decorator methods repeatedly. This can be quite
+  a bit of redundant typing.  Less code is better code, so as an alternative, you may define a <constructor> for your
+  module that accepts annotated parameters (as with 
+  {{{service.html#Injecting Dependencies}service builder injection}}).
+  
+  This gives you a chance to store common services in instance variables for later use inside 
+  service builder methods.
+  
++-----------------------------------------------------------------------------------+
+
+public class MyModule
+{   
+  private final JobScheduler _scheduler;
+  private final FileSystem _fileSystem;
+  
+  public MyModule(
+    @Inject("service:JobScheduler")
+    JobScheduler scheduler, 
+    @Inject("service:FileSystem")
+    FileSystem fileSystem)
+  {
+    _scheduler = scheduler;
+    _fileSystem = fileSystem;
+  }
+  
+  public Indexer buildIndexer()
+  {
+    IndexerImpl indexer = new IndexerImpl(_fileSystem);
+      
+    _scheduler.scheduleDailyJob(indexer);
+      
+    return indexer;
+  }
+}
++-----------------------------------------------------------------------------------+
+
+  In addition to injecting dependencies with the @InjectService and @Inject annotations,
+  you may also inject a number of <module> resources:
+  
+  * java.lang.String: the module id
+    
+  * org.apache.commons.logging.Log: log for the module
+   
+  * {{{../apidocs/org/apache/tapestry/ioc/ServiceLocator.html}ServiceLocator}}:  access to other services
+  
+  []
+  
+  Care should be taken with this approach: in some circustances, you may force a situtation in which
+  the module constructor is dependent on itself. For example, if you invoke a method on any injected services
+  defined within the same module from the module builder's constructor,
+  then the service implementation will be needed. Creating service implementations
+  requires the module builder instance ... that's a recursive reference.
+  
+  Another common example would be using @Inject("infrastructure:<property>") when the module being constructed
+  contributes into the tapestry.Infrastructure service's configuration. Here, to resolve the contribution, Tapestry
+  needs an instance of the module builder class even as it is trying to invoke the module builder's constructor.
+  
+  Tapestry detects these scenarios and throws a runtime exception to prevent an endless loop.
+    
 Autoloading modules
 
   When setting up the registry, Tapestry can automatically locate modules packaged into JARs.
@@ -85,7 +147,7 @@
 Tapestry-Module-Classes: org.example.mylib.LibModule, org.example.mylib.internal.InternalModule
 +-----------------------------------------------------------------------------------+
 
-  If you are using Maven 2, then  getting these entries into your JAR's manifest
+  If you are using Maven 2, then getting these entries into your JAR's manifest
   is as simple as some configuration in your pom.xml:
   
 +-----------------------------------------------------------------------------------+
@@ -140,17 +202,13 @@
   . . .
 +----+
 
+  In general, your should only need to identify a single module in the JAR manifest, and make use of
+  @SubModule to pull in any additional module builder classes.
+
 Module Builder Implementation Notes
 
   Module builder classes are designed to be very, very simple to implement.
-  
-  They must have a no-arguments public constructor.
-  
-  You should <<not>> attempt to cache services. There is really no way to
-  determine in what order methods of the builder class will be invoked. Because
-  services are generally instantiated only as needed, methods will be
-  invoked in an arbitrary order, and some may never be invoked.
-  
+    
   Again, keep the methods very simple. Use {{{service.html#Injecting Dependencies}parameter injection}}
   to gain access to the dependencies you need.
   

Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/provider.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/provider.apt?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/provider.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/provider.apt Sat Aug 12 11:24:17 2006
@@ -26,6 +26,42 @@
   As outlined above, the service provider interprets the expression as
   a service id, either fully qualified or local.
   
+* infrastructure provider
+
+  The infrastructure provider is a key element in making Tapestry extensible; it adds a layer of
+  indirection between service implementations and their collaborators. Using the infrastructure
+  provider allows applications to identify and override individual services within Tapestry's
+  network of services. 
+  
+  The <expression> for the infrastructure provider is the name of a property. This property is
+  mapped to a particular service via a <pair> of services. The
+  {{{../apidocs/org/apache/tapestry/services/Infrastructure.html}tapestry.Infrastructure}} service
+  has a mapped configuration of 
+  {{{../apidocs/org/apache/tapestry/services/InfrastructureContribution.html}InfrastructureContribution}}s.
+  Each contribution is keyed on the property it provides.
+  
+  A second service (<<Caution:>> not yet implemented), tapestry.InfrastructureOverride, exists
+  to support a second, identical configuration. Any properties contributed here override the normal
+  Infrastructure properties.
+  
+  In order to override an individual Tapestry service, all that is necessary is to provide
+  a new implementation as a new service, and contribute that service into the configuration for
+  the tapestry.InfrastructureOverride configuration.
+  
+  In many cases, the original service can be injected into the new implementation; this must be done
+  using the original service's fully qualified service id.
+  
+  The following table identifies the properties that are available via the infrastructure provider
+  by default:
+  
+*---------------------+-----------------------------------------------------------------------------------------+
+| <<Property>>        | <<Default Service or Implementation>>                                                   |
+*---------------------+-----------------------------------------------------------------------------------------+
+| xyz                 | {{{../apidocs/org/apache/tapestry/ioc/services/ClassFactory.html}ClassFactory}}         |
+*---------------------+-----------------------------------------------------------------------------------------+
+Default properties available via the infrastructure object provider
+  
+  
 Defining New Providers
 
   New providers can be specified by contributing to the