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/07/06 17:25:47 UTC

svn commit: r419581 [1/2] - in /tapestry/tapestry5/tapestry-core/trunk/src: main/java/org/apache/tapestry/internal/ioc/ main/java/org/apache/tapestry/internal/test/ main/java/org/apache/tapestry/ioc/ main/java/org/apache/tapestry/ioc/annotations/ main/...

Author: hlship
Date: Thu Jul  6 08:25:45 2006
New Revision: 419581

URL: http://svn.apache.org/viewvc?rev=419581&view=rev
Log:
Flesh out more of the new IoC container.

Added:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/BasicServiceCreator.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImpl.java
      - copied, changed from r418781, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleGrinder.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InternalRegistry.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/RegistryImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceCreator.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/test/
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/IOCConstants.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/Registry.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.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/annotations/Lifecycle.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ModuleDef.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java
      - copied, changed from r418781, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDef.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/BasicServiceCreatorTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImplTest.java
      - copied, changed from r418781, tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleGrinderTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ReadManifest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ServiceIdConflictMethodBuilder.java
      - copied, changed from r418781, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceIdConflictMethodBuilder.java
Removed:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleGrinder.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDef.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceIdConflictMethodBuilder.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleGrinderTest.java
Modified:
    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/Module.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/ioc/ServiceResources.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleBuilderWithId.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SimpleModuleBuilder.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/InternalClassTransformationImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/worker/RetainWorkerTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/worker/UnclaimedFieldWorkerTest.java

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/BasicServiceCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/BasicServiceCreator.java?rev=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/BasicServiceCreator.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/BasicServiceCreator.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,112 @@
+// 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 java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+import org.apache.tapestry.ioc.ErrorLog;
+import org.apache.tapestry.ioc.ServiceResources;
+import org.apache.tapestry.ioc.def.ServiceDef;
+
+import static org.apache.tapestry.util.CollectionFactory.newMap;
+
+/**
+ * Basic implementation of {@link org.apache.tapestry.internal.ioc.ServiceCreator} 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 BasicServiceCreator implements ServiceCreator
+{
+    private final Object _moduleBuilder;
+
+    private final ServiceDef _serviceDef;
+
+    private final String _serviceId;
+
+    private final Map<Class, Object> _parameterDefaults = newMap();
+
+    private final ErrorLog _log;
+
+    public BasicServiceCreator(ServiceDef serviceDef, Object moduleBuilder,
+            ServiceResources resources)
+    {
+        _serviceId = serviceDef.getServiceId();
+        _serviceDef = serviceDef;
+        _moduleBuilder = moduleBuilder;
+        _log = resources.getErrorLog();
+
+        _parameterDefaults.put(String.class, _serviceId);
+        _parameterDefaults.put(ServiceResources.class, resources);
+        _parameterDefaults.put(ErrorLog.class, _log);
+        _parameterDefaults.put(Class.class, serviceDef.getServiceInterface());
+    }
+
+    /**
+     * Invoked from the proxy to create the actual service implementation. TODO: Interceptors, etc.
+     */
+    public Object createService()
+    {
+        Method m = _serviceDef.getBuilderMethod();
+
+        Class[] parameterTypes = m.getParameterTypes();
+        Annotation[][] annotations = m.getParameterAnnotations();
+        int parameterCount = parameterTypes.length;
+
+        Object[] parameters = new Object[parameterCount];
+
+        for (int i = 0; i < parameterCount; i++)
+        {
+            parameters[i] = calculateParameterValue(parameterTypes[i], annotations[i]);
+        }
+
+        Object result = null;
+
+        try
+        {
+            result = m.invoke(_moduleBuilder, parameters);
+        }
+        catch (Exception ex)
+        {
+            throw new RuntimeException(IOCMessages.builderMethodError(m, _serviceId, ex), ex);
+        }
+
+        if (result == null)
+            throw new RuntimeException(IOCMessages.builderMethodReturnedNull(m, _serviceId));
+
+        return result;
+    }
+
+    private Object calculateParameterValue(Class parameterType, Annotation[] parameterAnnotations)
+    {
+        // TODO: Injecting services based on an annotation
+
+        // See if we have any "pre-determined" parameter type to object mappings
+
+        Object result = _parameterDefaults.get(parameterType);
+
+        // TODO: Injecting services based on type
+
+        if (result == null)
+            _log.warn(IOCMessages.unknownBuilderParameter(parameterType, _serviceDef
+                    .getBuilderMethod(), _serviceId), null);
+
+        return result;
+    }
+}

