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/11/21 01:58:30 UTC

svn commit: r477448 [3/3] - in /tapestry/tapestry5: tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/s...

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java?view=auto&rev=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java Mon Nov 20 16:58:25 2006
@@ -0,0 +1,275 @@
+// 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 static org.apache.tapestry.internal.ioc.ConfigurationType.MAPPED;
+import static org.apache.tapestry.internal.ioc.ConfigurationType.ORDERED;
+import static org.apache.tapestry.internal.ioc.ConfigurationType.UNORDERED;
+import static org.apache.tapestry.util.CollectionFactory.newMap;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.internal.util.InternalUtils;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
+import org.apache.tapestry.ioc.ServiceResources;
+
+/**
+ * Basic implementation of {@link org.apache.tapestry.ioc.ObjectCreator} that handles invoking a
+ * method on the module builder, and figures out the correct parameters to pass into the annotated
+ * method.
+ */
+public class ServiceBuilderMethodInvoker implements ObjectCreator
+{
+    private final String _serviceId;
+
+    private final Map<Class, Object> _parameterDefaults = newMap();
+
+    private final ServiceBuilderResources _resources;
+
+    private final Method _builderMethod;
+
+    private final Log _log;
+
+    private final static Map<Class, ConfigurationType> PARAMETER_TYPE_TO_CONFIGURATION_TYPE = newMap();
+
+    static
+    {
+        PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(Collection.class, UNORDERED);
+        PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(List.class, ORDERED);
+        PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(Map.class, MAPPED);
+    }
+
+    public ServiceBuilderMethodInvoker(Method method, ServiceBuilderResources resources)
+    {
+        _serviceId = resources.getServiceId();
+        _builderMethod = method;
+        _resources = resources;
+        _log = resources.getServiceLog();
+
+        _parameterDefaults.put(String.class, _serviceId);
+        _parameterDefaults.put(ServiceResources.class, resources);
+        _parameterDefaults.put(Log.class, _log);
+        _parameterDefaults.put(Class.class, resources.getServiceInterface());
+    }
+
+    /**
+     * Returns a map (based on _parameterDefaults) that includes (possibly) an additional mapping
+     * containing the collected configuration data. This involves scanning the builder method's
+     * parameters
+     */
+    private Map<Class, Object> getParameterDefaultsWithConfigurations()
+    {
+        Map<Class, Object> result = newMap(_parameterDefaults);
+        ConfigurationType type = null;
+
+        Class[] parameterTypes = _builderMethod.getParameterTypes();
+
+        for (int i = 0; i < parameterTypes.length; i++)
+        {
+            Class parameterType = parameterTypes[i];
+
+            ConfigurationType thisType = PARAMETER_TYPE_TO_CONFIGURATION_TYPE.get(parameterType);
+
+            if (thisType == null)
+                continue;
+
+            if (type != null)
+            {
+                _log.warn(IOCMessages.tooManyConfigurationParameters(_builderMethod));
+                break;
+            }
+
+            // Remember that we've seen a configuration parameter, in case there
+            // is another.
+
+            type = thisType;
+
+            Type genericType = _builderMethod.getGenericParameterTypes()[i];
+
+            switch (type)
+            {
+
+                case UNORDERED:
+
+                    addUnorderedConfigurationParameter(result, genericType);
+
+                    break;
+
+                case ORDERED:
+
+                    addOrderedConfigurationParameter(result, genericType);
+
+                    break;
+
+                case MAPPED:
+
+                    addMappedConfigurationParameter(result, genericType);
+
+                    break;
+
+            }
+
+        }
+
+        return result;
+    }
+
+    @SuppressWarnings("unchecked")
+    private void addOrderedConfigurationParameter(Map<Class, Object> parameterDefaults,
+            Type genericType)
+    {
+        Class valueType = findParameterizedTypeFromGenericType(genericType);
+        List configuration = _resources.getOrderedConfiguration(valueType);
+
+        parameterDefaults.put(List.class, configuration);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void addUnorderedConfigurationParameter(Map<Class, Object> parameterDefaults,
+            Type genericType)
+    {
+        Class valueType = findParameterizedTypeFromGenericType(genericType);
+        Collection configuration = _resources.getUnorderedConfiguration(valueType);
+
+        parameterDefaults.put(Collection.class, configuration);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void addMappedConfigurationParameter(Map<Class, Object> parameterDefaults,
+            Type genericType)
+    {
+        Class keyType = findParameterizedTypeFromGenericType(genericType, 0);
+        Class valueType = findParameterizedTypeFromGenericType(genericType, 1);
+
+        if (keyType == null || valueType == null)
+            throw new IllegalArgumentException(IOCMessages.genericTypeNotSupported(genericType));
+
+        Map configuration = _resources.getMappedConfiguration(keyType, valueType);
+
+        parameterDefaults.put(Map.class, configuration);
+    }
+
+    /**
+     * Extracts from a generic type the underlying parameterized type. I.e., for List<Runnable>,
+     * will return Runnable. This is limited to simple parameterized types, not the more complex
+     * cases involving wildcards and upper/lower boundaries.
+     * 
+     * @param type
+     *            the genetic type of the parameter, i.e., List<Runnable>
+     * @return the parameterize type (i.e. Runnable.class if type represents List<Runnable>).
+     */
+
+    // package private for testing
+    static Class findParameterizedTypeFromGenericType(Type type)
+    {
+        Class result = findParameterizedTypeFromGenericType(type, 0);
+
+        if (result == null)
+            throw new IllegalArgumentException(IOCMessages.genericTypeNotSupported(type));
+
+        return result;
+    }
+
+    /**
+     * "Sniffs" a generic type to find the underlying parameterized type. If the Type is a class,
+     * then Object.class is returned. Otherwise, the type must be a ParameterizedType. We check to
+     * make sure it has the correct number of a actual types (1 for a Collection or List, 2 for a
+     * Map). The actual types must be classes (wildcards just aren't supported)
+     * 
+     * @param type
+     *            a Class or ParameterizedType to inspect
+     * @param typeIndex
+     *            the index within the ParameterizedType to extract
+     * @return the actual type, or Object.class if the input type is not generic, or null if any
+     *         other pre-condition is not met
+     */
+    private static Class findParameterizedTypeFromGenericType(Type type, int typeIndex)
+    {
+        // For a raw Class type, it means the parameter is not parameterized (i.e. Collection, not
+        // Collection<Foo>), so we can return Object.class to allow no restriction.
+
+        if (type instanceof Class)
+            return Object.class;
+
+        if (!(type instanceof ParameterizedType))
+            return null;
+
+        ParameterizedType pt = (ParameterizedType) type;
+
+        Type[] types = pt.getActualTypeArguments();
+
+        Type actualType = types[typeIndex];
+
+        return actualType instanceof Class ? (Class) actualType : null;
+
+    }
+
+    /**
+     * Invoked from the proxy to create the actual service implementation.
+     */
+    public Object createObject()
+    {
+        // Defer getting (and possibly instantitating) the module builder until the last possible
+        // moment. If the method is static, there's no need to even get the builder.
+
+        Object moduleBuilder = InternalUtils.isStatic(_builderMethod) ? null : _resources
+                .getModuleBuilder();
+
+        Object result = null;
+        Throwable failure = null;
+
+        try
+        {
+            Object[] parameters = InternalUtils.calculateParametersForMethod(
+                    _builderMethod,
+                    _resources,
+                    getParameterDefaultsWithConfigurations());
+
+            if (_log.isDebugEnabled())
+                _log.debug(IOCMessages.invokingMethod(_builderMethod));
+
+            result = _builderMethod.invoke(moduleBuilder, parameters);
+        }
+        catch (InvocationTargetException ite)
+        {
+            failure = ite.getTargetException();
+        }
+        catch (Exception ex)
+        {
+            failure = ex;
+        }
+
+        if (failure != null)
+            throw new RuntimeException(IOCMessages.builderMethodError(
+                    _builderMethod,
+                    _serviceId,
+                    failure), failure);
+
+        if (result == null)
+            throw new RuntimeException(IOCMessages.builderMethodReturnedNull(
+                    _builderMethod,
+                    _serviceId));
+
+        return result;
+    }
+}

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDecoratorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDecoratorImpl.java?view=auto&rev=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDecoratorImpl.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDecoratorImpl.java Mon Nov 20 16:58:25 2006
@@ -0,0 +1,123 @@
+// 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 static org.apache.tapestry.util.CollectionFactory.newMap;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.internal.util.InternalUtils;
+import org.apache.tapestry.ioc.ModuleBuilderSource;
+import org.apache.tapestry.ioc.ServiceDecorator;
+import org.apache.tapestry.ioc.ServiceResources;
+
+/**
+ * A wrapper around a decorator method.
+ * 
+ * 
+ */
+public class ServiceDecoratorImpl implements ServiceDecorator
+{
+    private final ModuleBuilderSource _moduleBuilderSource;
+
+    private final String _serviceId;
+
+    private final Map<Class, Object> _parameterDefaults = newMap();
+
+    private final Log _log;
+
+    private final ServiceResources _resources;
+
+    private final Method _decoratorMethod;
+
+    private final Class _serviceInterface;
+
+    public ServiceDecoratorImpl(Method method, ModuleBuilderSource moduleBuilderSource,
+            ServiceResources resources)
+    {
+        _serviceId = resources.getServiceId();
+        _decoratorMethod = method;
+        _moduleBuilderSource = moduleBuilderSource;
+        _resources = resources;
+        _serviceInterface = resources.getServiceInterface();
+        _log = resources.getServiceLog();
+
+        _parameterDefaults.put(String.class, _serviceId);
+        _parameterDefaults.put(ServiceResources.class, resources);
+        _parameterDefaults.put(Log.class, _log);
+        _parameterDefaults.put(Class.class, _serviceInterface);
+    }
+
+    public Object createInterceptor(Object delegate)
+    {
+        // Create a copy of the parameters map so that Object.class points to the delegate instance.
+
+        Map<Class, Object> parameterDefaults = newMap(_parameterDefaults);
+        parameterDefaults.put(Object.class, delegate);
+
+        if (_log.isDebugEnabled())
+            _log.debug(IOCMessages.invokingMethod(_decoratorMethod));
+
+        Object result = null;
+        Throwable failure = null;
+
+        Object moduleBuilder = InternalUtils.isStatic(_decoratorMethod) ? null : _moduleBuilderSource
+                .getModuleBuilder();
+
+        try
+        {
+            Object[] parameters = InternalUtils.calculateParametersForMethod(
+                    _decoratorMethod,
+                    _resources,
+                    parameterDefaults);
+
+            result = _decoratorMethod.invoke(moduleBuilder, parameters);
+        }
+        catch (InvocationTargetException ite)
+        {
+            failure = ite.getTargetException();
+        }
+
+        catch (Exception ex)
+        {
+            failure = ex;
+        }
+
+        if (failure != null)
+            throw new RuntimeException(IOCMessages.decoratorMethodError(
+                    _decoratorMethod,
+                    _serviceId,
+                    failure), failure);
+
+        if (result != null && !_serviceInterface.isInstance(result))
+        {
+            _log.warn(IOCMessages.decoratorReturnedWrongType(
+                    _decoratorMethod,
+                    _serviceId,
+                    result,
+                    _serviceInterface), null);
+
+            // Change the result to null so that we won't use the interceptor,
+            // and so that ClassCastExceptions don't occur later down the pipeline.
+
+            result = null;
+        }
+
+        return result;
+    }
+}

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java?view=auto&rev=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java Mon Nov 20 16:58:25 2006
@@ -0,0 +1,90 @@
+// 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.Method;
+
+import org.apache.tapestry.internal.util.InternalUtils;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
+import org.apache.tapestry.ioc.def.ServiceDef;
+
+/**
+ * 
+ */
+public class ServiceDefImpl implements ServiceDef
+{
+    private final Method _builderMethod;
+
+    private final String _serviceId;
+
+    private final String _lifecycle;
+
+    private final boolean _private;
+
+    private final boolean _eagerLoad;
+
+    ServiceDefImpl(String serviceId, String lifecycle, Method builderMethod, boolean isprivate,
+            boolean eagerLoad)
+    {
+        _serviceId = serviceId;
+        _lifecycle = lifecycle;
+        _builderMethod = builderMethod;
+        _private = isprivate;
+        _eagerLoad = eagerLoad;
+    }
+
+    @Override
+    public String toString()
+    {
+        return InternalUtils.asString(_builderMethod);
+    }
+
+    Method getBuilderMethod()
+    {
+        return _builderMethod;
+    }
+
+    public ObjectCreator createServiceCreator(ServiceBuilderResources resources)
+    {
+        return new ServiceBuilderMethodInvoker(_builderMethod, resources);
+    }
+
+    public String getServiceId()
+    {
+        return _serviceId;
+    }
+
+    public Class getServiceInterface()
+    {
+        return _builderMethod.getReturnType();
+    }
+
+    public String getServiceLifeycle()
+    {
+        return _lifecycle;
+    }
+
+    public boolean isPrivate()
+    {
+        return _private;
+    }
+
+    public boolean isEagerLoad()
+    {
+        return _eagerLoad;
+    }
+
+}

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java?view=auto&rev=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java Mon Nov 20 16:58:25 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 static org.apache.tapestry.ioc.IOCUtilities.toQualifiedId;
+
+import org.apache.tapestry.ioc.ServiceLocator;
+
+/**
+ * Base service locator class used when only the module is known (i.e., when instantiating a module
+ * builder class).
+ * 
+ * 
+ */
+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;
+    }
+}

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java?view=auto&rev=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java Mon Nov 20 16:58:25 2006
@@ -0,0 +1,103 @@
+// 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.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
+import org.apache.tapestry.ioc.def.ServiceDef;
+
+/**
+ * Implementation of {@link org.apache.tapestry.ioc.ServiceBuilderResources}. We just have one
+ * implementation that fills the purposes of methods that need a
+ * {@link org.apache.tapestry.ioc.ServiceResources} (which includes service decorator methods) as
+ * well as methods that need a {@link org.apache.tapestry.ioc.ServiceBuilderResources} (which is
+ * just service builder methods). Since it is most commonly used for the former, we'll just leave
+ * the name as ServiceResourcesImpl.
+ * 
+ * 
+ */
+public class ServiceResourcesImpl extends ServiceLocatorImpl implements ServiceBuilderResources
+{
+    private final ServiceDef _serviceDef;
+
+    private Log _log;
+
+    public ServiceResourcesImpl(InternalRegistry registry, Module module, ServiceDef serviceDef,
+            Log log)
+    {
+        super(registry, module);
+        _serviceDef = serviceDef;
+        _log = log;
+    }
+
+    public String getServiceId()
+    {
+        return _serviceDef.getServiceId();
+    }
+
+    public Class getServiceInterface()
+    {
+        return _serviceDef.getServiceInterface();
+    }
+
+    public Log getServiceLog()
+    {
+        return _log;
+    }
+
+    public <T> Collection<T> getUnorderedConfiguration(Class<T> valueType)
+    {
+        Collection<T> result = getRegistry().getUnorderedConfiguration(_serviceDef, valueType);
+
+        logConfiguration(result);
+
+        return result;
+    }
+
+    private void logConfiguration(Collection configuration)
+    {
+        if (_log.isDebugEnabled())
+            _log.debug(IOCMessages.constructedConfiguration(configuration));
+    }
+
+    public <T> List<T> getOrderedConfiguration(Class<T> valueType)
+    {
+        List<T> result = getRegistry().getOrderedConfiguration(_serviceDef, valueType);
+
+        logConfiguration(result);
+
+        return result;
+    }
+
+    public <K, V> Map<K, V> getMappedConfiguration(Class<K> keyType, Class<V> valueType)
+    {
+        Map<K, V> result = getRegistry().getMappedConfiguration(_serviceDef, keyType, valueType);
+
+        if (_log.isDebugEnabled())
+            _log.debug(IOCMessages.constructedConfiguration(result));
+
+        return result;
+    }
+
+    public Object getModuleBuilder()
+    {
+        return getModule().getModuleBuilder();
+    }
+
+}

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java?view=auto&rev=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java Mon Nov 20 16:58:25 2006
@@ -0,0 +1,33 @@
+// 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.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.ObjectCreator} to create an instance of the service when asked.
+ * 
+ * 
+ */
+public class SingletonServiceLifecycle implements ServiceLifecycle
+{
+    public Object createService(ServiceResources resources, ObjectCreator creator)
+    {
+        return creator.createObject();
+    }
+}

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapper.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapper.java?view=auto&rev=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapper.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapper.java Mon Nov 20 16:58:25 2006
@@ -0,0 +1,68 @@
+// 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.commons.logging.Log;
+import org.apache.tapestry.ioc.Configuration;
+import org.apache.tapestry.ioc.def.ContributionDef;
+
+/**
+ * Performs some validation before delegating to another Configuration.
+ */
+public class ValidatingConfigurationWrapper<T> implements Configuration<T>
+{
+    private final String _serviceId;
+
+    private final ContributionDef _contributionDef;
+
+    private final Log _log;
+
+    private final Configuration<T> _delegate;
+
+    private final Class _expectedType;
+
+    // Need a strategy for determing the right order for this mass of parameters!
+
+    public ValidatingConfigurationWrapper(String serviceId, Log log, Class expectedType,
+            ContributionDef contributionDef, Configuration<T> delegate)
+    {
+        _serviceId = serviceId;
+        _log = log;
+        _expectedType = expectedType;
+        _contributionDef = contributionDef;
+        _delegate = delegate;
+    }
+
+    public void add(T object)
+    {
+        if (object == null)
+        {
+            _log.warn(IOCMessages.contributionWasNull(_serviceId, _contributionDef));
+            return;
+        }
+
+        // Sure, we say it is type T ... but is it really?
+
+        if (!_expectedType.isInstance(object))
+        {
+            _log.warn(IOCMessages.contributionWrongValueType(_serviceId, _contributionDef, object
+                    .getClass(), _expectedType));
+            return;
+        }
+
+        _delegate.add(object);
+    }
+
+}

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingMappedConfigurationWrapper.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingMappedConfigurationWrapper.java?view=auto&rev=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingMappedConfigurationWrapper.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingMappedConfigurationWrapper.java Mon Nov 20 16:58:25 2006
@@ -0,0 +1,109 @@
+// 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.commons.logging.Log;
+import org.apache.tapestry.ioc.MappedConfiguration;
+import org.apache.tapestry.ioc.def.ContributionDef;
+
+/**
+ * Provides two forms of validation for mapped configurations:
+ * <ul>
+ * <li>If either key or value is null, then a warning is logged </li>
+ * <li>If the key has previously been stored (by some other
+ * {@link org.apache.tapestry.ioc.def.ContributionDef}, then a warning is logged</li>
+ * </ul>
+ * <p>
+ * When a warning is logged, the key/value pair is not added to the delegate.
+ * 
+ * @param <K>
+ * @param <V>
+ */
+public class ValidatingMappedConfigurationWrapper<K, V> implements MappedConfiguration<K, V>
+{
+    private final String _serviceId;
+
+    private final ContributionDef _contributionDef;
+
+    private final Log _log;
+
+    private final Class<K> _expectedKeyType;
+
+    private final Class<V> _expectedValueType;
+
+    private final Map<K, ContributionDef> _keyToContributor;
+
+    private final MappedConfiguration<K, V> _delegate;
+
+    public ValidatingMappedConfigurationWrapper(String serviceId, ContributionDef contributionDef,
+            Log log, Class<K> expectedKeyType, Class<V> expectedValueType,
+            Map<K, ContributionDef> keyToContributor, MappedConfiguration<K, V> delegate)
+    {
+        _serviceId = serviceId;
+        _contributionDef = contributionDef;
+        _log = log;
+        _expectedKeyType = expectedKeyType;
+        _expectedValueType = expectedValueType;
+        _keyToContributor = keyToContributor;
+        _delegate = delegate;
+    }
+
+    public void add(K key, V value)
+    {
+        if (key == null)
+        {
+            _log.warn(IOCMessages.contributionKeyWasNull(_serviceId, _contributionDef));
+            return;
+        }
+
+        if (value == null)
+        {
+            _log.warn(IOCMessages.contributionWasNull(_serviceId, _contributionDef));
+            return;
+        }
+
+        if (!_expectedKeyType.isInstance(key))
+        {
+            _log.warn(IOCMessages.contributionWrongKeyType(_serviceId, _contributionDef, key
+                    .getClass(), _expectedKeyType));
+            return;
+        }
+
+        if (!_expectedValueType.isInstance(value))
+        {
+            _log.warn(IOCMessages.contributionWrongValueType(_serviceId, _contributionDef, value
+                    .getClass(), _expectedValueType));
+            return;
+        }
+
+        ContributionDef existing = _keyToContributor.get(key);
+
+        if (existing != null)
+        {
+            _log.warn(IOCMessages.contributionDuplicateKey(_serviceId, _contributionDef, existing));
+            return;
+        }
+
+        _delegate.add(key, value);
+
+        // Remember that this key is provided by this contribution, when looking
+        // for future conflicts.
+
+        _keyToContributor.put(key, _contributionDef);
+    }
+
+}

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingOrderedConfigurationWrapper.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingOrderedConfigurationWrapper.java?view=auto&rev=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingOrderedConfigurationWrapper.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingOrderedConfigurationWrapper.java Mon Nov 20 16:58:25 2006
@@ -0,0 +1,75 @@
+// 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 static org.apache.tapestry.ioc.IOCUtilities.toQualifiedId;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.ioc.OrderedConfiguration;
+import org.apache.tapestry.ioc.def.ContributionDef;
+
+/**
+ * Implements validation of values provided to an
+ * {@link org.apache.tapestry.ioc.OrderedConfiguration}. It also takes care of qualifying any ids.
+ * If you provide an incorrect value type, the value is converted to null but added anyway. This
+ * ensures that incorrect values contributed in don't screw up the
+ * {@link org.apache.tapestry.internal.util.Orderer} (and generate a bunch of error messages there).
+ * 
+ * @param <T>
+ */
+public class ValidatingOrderedConfigurationWrapper<T> implements OrderedConfiguration<T>
+{
+    private final String _serviceId;
+
+    /** Module id containing the contribution (not necessarily the service). */
+    private final String _moduleId;
+
+    private final ContributionDef _contributionDef;
+
+    private final Log _log;
+
+    private final Class _expectedType;
+
+    private final OrderedConfiguration<T> _delegate;
+
+    public ValidatingOrderedConfigurationWrapper(String serviceId, String moduleId,
+            ContributionDef contributionDef, Log log, Class expectedType,
+            OrderedConfiguration<T> delegate)
+    {
+        _serviceId = serviceId;
+        _moduleId = moduleId;
+        _contributionDef = contributionDef;
+        _log = log;
+        _expectedType = expectedType;
+        _delegate = delegate;
+    }
+
+    public void add(String id, T object, String... constraints)
+    {
+        _delegate.add(toQualifiedId(_moduleId, id), validVersionOf(object), constraints);
+    }
+
+    private T validVersionOf(T object)
+    {
+        if (object == null || _expectedType.isInstance(object))
+            return object;
+
+        if (!_expectedType.isInstance(object))
+            _log.warn(IOCMessages.contributionWrongValueType(_serviceId, _contributionDef, object
+                    .getClass(), _expectedType));
+
+        return null;
+    }
+}