Copied: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImpl.java (from r418781, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleGrinder.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImpl.java?p2=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImpl.java&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleGrinder.java&r1=418781&r2=419581&rev=419581&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleGrinder.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImpl.java Thu Jul  6 08:25:45 2006
@@ -23,7 +23,11 @@
 import java.util.Set;
 
 import org.apache.tapestry.ioc.ErrorLog;
+import org.apache.tapestry.ioc.IOCConstants;
 import org.apache.tapestry.ioc.annotations.Id;
+import org.apache.tapestry.ioc.annotations.Lifecycle;
+import org.apache.tapestry.ioc.def.ModuleDef;
+import org.apache.tapestry.ioc.def.ServiceDef;
 
 import static org.apache.tapestry.internal.ioc.IOCMessages.buildMethodConflict;
 import static org.apache.tapestry.internal.ioc.IOCMessages.buildMethodWrongReturnType;
@@ -35,29 +39,29 @@
  * 
  * @author Howard M. Lewis Ship
  */
-public class ModuleGrinder
+public class DefaultModuleDefImpl implements ModuleDef
 {
     /** The prefix used to identify service building methods. */
 
     private static final String BUILD_METHOD_NAME_PREFIX = "build";
 
-    private final Class _moduleBuilder;
+    private final Class _builderClass;
 
     private final ErrorLog _log;
 
-    /** Keyed on unqualified service id. */
+    /** Keyed on fully qualified service id. */
     private final Map<String, ServiceDef> _serviceDefs = newMap();
 
     private final String _moduleId;
 
     /**
-     * @param moduleBuilder
-     *            the class that is responsible for building
+     * @param builderClass
+     *            the class that is responsible for building services, etc.
      * @param log
      */
-    public ModuleGrinder(Class moduleBuilder, ErrorLog log)
+    public DefaultModuleDefImpl(Class builderClass, ErrorLog log)
     {
-        _moduleBuilder = moduleBuilder;
+        _builderClass = builderClass;
         _log = log;
 
         _moduleId = extractModuleId();
@@ -65,35 +69,21 @@
         grind();
     }
 
-    /** Returns the ids of the services built/provided by the module. */
+    public Class getBuilderClass()
+    {
+        return _builderClass;
+    }
+
     public Set<String> getServiceIds()
     {
         return _serviceDefs.keySet();
     }
 
-    /**
-     * Returns a service definition via local (unqualified) service id. May return null (after
-     * logging a warning) if the requested service does not exist.
-     * 
-     * @param serviceId
-     *            unqualified service ids
-     * @return service definition or null
-     */
     public ServiceDef getServiceDef(String serviceId)
     {
-        ServiceDef result = _serviceDefs.get(serviceId);
-
-        if (result == null)
-            _log.warn(IOCMessages.missingService(serviceId, _moduleId), null);
-
-        return result;
+        return _serviceDefs.get(serviceId);
     }
 
-    /**
-     * Returns the module id extracted from the {@link org.apache.tapestry.ioc.annotations.Id}
-     * annotation on the module builder class (or calculated from the module bulder's package, if
-     * the annotation is not present).
-     */
     public String getModuleId()
     {
         return _moduleId;
@@ -101,12 +91,12 @@
 
     private String extractModuleId()
     {
-        Id id = getAnnotation(_moduleBuilder, Id.class);
+        Id id = getAnnotation(_builderClass, Id.class);
 
         if (id != null)
             return id.value();
 
-        String className = _moduleBuilder.getName();
+        String className = _builderClass.getName();
 
         // Don't try to do this with classes in the default package. Then again, you should
         // never put classes in the default package!
@@ -116,25 +106,18 @@
         return className.substring(0, lastdot);
     }
 
+    // This appears useless, but it's really about some kind of ambiguity in Class, which seems
+    // to think getAnnotation() returns Object, not <? extends Annotation>. This may be a bug
+    // in Eclipse's Java compiler.
+
     private <T extends Annotation> T getAnnotation(AnnotatedElement element, Class<T> annotationType)
     {
         return element.getAnnotation(annotationType);
     }
 
-    // private <T extends Annotation> T getRequiredAnnotation(AnnotatedElement element,
-    // Class<T> annotationType)
-    // {
-    // T result = element.getAnnotation(annotationType);
-    //
-    // if (result == null)
-    // _log.fail(IOCMessages.missingAnnotation(annotationType, element), null);
-    //
-    // return result;
-    // }
-
     private void grind()
     {
-        Method[] methods = _moduleBuilder.getMethods();
+        Method[] methods = _builderClass.getMethods();
 
         Comparator<Method> c = new Comparator<Method>()
         {
@@ -169,7 +152,7 @@
     private void addServiceBuildMethod(Method method)
     {
         // TODO: Methods named just "build"
-        String serviceId = method.getName().substring(BUILD_METHOD_NAME_PREFIX.length());
+        String serviceId = _moduleId + "." + method.getName().substring(BUILD_METHOD_NAME_PREFIX.length());
 
         ServiceDef existing = _serviceDefs.get(serviceId);
 
@@ -198,6 +181,15 @@
             return;
         }
 
-        _serviceDefs.put(serviceId, new ServiceDefImpl(serviceId, method));
+        String lifecycle = extractLifecycle(method);
+
+        _serviceDefs.put(serviceId, new ServiceDefImpl(serviceId, lifecycle, method));
+    }
+
+    private String extractLifecycle(Method method)
+    {
+        Lifecycle lifecycle = method.getAnnotation(Lifecycle.class);
+
+        return lifecycle != null ? lifecycle.value() : IOCConstants.DEFAULT_LIFECYCLE;
     }
 }

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=419581&r1=419580&r2=419581&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 Thu Jul  6 08:25:45 2006
@@ -43,8 +43,64 @@
         return MESSAGES.format("build-method-wrong-return-type", method);
     }
 
+    static String noSuchModule(String moduleId)
+    {
+        return MESSAGES.format("no-such-module", moduleId);
+    }
+
     static String missingService(String serviceId, String moduleId)
     {
         return MESSAGES.format("missing-service", serviceId, moduleId);
     }
+
+    public static String builderLocked()
+    {
+        return MESSAGES.getMessage("builder-locked");
+    }
+
+    public static String moduleIdConflict(String id)
+    {
+        return MESSAGES.format("module-id-conflict", id);
+    }
+
+    static String serviceWrongInterface(String serviceId, Class actualInterface,
+            Class requestedInterface)
+    {
+        return MESSAGES.format(
+                "service-wrong-interface",
+                serviceId,
+                actualInterface.getName(),
+                requestedInterface.getName());
+    }
+
+    static String instantiateBuilderError(Class builderClass, String moduleId, Throwable cause)
+    {
+        return MESSAGES
+                .format("instantiate-builder-error", builderClass.getName(), moduleId, cause);
+    }
+
+    static String singletonProxyToString(String serviceId, Class serviceInterface)
+    {
+        return MESSAGES.format("singleton-proxy-to-string", serviceId, serviceInterface.getName());
+    }
+
+    static String builderMethodError(Method m, String serviceId, Throwable cause)
+    {
+        return MESSAGES.format("builder-method-error", m, serviceId, cause);
+    }
+
+    static String unknownBuilderParameter(Class parameterType, Method method, String serviceId)
+    {
+        return MESSAGES.format(
+                "unknown-builder-parameter",
+                parameterType.getName(),
+                method,
+                serviceId);
+    }
+
+    static String builderMethodReturnedNull(Method method, String serviceId)
+    {
+        return MESSAGES.format("builder-method-returned-null", method, serviceId);
+    }
+
 }

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InternalRegistry.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InternalRegistry.java?rev=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InternalRegistry.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InternalRegistry.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,37 @@
+// 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.Registry;
+
+public interface InternalRegistry extends Registry
+{
+    /**
+     * Locates a service given a fully qualified service id and the corresponding service interface
+     * type
+     * 
+     * @param <T>
+     * @param serviceId
+     *            the simple or fully qualified service id
+     * @param serviceInterface
+     *            the interface the service implements
+     * @param module
+     *            the module requesting the service (used for visibility checks)
+     * @return the service's proxy
+     * @throws RuntimeException
+     *             if the service does not exist (this is considered programmer error)
+     */
+    <T> T getService(String serviceId, Class<T> serviceInterface, Module module);
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/Module.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/Module.java?rev=419581&r1=419580&r2=419581&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/Module.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/Module.java Thu Jul  6 08:25:45 2006
@@ -15,13 +15,28 @@
 package org.apache.tapestry.internal.ioc;
 
 /**
- * A module with the Tapestry IoC registry. Each Module is constructed around a corresponding module
- * builder instance; the methods and annotations of that instance define the services provided by
- * the module.
+ * A module within the Tapestry IoC registry. Each Module is constructed around a corresponding
+ * module builder instance; the methods and annotations of that instance define the services
+ * provided by the module.
  * 
  * @author Howard M. Lewis Ship
  */
 public interface Module
 {
-
+    /**
+     * Locates a service given a service id and the corresponding service interface type.
+     * 
+     * @param <T>
+     * @param serviceId
+     *            the fully qualified service id
+     * @param serviceInterface
+     *            the interface the service implements
+     * @param module
+     *            the module requesting the service, or null for no module; this is used for
+     *            performing visibility checks
+     * @return the service's proxy
+     * @throws RuntimeException
+     *             if the service does not exist (this is considered programmer error)
+     */
+    <T> T getService(String serviceId, Class<T> serviceInterface, Module module);
 }

Added: 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=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,107 @@
+// 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 java.util.Map;
+
+import org.apache.tapestry.ioc.def.ModuleDef;
+import org.apache.tapestry.ioc.def.ServiceDef;
+
+import static org.apache.tapestry.util.CollectionFactory.newMap;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public class ModuleImpl implements Module
+{
+    private InternalRegistry _registry;
+
+    private ModuleDef _moduleDef;
+
+    private Object _moduleBuilder;
+
+    /** Keyed on fully qualified service id; values are instantiated services (proxies). */
+    private final Map<String, Object> _services = newMap();
+
+    public <T> T getService(String serviceId, Class<T> serviceInterface, Module module)
+    {
+        ServiceDef def = _moduleDef.getServiceDef(serviceId);
+
+        // No check yet for visibility, so ...
+
+        Object service = findOrCreate(def);
+
+        try
+        {
+            return serviceInterface.cast(service);
+        }
+        catch (ClassCastException ex)
+        {
+            throw new RuntimeException(IOCMessages.serviceWrongInterface(serviceId, def
+                    .getServiceInterface(), serviceInterface));
+        }
+
+    }
+
+    // Why synchronized here? Two reasons. First, with some lifecycle models (or perhaps in some
+    // scenarios using interceptors), we may try to acquire the write lock a second time and the
+    // Synchronized.Write annotation doesn't currently support that. Second, I'm concerned about
+    // multiple threads building services simultaneously, and getting into a thread deadlock. Of
+    // course, this isn't a solution for that ... we may need a global mutex to handle that specific
+    // case!
+
+    private synchronized Object findOrCreate(ServiceDef def)
+    {
+        String key = def.getServiceId();
+
+        Object result = _services.get(key);
+
+        if (result == null)
+        {
+            result = create(def);
+            _services.put(key, result);
+        }
+
+        return result;
+    }
+
+    /** Creates the service and updates the cache of created services. */
+    private Object create(ServiceDef def)
+    {
+        if (_moduleBuilder == null)
+        {
+            Class builderClass = _moduleDef.getBuilderClass();
+
+            try
+            {
+                _moduleBuilder = builderClass.newInstance();
+            }
+            catch (Exception ex)
+            {
+                throw new RuntimeException(IOCMessages.instantiateBuilderError(
+                        builderClass,
+                        _moduleDef.getModuleId(),
+                        ex), ex);
+            }
+        }
+
+        Object service = new Object();
+
+        _services.put(def.getServiceId(), service);
+
+        return service;
+    }
+
+}

Added: 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=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,53 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.ioc;
+
+import java.util.Map;
+
+import org.apache.hivemind.util.IdUtils;
+import org.apache.tapestry.ioc.Registry;
+
+public class RegistryImpl implements Registry, InternalRegistry
+{
+    /** Keyed on module id. */
+    private Map<String, Module> _modules;
+
+    public <T> T getService(String serviceId, Class<T> serviceInterface, Module module)
+    {
+        Module containingModule = localeModuleForService(serviceId);
+
+        return containingModule.getService(serviceId, serviceInterface, module);
+    }
+
+    public <T> T getService(String serviceId, Class<T> serviceInterface)
+    {
+        Module module = localeModuleForService(serviceId);
+
+        return module.getService(serviceId, serviceInterface, null);
+    }
+
+    private Module localeModuleForService(String serviceId)
+    {
+        String moduleId = IdUtils.extractModule(serviceId);
+
+        Module module = _modules.get(moduleId);
+
+        if (module == null)
+            throw new RuntimeException(IOCMessages.noSuchModule(moduleId));
+
+        return module;
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceCreator.java?rev=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceCreator.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceCreator.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,28 @@
+// 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;
+
+/**
+ * Interface used to encapsulate any strategy used to obtain a service implementation (the real
+ * service implementation, not a proxy) on demand.
+ * 
+ * @author Howard M. Lewis Ship
+ * @see org.apache.tapestry.internal.ioc.SingletonServiceLifecycle
+ */
+public interface ServiceCreator
+{
+    /** Create and return the service implementation. */
+    Object createService();
+}

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=419581&r1=419580&r2=419581&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 Thu Jul  6 08:25:45 2006
@@ -16,6 +16,8 @@
 
 import java.lang.reflect.Method;
 
+import org.apache.tapestry.ioc.def.ServiceDef;
+
 /**
  * @author Howard M. Lewis Ship
  */
@@ -25,9 +27,12 @@
 
     private final String _serviceId;
 
-    ServiceDefImpl(String serviceId, Method builderMethod)
+    private final String _lifecycle;
+
+    ServiceDefImpl(String serviceId, String lifecycle, Method builderMethod)
     {
         _serviceId = serviceId;
+        _lifecycle = lifecycle;
         _builderMethod = builderMethod;
     }
 
@@ -44,6 +49,11 @@
     public Class getServiceInterface()
     {
         return _builderMethod.getReturnType();
+    }
+
+    public String getServiceLifeycle()
+    {
+        return _lifecycle;
     }
 
 }

Added: 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=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,136 @@
+// 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 java.lang.reflect.Modifier;
+
+import org.apache.hivemind.service.BodyBuilder;
+import org.apache.hivemind.service.ClassFab;
+import org.apache.hivemind.service.ClassFabUtils;
+import org.apache.hivemind.service.ClassFactory;
+import org.apache.hivemind.service.MethodIterator;
+import org.apache.hivemind.service.MethodSignature;
+import org.apache.tapestry.ioc.IOCConstants;
+import org.apache.tapestry.ioc.ServiceLifecycle;
+import org.apache.tapestry.ioc.ServiceResources;
+import org.apache.tapestry.ioc.def.ServiceDef;
+
+/**
+ * The basic implementation of a service lifecycle, which provides for a proxy that forces the
+ * creation of the real service when a method is invoked on the proxy.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public class SingletonServiceLifecycle implements ServiceLifecycle
+{
+    public Object createService(ServiceDef serviceDef, Object moduleBuilder,
+            ServiceResources resources)
+    {
+        ClassFactory factory = resources.getService(
+                IOCConstants.CLASS_FACTORY_SERVICE_ID,
+                ClassFactory.class);
+
+        Class proxyClass = createProxyClass(serviceDef, factory);
+
+        ServiceCreator creator = new BasicServiceCreator(serviceDef, moduleBuilder, resources);
+
+        try
+        {
+            return proxyClass.getConstructors()[0].newInstance(creator);
+        }
+        catch (Exception ex)
+        {
+            // This should never happen, so we won't go to a lot of trouble
+            // reporting it.
+            throw new RuntimeException(ex.getMessage(), ex);
+        }
+    }
+
+    private Class createProxyClass(ServiceDef serviceDef, ClassFactory factory)
+    {
+        String serviceId = serviceDef.getServiceId();
+        Class serviceInterface = serviceDef.getServiceInterface();
+
+        String name = ClassFabUtils.generateClassName(serviceInterface);
+        ClassFab cf = factory.newClass(name, Object.class);
+
+        addInfrastructure(cf, serviceInterface);
+
+        addDelegateGetter(cf, serviceInterface);
+
+        addServiceMethods(cf, serviceId, serviceInterface);
+
+        return cf.createClass();
+    }
+
+    private void addServiceMethods(ClassFab cf, String serviceId, Class serviceInterface)
+    {
+        MethodIterator mi = new MethodIterator(serviceInterface);
+
+        while (mi.hasNext())
+        {
+            MethodSignature sig = mi.next();
+
+            // Make each method in the proxy delegates to the service implementation (or outermost
+            // interceptor). The "($r)" cast is magic for converting to the return type and
+            // understands void methods. The "$$" is just the list of method arguments.
+
+            String body = "return ($r) _delegate()." + sig.getName() + "($$);";
+
+            cf.addMethod(Modifier.PUBLIC, sig, body);
+        }
+
+        // If toString() is not part of the service interface, then add a toString()
+        // to the class. Objects visible to client code need a toString() to help
+        // with debugging.
+
+        if (!mi.getToString())
+            ClassFabUtils.addToStringMethod(cf, IOCMessages.singletonProxyToString(
+                    serviceId,
+                    serviceInterface));
+    }
+
+    private void addDelegateGetter(ClassFab cf, Class serviceInterface)
+    {
+        BodyBuilder builder = new BodyBuilder();
+        builder.begin();
+        
+        // We can release the creator after invoking it, we only create the service once.
+        
+        builder.addln("if (_delegate == null)");
+        builder.begin();
+        builder.addln("_delegate = ({0}) _creator.createService();", serviceInterface.getName());
+        builder.addln("_creator = null;");
+        builder.end();
+        
+        builder.addln("return _delegate;");
+        builder.end();
+
+        MethodSignature sig = new MethodSignature(serviceInterface, "_delegate", null, null);
+
+        cf.addMethod(Modifier.PRIVATE | Modifier.SYNCHRONIZED, sig, builder.toString());
+    }
+
+    private void addInfrastructure(ClassFab cf, Class serviceInterface)
+    {
+        cf.addInterface(serviceInterface);
+        cf.addField("_delegate", serviceInterface);
+        cf.addField("_creator", ServiceCreator.class);
+
+        cf.addConstructor(new Class[]
+        { ServiceCreator.class }, null, "_creator = $1;");
+    }
+
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java?rev=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,38 @@
+// 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.test;
+
+import org.apache.tapestry.internal.InternalComponentResources;
+import org.apache.tapestry.internal.parser.ComponentTemplate;
+import org.apache.tapestry.test.BaseTestCase;
+
+/**
+ * Contains additional factory and training methods related to internal interfaces.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public class InternalBaseTestCase extends BaseTestCase
+{
+
+    protected final InternalComponentResources newInternalComponentResources()
+    {
+        return newMock(InternalComponentResources.class);
+    }
+
+    protected final ComponentTemplate newComponentTemplate()
+    {
+        return newMock(ComponentTemplate.class);
+    }
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/IOCConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/IOCConstants.java?rev=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/IOCConstants.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/IOCConstants.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,32 @@
+// 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.ioc;
+
+import org.apache.tapestry.internal.annotations.Utility;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+@Utility
+public class IOCConstants
+{
+    public static final String DEFAULT_LIFECYCLE = "singleton";
+
+    /**
+     * Used to obtain the {@link org.apache.hivemind.service.ClassFactory} service, which is crucial
+     * when creating new classes for proxies and the like.
+     */
+    public static final String CLASS_FACTORY_SERVICE_ID = "tapestry.ioc.ClassFactory";
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/Registry.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/Registry.java?rev=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/Registry.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/Registry.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,40 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.ioc;
+
+/**
+ * Public access to the IoC service registry.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public interface Registry
+{
+    /**
+     * Obtains a service via its fully qualified service id. Returns the service's proxy. The
+     * service proxy implements the same interface as the actual service, and is used to instantiate
+     * the actual service only as needed.
+     * 
+     * @param <T>
+     * @param serviceId
+     *            fully qualified service id, used to locate the service object
+     * @param serviceInterface
+     *            the interface implemented by the service (or an interface extended by the service
+     *            interface)
+     * @return the service instance
+     * @throws RuntimeException
+     *             if the service is not defined, or if an error occurs instantitating it
+     */
+    <T> T getService(String serviceId, Class<T> serviceInterface);
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java?rev=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,69 @@
+// 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.ioc;
+
+import java.util.Map;
+
+import org.apache.tapestry.internal.ioc.IOCMessages;
+import org.apache.tapestry.ioc.def.ModuleDef;
+
+import static org.apache.tapestry.util.CollectionFactory.newMap;
+
+/**
+ * Used to construct the IoC {@link org.apache.tapestry.ioc.Registry}. This class is <em>not</em>
+ * threadsafe. The registry, once created, <em>is</em> threadsafe.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public final class RegistryBuilder
+{
+    /** Module defs, keyed on module id. */
+    private final Map<String, ModuleDef> _modules = newMap();
+
+    private final ErrorLog _log;
+
+    private boolean _locked;
+
+    public RegistryBuilder(ErrorLog log)
+    {
+        _log = log;
+    }
+
+    public void add(ModuleDef moduleDef)
+    {
+        checkLocked();
+
+        String id = moduleDef.getModuleId();
+
+        if (_modules.containsKey(id))
+        {
+            _log.warn(IOCMessages.moduleIdConflict(id), null);
+            return;
+        }
+
+        _modules.put(id, moduleDef);
+    }
+
+    private void checkLocked()
+    {
+        if (_locked)
+            throw new RuntimeException(IOCMessages.builderLocked());
+    }
+
+    Registry build()
+    {
+        return null;
+    }
+}

Added: 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=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,42 @@
+// 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.ioc;
+
+import org.apache.tapestry.ioc.def.ServiceDef;
+
+/**
+ * A strategy for creating a service when first referenced. Most implementations create a proxy to
+ * the service, and defer the creation of the actual service implementation until needed.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public interface ServiceLifecycle
+{
+    /**
+     * Creates the service implementation or, more commonly, creates a proxy that will cause the
+     * service itself to be created as needed.
+     * @param serviceDef
+     *            additional definition of the service
+     * @param resources
+     *            source of additional services or other resources that may be needed when
+     *            constructing the core service implementation
+     * @param builder
+     *            module builder instance, against which methods may be invoked to create the
+     *            service
+     * 
+     * @return the service or equivalent service proxy
+     */
+    Object createService(ServiceDef serviceDef, Object moduleBuilder, ServiceResources resources);
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceResources.java?rev=419581&r1=419580&r2=419581&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceResources.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceResources.java Thu Jul  6 08:25:45 2006
@@ -22,18 +22,29 @@
  */
 public interface ServiceResources
 {
+    /** Returns the fully qualified id of the service. */
+    String getServiceId();
+
+    /** Returns the service interface implemented by the service. */
+    Class getServiceInterface();
+
     /**
-     * Locates a service given a fully qualified service id and the corresponding service interface
-     * type.
+     * Locates a service given a service id and the corresponding service interface type. The
+     * service id may be simple (just an id), in which case it is evaluated as a reference to
+     * another service within the same module. Alternately, it can be a fully qualified id, in which
+     * case the service may be provided by any module.
      * 
      * @param <T>
      * @param serviceId
-     *            fully qualified id of the service
+     *            the simple or fully qualified service id
      * @param serviceInterface
      *            the interface the service implements
-     * @return the service's proxy
+     * @return the service instance (or proxy)
      * @throws RuntimeException
      *             if the service does not exist (this is considered programmer error)
      */
     <T> T getService(String serviceId, Class<T> serviceInterface);
+
+    /** Returns an error log appropriate for the service. */
+    ErrorLog getErrorLog();
 }

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/annotations/Lifecycle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/annotations/Lifecycle.java?rev=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/annotations/Lifecycle.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/annotations/Lifecycle.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,38 @@
+// 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.ioc.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * An optional annotation that may be placed on a service building method of a module. The
+ * annotation overrides the default lifecycle for services (the default being a global singleton
+ * that is instantiated on demand) for an alternate lifecycle. Alternate lifecycles are typically
+ * used to bind a service implementation to a single thread or request.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+@Target(METHOD)
+@Retention(RUNTIME)
+@Documented
+public @interface Lifecycle {
+    /** An identifier used to look up a non-default lifecycle. */
+    String value();
+}

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ModuleDef.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ModuleDef.java?rev=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ModuleDef.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ModuleDef.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,52 @@
+// 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.ioc.def;
+
+import java.util.Set;
+
+/**
+ * Defines the contents of a module. In the default case, this is information about the services
+ * provided by the module builder class.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public interface ModuleDef
+{
+    /** Returns the ids of the services built/provided by the module. */
+    Set<String> getServiceIds();
+
+    /**
+     * Returns a service definition via the fully qualified service id.
+     * 
+     * @param serviceId
+     *            fully qualified service id
+     * @return service definition or null if it doesn't exist
+     */
+    ServiceDef getServiceDef(String serviceId);
+
+    /**
+     * Returns the module id extracted from the {@link org.apache.tapestry.ioc.annotations.Id}
+     * annotation on the module builder class (or calculated from the module builder's package, if
+     * the annotation is not present).
+     */
+    String getModuleId();
+
+    /**
+     * Returns the class that will be instantiated. Annotated instance methods of this class are
+     * invoked to build services, to decorate/intercept services, and make contributions to other
+     * services.
+     */
+    Class getBuilderClass();
+}
\ No newline at end of file

Copied: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java (from r418781, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDef.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java?p2=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDef.java&r1=418781&r2=419581&rev=419581&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDef.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java Thu Jul  6 08:25:45 2006
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.internal.ioc;
+package org.apache.tapestry.ioc.def;
 
 import java.lang.reflect.Method;
 
@@ -29,7 +29,7 @@
      */
     Method getBuilderMethod();
 
-    /** Returns the unqualified service id, derived from the method name. */
+    /** Returns the fully qualified service id, derived from the method name. */
     String getServiceId();
 
     /**
@@ -37,4 +37,11 @@
      * the outside world, as well as the one used to build proxies.
      */
     Class getServiceInterface();
+
+    /**
+     * Returns the lifecycle defined for the service. This is indicated by adding a
+     * {@link org.apache.tapestry.ioc.annotations.Lifecycle} annotation to the builder method for
+     * the service.
+     */
+    String getServiceLifeycle();
 }

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=419581&r1=419580&r2=419581&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 Thu Jul  6 08:25:45 2006
@@ -18,6 +18,7 @@
 import java.io.FileOutputStream;
 import java.io.OutputStream;
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
@@ -26,9 +27,10 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.hivemind.Resource;
-import org.apache.tapestry.internal.InternalComponentResources;
 import org.apache.tapestry.internal.annotations.SuppressNullCheck;
-import org.apache.tapestry.internal.parser.ComponentTemplate;
+import org.apache.tapestry.ioc.ErrorLog;
+import org.apache.tapestry.ioc.ServiceResources;
+import org.apache.tapestry.ioc.def.ServiceDef;
 import org.apache.tapestry.model.MutableComponentModel;
 import org.apache.tapestry.transform.ClassTransformation;
 
@@ -80,11 +82,6 @@
         return newMock(Log.class);
     }
 
-    protected final InternalComponentResources newInternalComponentResources()
-    {
-        return newMock(InternalComponentResources.class);
-    }
-
     protected final void trainAddInjectedField(ClassTransformation ct, Class type,
             String suggestedName, Object value, String fieldName)
     {
@@ -115,9 +112,9 @@
             if (newModified != startModified)
                 return;
 
-            // Sleep 1/4 second and try again
+            // Sleep 1/20 second and try again
 
-            sleep(250);
+            sleep(50);
         }
     }
 
@@ -156,9 +153,38 @@
         return newMock(Resource.class);
     }
 
-    protected final ComponentTemplate newComponentTemplate()
+    protected final void trainGetBuilderMethod(ServiceDef def, Method m)
+    {
+        def.getBuilderMethod();
+        setReturnValue(m);
+    }
+
+    protected final void trainGetServiceInterface(ServiceDef def, Class serviceInterface)
+    {
+        def.getServiceInterface();
+        setReturnValue(serviceInterface);
+    }
+
+    protected final void trainGetErrorLog(ServiceResources resources, ErrorLog log)
+    {
+        resources.getErrorLog();
+        setReturnValue(log);
+    }
+
+    protected final void trainGetServiceId(ServiceDef def, String serviceId)
+    {
+        def.getServiceId();
+        setReturnValue(serviceId);
+    }
+
+    protected final ServiceResources newServiceResources()
+    {
+        return newMock(ServiceResources.class);
+    }
+
+    protected final ServiceDef newServiceDef()
     {
-        return newMock(ComponentTemplate.class);
+        return newMock(ServiceDef.class);
     }
 
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java?rev=419581&r1=419580&r2=419581&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java Thu Jul  6 08:25:45 2006
@@ -15,6 +15,7 @@
 package org.apache.tapestry.test;
 
 import org.apache.tapestry.internal.annotations.SuppressNullCheck;