Copied: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java (from r477434, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java?view=diff&rev=477448&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java&r1=477434&p2=tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java&r2=477448
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java Mon Nov 20 16:58:25 2006
@@ -21,7 +21,7 @@
 import javassist.CtClass;
 
 import org.apache.commons.logging.Log;
-import org.apache.tapestry.internal.util.OneShotLock;
+import org.apache.tapestry.ioc.internal.util.OneShotLock;
 
 /**
  * Base class for {@link org.apache.tapestry.internal.ioc.services.ClassFabImpl}. This code is a

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java
------------------------------------------------------------------------------
    cvs2svn:cvs-rev = 1.2

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/AbstractFab.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Copied: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/BridgeBuilder.java (from r477434, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/BridgeBuilder.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/BridgeBuilder.java?view=diff&rev=477448&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/BridgeBuilder.java&r1=477434&p2=tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/BridgeBuilder.java&r2=477448
==============================================================================
    (empty)

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/BridgeBuilder.java
------------------------------------------------------------------------------
    cvs2svn:cvs-rev = 1.9

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/BridgeBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/BridgeBuilder.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Copied: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFabImpl.java (from r477434, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFabImpl.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFabImpl.java?view=diff&rev=477448&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFabImpl.java&r1=477434&p2=tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFabImpl.java&r2=477448
==============================================================================
    (empty)

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFabImpl.java
------------------------------------------------------------------------------
    cvs2svn:cvs-rev = 1.10

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFabImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFabImpl.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Copied: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryImpl.java (from r477434, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryImpl.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryImpl.java?view=diff&rev=477448&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryImpl.java&r1=477434&p2=tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryImpl.java&r2=477448
==============================================================================
    (empty)

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryImpl.java
------------------------------------------------------------------------------
    cvs2svn:cvs-rev = 1.10

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/ClassFactoryImpl.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Copied: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/CtClassSource.java (from r477434, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/CtClassSource.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/CtClassSource.java?view=diff&rev=477448&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/CtClassSource.java&r1=477434&p2=tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/CtClassSource.java&r2=477448
==============================================================================
    (empty)

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/CtClassSource.java
------------------------------------------------------------------------------
    cvs2svn:cvs-rev = 1.8

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/CtClassSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/CtClassSource.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Copied: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/RegistryShutdownHubImpl.java (from r477434, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/RegistryShutdownHubImpl.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/RegistryShutdownHubImpl.java?view=diff&rev=477448&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/RegistryShutdownHubImpl.java&r1=477434&p2=tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/RegistryShutdownHubImpl.java&r2=477448
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/RegistryShutdownHubImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/RegistryShutdownHubImpl.java Mon Nov 20 16:58:25 2006
@@ -14,14 +14,14 @@
 
 package org.apache.tapestry.internal.ioc.services;
 
-import static org.apache.tapestry.util.CollectionFactory.newThreadSafeList;
-
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.tapestry.internal.util.OneShotLock;
-import org.apache.tapestry.ioc.services.RegistryShutdownHub;
-import org.apache.tapestry.ioc.services.RegistryShutdownListener;
+import static org.apache.tapestry.util.CollectionFactory.newThreadSafeList;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.ioc.internal.util.OneShotLock;
+import org.apache.tapestry.ioc.services.RegistryShutdownHub;
+import org.apache.tapestry.ioc.services.RegistryShutdownListener;
 
 public class RegistryShutdownHubImpl implements RegistryShutdownHub
 {

Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java?view=diff&rev=477448&r1=477447&r2=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/RegistryBuilder.java Mon Nov 20 16:58:25 2006
@@ -14,23 +14,23 @@
 
 package org.apache.tapestry.ioc;
 
-import static org.apache.tapestry.util.CollectionFactory.newList;
-import static org.apache.tapestry.util.CollectionFactory.newMap;
-
-import java.lang.reflect.AnnotatedElement;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.tapestry.internal.ioc.DefaultModuleDefImpl;
-import org.apache.tapestry.internal.ioc.IOCMessages;
-import org.apache.tapestry.internal.ioc.LogSourceImpl;
-import org.apache.tapestry.internal.ioc.RegistryImpl;
-import org.apache.tapestry.internal.util.OneShotLock;
-import org.apache.tapestry.ioc.annotations.SubModule;
-import org.apache.tapestry.ioc.def.ModuleDef;
-import org.apache.tapestry.ioc.services.TapestryIOCModule;
+import static org.apache.tapestry.util.CollectionFactory.newList;
+import static org.apache.tapestry.util.CollectionFactory.newMap;
+
+import java.lang.reflect.AnnotatedElement;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.internal.ioc.DefaultModuleDefImpl;
+import org.apache.tapestry.internal.ioc.IOCMessages;
+import org.apache.tapestry.internal.ioc.LogSourceImpl;
+import org.apache.tapestry.internal.ioc.RegistryImpl;
+import org.apache.tapestry.ioc.annotations.SubModule;
+import org.apache.tapestry.ioc.def.ModuleDef;
+import org.apache.tapestry.ioc.internal.util.OneShotLock;
+import org.apache.tapestry.ioc.services.TapestryIOCModule;
 
 /**
  * Used to construct the IoC {@link org.apache.tapestry.ioc.Registry}. This class is <em>not</em>

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/DependencyNode.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/DependencyNode.java?view=auto&rev=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/DependencyNode.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/DependencyNode.java Mon Nov 20 16:58:25 2006
@@ -0,0 +1,146 @@
+// 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.util;
+
+import static org.apache.tapestry.util.CollectionFactory.newList;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.ioc.Orderable;
+
+/**
+ * Used by {@link org.apache.tapestry.internal.util.Orderer} to establish backward dependencies for
+ * {@link org.apache.tapestry.ioc.Orderable} objects.
+ * 
+ * @param <T>
+ */
+
+class DependencyNode<T>
+{
+    private final Log _log;
+
+    private final Orderable<T> _orderable;
+
+    private final List<DependencyNode<T>> _dependencies = newList();
+
+    DependencyNode(Log errorLog, Orderable<T> orderable)
+    {
+        _log = errorLog;
+        _orderable = orderable;
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder buffer = new StringBuilder(String.format("[%s", getId()));
+
+        boolean first = true;
+
+        for (DependencyNode<T> node : _dependencies)
+        {
+
+            buffer.append(first ? ": " : ", ");
+
+            buffer.append(node.toString());
+
+            first = false;
+        }
+
+        buffer.append("]");
+
+        return buffer.toString();
+    }
+
+    /**
+     * Returns the underlying {@link Orderable}'s id.
+     */
+    public String getId()
+    {
+        return _orderable.getId();
+    }
+
+    void addDependency(DependencyNode<T> node)
+    {
+        if (node.isReachable(this))
+        {
+            String message = UtilMessages.dependencyCycle(node, this);
+            _log.warn(message, null);
+            return;
+        }
+
+        // Make this node depend on the other node.
+        // That forces the other node's orderable
+        // to appear before this node's orderable.
+
+        _dependencies.add(node);
+    }
+
+    boolean isReachable(DependencyNode<T> node)
+    {
+        if (this == node)
+            return true;
+
+        // Quick fast pass for immediate dependencies
+
+        for (DependencyNode<T> d : _dependencies)
+        {
+            if (d == node)
+                return true;
+        }
+
+        // Slower second pass looks for
+        // indirect dependencies
+
+        for (DependencyNode<T> d : _dependencies)
+        {
+            if (d.isReachable(node))
+                return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns the {@link Orderable} objects for this node ordered based on dependencies.
+     */
+    List<Orderable<T>> getOrdered()
+    {
+        List<Orderable<T>> result = newList();
+
+        fillOrder(result);
+
+        return result;
+    }
+
+    private void fillOrder(List<Orderable<T>> list)
+    {
+        if (list.contains(_orderable))
+            return;
+
+        // Recusively add dependencies
+
+        for (DependencyNode<T> node : _dependencies)
+        {
+            node.fillOrder(list);
+        }
+
+        list.add(_orderable);
+    }
+
+}
\ No newline at end of file

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/OneShotLock.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/OneShotLock.java?view=auto&rev=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/OneShotLock.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/OneShotLock.java Mon Nov 20 16:58:25 2006
@@ -0,0 +1,58 @@
+// 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.internal.util;
+
+/**
+ * Logic for handling one shot semantics for classes; classes that include a method (or methods)
+ * that "locks down" the instance, to prevent it from being used again in the future.
+ */
+public class OneShotLock
+{
+    private boolean _lock;
+
+    /**
+     * Checks to see if the lock has been set (via {@link #lock()}).
+     * 
+     * @throws IllegalStateException
+     *             if the lock is set
+     */
+    public void check()
+    {
+        innerCheck();
+    }
+
+    private void innerCheck()
+    {
+        if (_lock)
+        {
+            // [0] is getStackTrace()
+            // [1] is innerCheck()
+            // [2] is check() or lock()
+            // [3] is caller of check() or lock()
+            
+            StackTraceElement element = Thread.currentThread().getStackTrace()[4];
+
+            throw new IllegalStateException(UtilMessages.oneShotLock(element));
+        }
+    }
+
+    /** Checks the lock, then sets it. */
+    public void lock()
+    {
+        innerCheck();
+
+        _lock = true;
+    }
+}

Copied: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/Orderer.java (from r477434, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/Orderer.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/Orderer.java?view=diff&rev=477448&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/Orderer.java&r1=477434&p2=tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/Orderer.java&r2=477448
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/Orderer.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/Orderer.java Mon Nov 20 16:58:25 2006
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.internal.util;
+package org.apache.tapestry.ioc.internal.util;
 
 import static org.apache.tapestry.util.CollectionFactory.newList;
 import static org.apache.tapestry.util.CollectionFactory.newMap;
@@ -27,6 +27,7 @@
 import org.apache.tapestry.ioc.IdMatcher;
 import org.apache.tapestry.ioc.OrIdMatcher;
 import org.apache.tapestry.ioc.Orderable;
+import org.apache.tapestry.ioc.internal.util.OneShotLock;
 
 /**
  * Used to order objects into an "execution" order. Each object must have a unique id. It may

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/Orderer.java
------------------------------------------------------------------------------
    cvs2svn:cvs-rev = 1.15

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/Orderer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/Orderer.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/UtilMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/UtilMessages.java?view=auto&rev=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/UtilMessages.java (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/util/UtilMessages.java Mon Nov 20 16:58:25 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.internal.util;
+
+import org.apache.tapestry.internal.MessagesImpl;
+import org.apache.tapestry.ioc.Messages;
+
+class UtilMessages {
+	private static final Messages MESSAGES = MessagesImpl
+			.forClass(UtilMessages.class);
+
+	static String oneShotLock(StackTraceElement element) {
+		return MESSAGES.format("one-shot-lock", element);
+	}
+
+	static String dependencyCycle(DependencyNode dependency, DependencyNode node) {
+		return MESSAGES.format("dependency-cycle", dependency.getId(), node
+				.getId());
+	}
+
+	static String duplicateOrderer(String id) {
+		return MESSAGES.format("duplicate-orderer", id);
+	}
+
+	static String constraintFormat(String constraint, String id) {
+		return MESSAGES.format("constraint-format", constraint, id);
+	}
+}

Added: tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/util/UtilStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/util/UtilStrings.properties?view=auto&rev=477448
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/util/UtilStrings.properties (added)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/util/UtilStrings.properties Mon Nov 20 16:58:25 2006
@@ -0,0 +1,19 @@
+# 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.
+
+unable-to-read-last-modified=Unable to read last modified time stamp of resource %s: %s
+dependency-cycle=Unable to add '%s' as a dependency of '%s', as that forms a dependency cycle ('%<s' depends on itself via '%1$s'). The dependency has been ignored.
+duplicate-orderer=Could not add object with duplicate id '%s'.  The duplicate object has been ignored.
+constraint-format=Could not parse ordering constraint '%s' (for '%s'). The constraint has been ignored.
+one-shot-lock=Method %s may no longer be invoked.

Copied: tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/util/OneShotLockSubject.java (from r477434, tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/OneShotLockSubject.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/util/OneShotLockSubject.java?view=diff&rev=477448&p1=tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/OneShotLockSubject.java&r1=477434&p2=tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/util/OneShotLockSubject.java&r2=477448
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/OneShotLockSubject.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/util/OneShotLockSubject.java Mon Nov 20 16:58:25 2006
@@ -15,9 +15,9 @@
 /**
  * 
  */
-package org.apache.tapestry.internal.util;
+package org.apache.tapestry.ioc.internal.util;
 
-import org.apache.tapestry.internal.util.OneShotLock;
+import org.apache.tapestry.ioc.internal.util.OneShotLock;
 
 /**
  * Evolved from a test for aspects + annotations to a test of a class that utilizeds OneShotLock as

Copied: tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/util/OneShotLockTest.java (from r477434, tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/OneShotLockTest.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/util/OneShotLockTest.java?view=diff&rev=477448&p1=tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/OneShotLockTest.java&r1=477434&p2=tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/util/OneShotLockTest.java&r2=477448
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/util/OneShotLockTest.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/util/OneShotLockTest.java Mon Nov 20 16:58:25 2006
@@ -12,12 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.internal.util;
+package org.apache.tapestry.ioc.internal.util;
 
-import org.apache.tapestry.test.BaseTestCase;
+import org.apache.tapestry.test.IOCTestCase;
 import org.testng.annotations.Test;
 
-public class OneShotLockTest extends BaseTestCase
+public class OneShotLockTest extends IOCTestCase
 {
     private static final String CLASS_NAME = OneShotLockSubject.class.getName();