+import org.apache.tapestry.ioc.ErrorLog;
 import org.easymock.EasyMock;
 import org.easymock.IMocksControl;
 import org.testng.annotations.Configuration;
@@ -108,6 +109,11 @@
     protected final void unreachable()
     {
         fail("This code should not be reachable.");
+    }
+
+    protected final ErrorLog newErrorLog()
+    {
+        return newMock(ErrorLog.class);
     }
 
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java?rev=419581&r1=419580&r2=419581&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/CollectionFactory.java Thu Jul  6 08:25:45 2006
@@ -16,6 +16,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -74,7 +75,7 @@
     }
 
     /** Constructs and returns a new {@link ArrayList} as a copy of the provided list. */
-    public static <T> List<T> newList(List<T> list)
+    public static <T> List<T> newList(Collection<T> list)
     {
         return new ArrayList<T>(list);
     }

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=419581&r1=419580&r2=419581&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 Thu Jul  6 08:25:45 2006
@@ -15,4 +15,13 @@
 build-method-conflict=Service building method {0} conflicts with (has the same name as, but different parameters than) previously seen method {1} and has been ignored.
 void-build-method=Method {0} appears to be a service builder method, but a void return type doesn't make sense. The method has been ignored.
 build-method-wrong-return-type=Method {0} is named like a service builder method, but the return type is not acceptible (try an interface). The method has been ignored.
-missing-service=Service ''{0}'' (within module ''{1}'') does not exist.
\ No newline at end of file
+missing-service=Service ''{0}'' (within module ''{1}'') does not exist.
+builder-locked=The Registry Builder has created the Registry, further operations are not allowed.
+module-id-conflict=Module ''{0}'' has already been defined. The duplicate definition will be ignored.
+no-such-module=Module ''{0}'' does not exist. Please ensure that the JAR file for the module is on the classpath.
+service-wrong-interface=Service ''{0}'' implements interface {1}, which is not compatible with the requested type {2}.
+instantiate-builder-error=Unable to instantiate class {0} as builder for module ''{1}'': {2}
+singleton-proxy-to-string=<Singleton proxy for {0}({1})>
+builder-method-error=Error invoking builder method {0} (for service ''{1}''): {2}
+unknown-builder-parameter=Unexpected parameter type {0} for method {1} (service ''{2}''). The value null will be passed into the builder method. Expect further errors below.
+builder-method-returned-null=Builder method {0} (for service ''{1}'') returned null.
\ No newline at end of file

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/BasicServiceCreatorTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/BasicServiceCreatorTest.java?rev=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/BasicServiceCreatorTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/BasicServiceCreatorTest.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,276 @@
+// 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 java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.apache.tapestry.internal.annotations.SuppressNullCheck;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.ioc.ErrorLog;
+import org.apache.tapestry.ioc.ServiceResources;
+import org.apache.tapestry.ioc.def.ServiceDef;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertSame;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public class BasicServiceCreatorTest extends InternalBaseTestCase
+{
+    private static final String SERVICE_ID = "ioc.Fie";
+
+    private FieService _fie;
+
+    private String _expectedServiceId;
+
+    private ServiceResources _expectedServiceResources;
+
+    private ErrorLog _expectedErrorLog;
+
+    private Class _expectedServiceInterface;
+
+    private Method findMethod(String name)
+    {
+        return findMethod(this, name);
+    }
+
+    private Method findMethod(Object source, String name)
+    {
+        Class clazz = source.getClass();
+        for (Method m : clazz.getMethods())
+        {
+            if (m.getName().equals(name))
+                return m;
+        }
+
+        throw new RuntimeException("No method named '" + name + "'.");
+    }
+
+    @Test
+    public void noargsMethod()
+    {
+        ServiceDef def = newServiceDef();
+        ServiceResources resources = newServiceResources();
+        ErrorLog log = newErrorLog();
+        _fie = newFieService();
+
+        trainGetServiceId(def, SERVICE_ID);
+
+        trainGetErrorLog(resources, log);
+
+        trainGetServiceInterface(def, FieService.class);
+
+        replay();
+
+        ServiceCreator sc = new BasicServiceCreator(def, this, resources);
+
+        verify();
+
+        trainGetBuilderMethod(def, findMethod("build_noargs"));
+
+        replay();
+
+        Object actual = sc.createService();
+
+        assertSame(actual, _fie);
+
+        verify();
+    }
+
+    @Test
+    public void argsMethod()
+    {
+        ServiceDef def = newServiceDef();
+        ServiceResources resources = newServiceResources();
+        ErrorLog log = newErrorLog();
+
+        _expectedErrorLog = log;
+        _expectedServiceId = SERVICE_ID;
+        _expectedServiceInterface = FieService.class;
+        _expectedServiceResources = resources;
+
+        _fie = newFieService();
+
+        trainGetServiceId(def, SERVICE_ID);
+
+        trainGetErrorLog(resources, log);
+
+        trainGetServiceInterface(def, FieService.class);
+
+        trainGetBuilderMethod(def, findMethod("build_args"));
+
+        replay();
+
+        ServiceCreator sc = new BasicServiceCreator(def, this, resources);
+
+        Object actual = sc.createService();
+
+        assertSame(actual, _fie);
+
+        verify();
+    }
+
+    @Test
+    public void builderMethodReturnsNull()
+    {
+        ServiceDef def = newServiceDef();
+        ServiceResources resources = newServiceResources();
+        ErrorLog log = newErrorLog();
+        _fie = null;
+
+        trainGetServiceId(def, SERVICE_ID);
+
+        trainGetErrorLog(resources, log);
+
+        trainGetServiceInterface(def, FieService.class);
+
+        trainGetBuilderMethod(def, findMethod("build_noargs"));
+
+        replay();
+
+        ServiceCreator sc = new BasicServiceCreator(def, this, resources);
+
+        try
+        {
+            sc.createService();
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            Assert
+                    .assertEquals(
+                            ex.getMessage(),
+                            "Builder method public org.apache.tapestry.internal.ioc.FieService "
+                                    + "org.apache.tapestry.internal.ioc.BasicServiceCreatorTest.build_noargs() "
+                                    + "(for service 'ioc.Fie') returned null.");
+        }
+
+        verify();
+    }
+
+    @Test
+    public void builderMethodFailed()
+    {
+        ServiceDef def = newServiceDef();
+        ServiceResources resources = newServiceResources();
+        ErrorLog log = newErrorLog();
+        _fie = null;
+
+        trainGetServiceId(def, SERVICE_ID);
+
+        trainGetErrorLog(resources, log);
+
+        trainGetServiceInterface(def, FieService.class);
+
+        trainGetBuilderMethod(def, findMethod("build_fail"));
+
+        replay();
+
+        ServiceCreator sc = new BasicServiceCreator(def, this, resources);
+
+        try
+        {
+            sc.createService();
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertEquals(
+                    ex.getMessage(),
+                    "Error invoking builder method public org.apache.tapestry.internal.ioc.FieService "
+                            + "org.apache.tapestry.internal.ioc.BasicServiceCreatorTest.build_fail() "
+                            + "(for service 'ioc.Fie'): java.lang.reflect.InvocationTargetException");
+
+            InvocationTargetException inner1 = (InvocationTargetException) ex.getCause();
+            RuntimeException inner2 = (RuntimeException) inner1.getTargetException();
+
+            assertEquals(inner2.getMessage(), "Method failed.");
+        }
+
+        verify();
+    }
+
+    @Test
+    public void builderMethodHasUnmatchableParameter()
+    {
+        ServiceDef def = newServiceDef();
+        ServiceResources resources = newServiceResources();
+        ErrorLog log = newErrorLog();
+        _fie = newFieService();
+
+        trainGetServiceId(def, SERVICE_ID);
+
+        trainGetErrorLog(resources, log);
+
+        trainGetServiceInterface(def, FieService.class);
+
+        Method method = findMethod("build_invalidargs");
+
+        trainGetBuilderMethod(def, method);
+
+        // The second call is when we need to report the method as having an error.
+
+        trainGetBuilderMethod(def, method);
+
+        log.warn(IOCMessages.unknownBuilderParameter(Object.class, method, SERVICE_ID), null);
+
+        replay();
+
+        ServiceCreator sc = new BasicServiceCreator(def, this, resources);
+
+        Object actual = sc.createService();
+
+        verify();
+
+        assertSame(actual, _fie);
+    }
+
+    private FieService newFieService()
+    {
+        return newMock(FieService.class);
+    }
+
+    public FieService build_noargs()
+    {
+        return _fie;
+    }
+
+    @SuppressNullCheck
+    public FieService build_invalidargs(Object unknown)
+    {
+        return _fie;
+    }
+
+    public FieService build_fail()
+    {
+        throw new RuntimeException("Method failed.");
+    }
+
+    public FieService build_args(String serviceId, ServiceResources resources, ErrorLog errorLog,
+            Class serviceInterface)
+    {
+        assertEquals(serviceId, _expectedServiceId);
+        assertSame(resources, _expectedServiceResources);
+        assertSame(errorLog, _expectedErrorLog);
+        assertSame(serviceInterface, _expectedServiceInterface);
+
+        return _fie;
+    }
+
+}

Copied: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImplTest.java (from r418781, tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleGrinderTest.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImplTest.java?p2=tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImplTest.java&p1=tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleGrinderTest.java&r1=418781&r2=419581&rev=419581&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleGrinderTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImplTest.java Thu Jul  6 08:25:45 2006
@@ -19,17 +19,21 @@
 import java.util.Set;
 
 import org.apache.tapestry.ioc.ErrorLog;
+import org.apache.tapestry.ioc.IOCConstants;
+import org.apache.tapestry.ioc.def.ModuleDef;
+import org.apache.tapestry.ioc.def.ServiceDef;
 import org.apache.tapestry.test.TestBase;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import static org.apache.tapestry.internal.ioc.IOCMessages.buildMethodConflict;
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
 
 /**
  * @author Howard M. Lewis Ship
  */
-public class ModuleGrinderTest extends TestBase
+public class DefaultModuleDefImplTest extends TestBase
 {
     @Test
     public void moduleBuilderWithoutId()
@@ -40,18 +44,13 @@
 
         // BigDecimal is arbitrary, any class would do.
 
-        ModuleGrinder g = new ModuleGrinder(BigDecimal.class, log);
+        ModuleDef g = new DefaultModuleDefImpl(BigDecimal.class, log);
 
         Assert.assertEquals("java.math", g.getModuleId());
 
         verify();
     }
 
-    protected final ErrorLog newErrorLog()
-    {
-        return newMock(ErrorLog.class);
-    }
-
     @Test
     public void moduleBuilderWithId()
     {
@@ -61,7 +60,7 @@
 
         // BigDecimal is arbitrary, any class would do.
 
-        ModuleGrinder g = new ModuleGrinder(ModuleBuilderWithId.class, log);
+        ModuleDef g = new DefaultModuleDefImpl(ModuleBuilderWithId.class, log);
 
         Assert.assertEquals("tapestry.ioc", g.getModuleId());
 
@@ -77,29 +76,31 @@
 
         // BigDecimal is arbitrary, any class would do.
 
-        ModuleGrinder g = new ModuleGrinder(SimpleModuleBuilder.class, log);
+        ModuleDef g = new DefaultModuleDefImpl(SimpleModuleBuilder.class, log);
 
         Set<String> ids = g.getServiceIds();
 
-        Assert.assertEquals(ids.size(), 2);
-        Assert.assertTrue(ids.contains("Fred"));
-        Assert.assertTrue(ids.contains("Barney"));
+        assertEquals(ids.size(), 2);
+        assertTrue(ids.contains("ioc.Fred"));
+        assertTrue(ids.contains("ioc.Barney"));
 
-        ServiceDef sd = g.getServiceDef("Fred");
+        ServiceDef sd = g.getServiceDef("ioc.Fred");
 
-        assertEquals(sd.getServiceId(), "Fred");
+        assertEquals(sd.getServiceId(), "ioc.Fred");
 
         assertEquals(sd.getServiceInterface(), FieService.class);
 
         assertEquals(sd.getBuilderMethod(), SimpleModuleBuilder.class.getMethod("buildFred"));
+        assertEquals(sd.getServiceLifeycle(), IOCConstants.DEFAULT_LIFECYCLE);
 
-        sd = g.getServiceDef("Barney");
+        sd = g.getServiceDef("ioc.Barney");
 
-        assertEquals(sd.getServiceId(), "Barney");
+        assertEquals(sd.getServiceId(), "ioc.Barney");
 
         assertEquals(sd.getServiceInterface(), FoeService.class);
 
         assertEquals(sd.getBuilderMethod(), SimpleModuleBuilder.class.getMethod("buildBarney"));
+        assertEquals(sd.getServiceLifeycle(), "threaded");
 
         verify();
     }
@@ -121,16 +122,16 @@
 
         // BigDecimal is arbitrary, any class would do.
 
-        ModuleGrinder g = new ModuleGrinder(ServiceIdConflictMethodBuilder.class, log);
+        ModuleDef g = new DefaultModuleDefImpl(ServiceIdConflictMethodBuilder.class, log);
 
         Set<String> ids = g.getServiceIds();
 
         Assert.assertEquals(ids.size(), 1);
-        Assert.assertTrue(ids.contains("Fred"));
+        Assert.assertTrue(ids.contains("ioc.Fred"));
 
-        ServiceDef sd = g.getServiceDef("Fred");
+        ServiceDef sd = g.getServiceDef("ioc.Fred");
 
-        assertEquals(sd.getServiceId(), "Fred");
+        assertEquals(sd.getServiceId(), "ioc.Fred");
 
         assertEquals(sd.getServiceInterface(), FieService.class);
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleBuilderWithId.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleBuilderWithId.java?rev=419581&r1=419580&r2=419581&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleBuilderWithId.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleBuilderWithId.java Thu Jul  6 08:25:45 2006
@@ -17,7 +17,7 @@
 import org.apache.tapestry.ioc.annotations.Id;
 
 /**
- * Used by {@link org.apache.tapestry.internal.ioc.ModuleGrinderTest}.
+ * Used by {@link org.apache.tapestry.internal.ioc.DefaultModuleDefImplTest}.
  * 
  * @author Howard M. Lewis Ship
  */

Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ReadManifest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ReadManifest.java?rev=419581&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ReadManifest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ReadManifest.java Thu Jul  6 08:25:45 2006
@@ -0,0 +1,91 @@
+// 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 java.io.InputStream;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import static java.lang.String.format;
+import static org.apache.tapestry.util.CollectionFactory.newList;
+
+public class ReadManifest
+{
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) throws Exception
+    {
+        ClassLoader loader = ReadManifest.class.getClassLoader();
+
+        Enumeration<URL> urls = loader.getResources("META-INF/MANIFEST.MF");
+
+        while (urls.hasMoreElements())
+        {
+            URL url = urls.nextElement();
+
+            System.out.println(url);
+
+            InputStream is = url.openStream();
+
+            Manifest mf = new Manifest(is);
+
+            is.close();
+
+            printManifest(mf);
+        }
+
+    }
+
+    static void printManifest(Manifest mf)
+    {
+
+        printAttributes(mf.getMainAttributes());
+
+        if (false)
+        {
+            Map<String, Attributes> entries = mf.getEntries();
+            List<String> keys = newList(entries.keySet());
+            Collections.sort(keys);
+
+            for (String key : keys)
+            {
+                System.out.println(format("  %s", key));
+
+                Attributes a = entries.get(key);
+
+                printAttributes(a);
+
+            }
+        }
+    }
+
+    private static void printAttributes(Attributes a)
+    {
+        for (Object key : a.keySet())
+        {
+            Object value = a.get(key);
+
+            System.out.println(format("    %30s: %s", key, value));
+        }
+
+    }
+}

Copied: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ServiceIdConflictMethodBuilder.java (from r418781, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceIdConflictMethodBuilder.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ServiceIdConflictMethodBuilder.java?p2=tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ServiceIdConflictMethodBuilder.java&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceIdConflictMethodBuilder.java&r1=418781&r2=419581&rev=419581&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceIdConflictMethodBuilder.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ServiceIdConflictMethodBuilder.java Thu Jul  6 08:25:45 2006
@@ -14,11 +14,14 @@
 
 package org.apache.tapestry.internal.ioc;
 
+import org.apache.tapestry.ioc.annotations.Id;
+
 /**
- * Used by {@link org.apache.tapestry.internal.ioc.ModuleGrinderTest}.
+ * Used by {@link org.apache.tapestry.internal.ioc.DefaultModuleDefImplTest}.
  * 
  * @author Howard M. Lewis Ship
  */
+@Id("ioc")
 public class ServiceIdConflictMethodBuilder
 {
     public FieService buildFred()

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SimpleModuleBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SimpleModuleBuilder.java?rev=419581&r1=419580&r2=419581&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SimpleModuleBuilder.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SimpleModuleBuilder.java Thu Jul  6 08:25:45 2006
@@ -14,11 +14,15 @@
 
 package org.apache.tapestry.internal.ioc;
 
+import org.apache.tapestry.ioc.annotations.Id;
+import org.apache.tapestry.ioc.annotations.Lifecycle;
+
 /**
- * Used by {@link org.apache.tapestry.internal.ioc.ModuleGrinderTest}.
+ * Used by {@link org.apache.tapestry.internal.ioc.DefaultModuleDefImplTest}.
  * 
  * @author Howard M. Lewis Ship
  */
+@Id("ioc")
 public class SimpleModuleBuilder
 {
     public FieService buildFred()
@@ -26,6 +30,7 @@
         return null;
     }
 
+    @Lifecycle("threaded")
     public FoeService buildBarney()
     {
         return null;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImplTest.java?rev=419581&r1=419580&r2=419581&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImplTest.java Thu Jul  6 08:25:45 2006
@@ -14,8 +14,6 @@
 
 package org.apache.tapestry.internal.pageload;
 
-import static org.testng.Assert.assertSame;
-
 import java.io.File;
 import java.net.URLClassLoader;
 import java.util.Locale;
@@ -29,15 +27,17 @@
 import org.apache.tapestry.events.UpdateEvent;
 import org.apache.tapestry.internal.parser.ComponentTemplate;
 import org.apache.tapestry.internal.parser.TemplateParser;
-import org.apache.tapestry.test.BaseTestCase;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
 import org.easymock.EasyMock;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
+import static org.testng.Assert.assertSame;
+
 /**
  * @author Howard M. Lewis Ship
  */
-public class ComponentTemplateSourceImplTest extends BaseTestCase
+public class ComponentTemplateSourceImplTest extends InternalBaseTestCase
 {
     private static final String PACKAGE = "org.apache.tapestry.internal.pageload";
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImplTest.java?rev=419581&r1=419580&r2=419581&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/ComponentInstantiatorSourceImplTest.java Thu Jul  6 08:25:45 2006
@@ -261,4 +261,9 @@
         _registry = null;
         _source = null;
     }
+
+    protected final InternalComponentResources newInternalComponentResources()
+    {
+        return newMock(InternalComponentResources.class);
+    }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/InternalClassTransformationImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/InternalClassTransformationImplTest.java?rev=419581&r1=419580&r2=419581&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/InternalClassTransformationImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/InternalClassTransformationImplTest.java Thu Jul  6 08:25:45 2006
@@ -415,4 +415,9 @@
         assertNull(getters.getObjectArray());
         assertNull(getters.getIntArray());
     }
+
+    protected final InternalComponentResources newInternalComponentResources()
+    {
+        return newMock(InternalComponentResources.class);
+    }
 }