You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2006/07/25 23:12:16 UTC
svn commit: r425525 - 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/def/
main/java/org/apach...
Author: hlship
Date: Tue Jul 25 14:12:14 2006
New Revision: 425525
URL: http://svn.apache.org/viewvc?rev=425525&view=rev
Log:
Implement unordered configurations and contributions.
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/BarneyModule.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/DecoratorList.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/FredModule.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/UnorderedNames.java
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ConfigurationType.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InternalRegistry.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/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/ServiceBuilderMethodInvoker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapper.java
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/def/ServiceDef.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvokerTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapperTest.java
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ConfigurationType.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ConfigurationType.java?rev=425525&r1=425524&r2=425525&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ConfigurationType.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ConfigurationType.java Tue Jul 25 14:12:14 2006
@@ -4,7 +4,7 @@
// 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
+// 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,
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImpl.java?rev=425525&r1=425524&r2=425525&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/DefaultModuleDefImpl.java Tue Jul 25 14:12:14 2006
@@ -82,12 +82,13 @@
private final String _moduleId;
- private final Map<Class, ConfigurationType> _contributorParameterToConfigurationType = newMap();
+ private final static Map<Class, ConfigurationType> PARAMETER_TYPE_TO_CONFIGURATION_TYPE = newMap();
+ static
{
- _contributorParameterToConfigurationType.put(MappedConfiguration.class, MAPPED);
- _contributorParameterToConfigurationType.put(OrderedConfiguration.class, ORDERED);
- _contributorParameterToConfigurationType.put(Configuration.class, UNORDERED);
+ PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(Configuration.class, UNORDERED);
+ PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(OrderedConfiguration.class, ORDERED);
+ PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(MappedConfiguration.class, MAPPED);
}
/**
@@ -214,7 +215,7 @@
for (Class parameterType : method.getParameterTypes())
{
- ConfigurationType thisParameter = _contributorParameterToConfigurationType
+ ConfigurationType thisParameter = PARAMETER_TYPE_TO_CONFIGURATION_TYPE
.get(parameterType);
if (thisParameter != null)
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=425525&r1=425524&r2=425525&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 Tue Jul 25 14:12:14 2006
@@ -15,6 +15,7 @@
package org.apache.tapestry.internal.ioc;
import java.lang.reflect.Method;
+import java.lang.reflect.Type;
import java.util.List;
import org.apache.hivemind.Messages;
@@ -201,5 +202,15 @@
{
return MESSAGES.format("contribution-wrong-value-type", new Object[]
{ serviceId, def, actualClass.getName(), expectedClass.getName() });
+ }
+
+ static String tooManyConfigurationParameters(Method method)
+ {
+ return MESSAGES.format("too-many-configuration-parameters", asString(method));
+ }
+
+ static String genericTypeNotSupported(Type type)
+ {
+ return MESSAGES.format("generic-type-not-supported", type);
}
}
Modified: 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=425525&r1=425524&r2=425525&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InternalRegistry.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InternalRegistry.java Tue Jul 25 14:12:14 2006
@@ -14,6 +14,7 @@
package org.apache.tapestry.internal.ioc;
+import java.util.Collection;
import java.util.List;
import org.apache.tapestry.ioc.LogSource;
@@ -82,4 +83,17 @@
* {@link ServiceDecorator}s.
*/
List<ServiceDecorator> findDecoratorsForService(ServiceDef serviceDef);
+
+ /**
+ * Builds up an unordered collection by invoking service contributor methods that target the
+ * service (from any module, unless the service is private).
+ *
+ * @param <T>
+ * @param serviceDef
+ * defines the service for which configuration data is being assembled
+ * @param objectType
+ * identifies the type of object allowed into the collection
+ * @return the final collection
+ */
+ <T> Collection<T> getUnorderedCollection(ServiceDef serviceDef, Class objectType);
}
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=425525&r1=425524&r2=425525&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 Tue Jul 25 14:12:14 2006
@@ -19,6 +19,7 @@
import java.util.Set;
import org.apache.tapestry.ioc.ServiceDecorator;
+import org.apache.tapestry.ioc.def.ContributionDef;
import org.apache.tapestry.ioc.def.DecoratorDef;
import org.apache.tapestry.ioc.def.ServiceDef;
@@ -87,4 +88,14 @@
* @return set of decorators, possibly empty (but not null)
*/
Set<DecoratorDef> findMatchingDecoratorDefs(ServiceDef serviceDef);
+
+ /** Returns the id that uniquely identifies this module within the registry. */
+ String getModuleId();
+
+ /** Finds any contributions that are targetted at the indicated service. */
+ Set<ContributionDef> getContributorDefsForService(String serviceId);
+
+ /** Assembles an unordered contribution by invoking any appropriate service contribution methods. */
+ <T> Collection<T> getUnorderedConfiguration(String serviceId, Class<T> objectType);
+
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java?rev=425525&r1=425524&r2=425525&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java Tue Jul 25 14:12:14 2006
@@ -24,9 +24,11 @@
import org.apache.tapestry.internal.annotations.SuppressNullCheck;
import org.apache.tapestry.ioc.IOCConstants;
import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ServiceCreatorResources;
import org.apache.tapestry.ioc.ServiceDecorator;
import org.apache.tapestry.ioc.ServiceLifecycle;
import org.apache.tapestry.ioc.ServiceResources;
+import org.apache.tapestry.ioc.def.ContributionDef;
import org.apache.tapestry.ioc.def.DecoratorDef;
import org.apache.tapestry.ioc.def.ModuleDef;
import org.apache.tapestry.ioc.def.ServiceDef;
@@ -202,7 +204,7 @@
ServiceLifecycle lifecycle = _registry.getServiceLifecycle(def.getServiceLifeycle());
- ServiceResources resources = new ServiceResourcesImpl(_registry, this, def, log);
+ ServiceCreatorResources resources = new ServiceResourcesImpl(_registry, this, def, log);
// Build up a stack of operations that will be needed to instantiate the service
// (by the proxy, at a later date).
@@ -344,6 +346,31 @@
// Let's hope that they aren't lying when they say that synchronized is now super cheap!
cf.addMethod(Modifier.PRIVATE | Modifier.SYNCHRONIZED, sig, builder.toString());
+ }
+
+ public String getModuleId()
+ {
+ return _moduleDef.getModuleId();
+ }
+
+ public Set<ContributionDef> getContributorDefsForService(String serviceId)
+ {
+ Set<ContributionDef> result = newSet();
+
+ for (ContributionDef def : _moduleDef.getContributionDefs())
+ {
+ if (def.getServiceId().equals(serviceId))
+ result.add(def);
+ }
+
+ return result;
+ }
+
+ public <T> Collection<T> getUnorderedConfiguration(String serviceId, Class<T> objectType)
+ {
+ ServiceDef def = _moduleDef.getServiceDef(serviceId);
+
+ return _registry.getUnorderedCollection(def, objectType);
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java?rev=425525&r1=425524&r2=425525&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java Tue Jul 25 14:12:14 2006
@@ -14,9 +14,6 @@
package org.apache.tapestry.internal.ioc;
-import static org.apache.tapestry.util.CollectionFactory.newList;
-import static org.apache.tapestry.util.CollectionFactory.newMap;
-
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -26,17 +23,23 @@
import org.apache.commons.logging.Log;
import org.apache.tapestry.internal.annotations.SuppressNullCheck;
import org.apache.tapestry.internal.util.Orderer;
+import org.apache.tapestry.ioc.Configuration;
import org.apache.tapestry.ioc.IOCUtilities;
import org.apache.tapestry.ioc.LogSource;
import org.apache.tapestry.ioc.Registry;
import org.apache.tapestry.ioc.ServiceDecorator;
import org.apache.tapestry.ioc.ServiceLifecycle;
+import org.apache.tapestry.ioc.ServiceLocator;
import org.apache.tapestry.ioc.ServiceResources;
+import org.apache.tapestry.ioc.def.ContributionDef;
import org.apache.tapestry.ioc.def.DecoratorDef;
import org.apache.tapestry.ioc.def.ModuleDef;
import org.apache.tapestry.ioc.def.ServiceDef;
import org.apache.tapestry.util.CollectionFactory;
+import static org.apache.tapestry.util.CollectionFactory.newList;
+import static org.apache.tapestry.util.CollectionFactory.newMap;
+
/**
* @author Howard M. Lewis Ship
*/
@@ -97,6 +100,63 @@
return module;
}
+ public <T> Collection<T> getUnorderedCollection(ServiceDef serviceDef, Class objectType)
+ {
+ final Collection<T> result = newList();
+
+ Configuration<T> configuration = new Configuration<T>()
+ {
+ public void add(T object)
+ {
+ result.add(object);
+ }
+
+ };
+
+ if (serviceDef.isPrivate())
+ {
+ String serviceId = serviceDef.getServiceId();
+
+ addToUnorderedConfiguration(
+ configuration,
+ objectType,
+ serviceDef,
+ locateModuleForService(serviceId));
+ }
+ else
+ {
+ for (Module m : _modules.values())
+ {
+ addToUnorderedConfiguration(configuration, objectType, serviceDef, m);
+ }
+ }
+
+ return result;
+ }
+
+ private <T> void addToUnorderedConfiguration(Configuration<T> configuration, Class objectType,
+ ServiceDef serviceDef, Module module)
+ {
+ String serviceId = serviceDef.getServiceId();
+ Set<ContributionDef> contributions = module.getContributorDefsForService(serviceId);
+
+ if (contributions.isEmpty())
+ return;
+
+ Log log = getLog(serviceId);
+
+ Object moduleBuilder = module.getModuleBuilder();
+ ServiceLocator locator = new ServiceResourcesImpl(this, module, serviceDef, log);
+
+ for (ContributionDef def : contributions)
+ {
+ Configuration<T> validating = new ValidatingConfigurationWrapper(serviceId, log,
+ objectType, def, configuration);
+
+ def.contribute(moduleBuilder, locator, validating);
+ }
+ }
+
// Seems like something that could be cached.
@SuppressNullCheck
public <T> T getService(Class<T> serviceInterface, Module module)
@@ -146,7 +206,6 @@
return result;
}
- // TODO: Real implementation
public List<ServiceDecorator> findDecoratorsForService(ServiceDef serviceDef)
{
Log log = getLog(serviceDef.getServiceId());
@@ -179,12 +238,14 @@
// the decorators module (important in terms of service visibility
// and abbreviated service ids).
- if (!moduleId.equals(decoratorModuleId))
+ if (!decoratorModuleId.equals(moduleId))
{
+ moduleId = decoratorModuleId;
+
Module module = _modules.get(moduleId);
moduleBuilder = module.getModuleBuilder();
+
resources = new ServiceResourcesImpl(this, module, serviceDef, log);
- moduleId = decoratorModuleId;
}
ServiceDecorator decorator = dd.createDecorator(moduleBuilder, resources);
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java?rev=425525&r1=425524&r2=425525&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java Tue Jul 25 14:12:14 2006
@@ -14,17 +14,25 @@
package org.apache.tapestry.internal.ioc;
-import static org.apache.tapestry.internal.ioc.IOCUtilities.calculateParametersForMethod;
-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.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ServiceCreatorResources;
import org.apache.tapestry.ioc.ServiceResources;
+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.internal.ioc.IOCUtilities.calculateParametersForMethod;
+import static org.apache.tapestry.util.CollectionFactory.newMap;
+
/**
* Basic implementation of {@link org.apache.tapestry.ioc.ServiceCreator} that handles invoking a
* method on the module builder, and figures out the correct parameters to pass into the annotated
@@ -40,14 +48,23 @@
private final Map<Class, Object> _parameterDefaults = newMap();
- private final ServiceResources _resources;
+ private final ServiceCreatorResources _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, Object moduleBuilder,
- ServiceResources resources)
+ ServiceCreatorResources resources)
{
_serviceId = resources.getServiceId();
_builderMethod = method;
@@ -62,6 +79,103 @@
}
/**
+ * 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;
+
+ switch (type)
+ {
+
+ case UNORDERED:
+
+ Class valueType = parameterizedType(_builderMethod.getGenericParameterTypes()[i]);
+ Collection configuration = _resources.getUnorderedConfiguration(valueType);
+
+ result.put(Collection.class, configuration);
+
+ break;
+
+ default:
+ throw new IllegalArgumentException(type + " not yet supported.");
+ }
+
+ }
+
+ return result;
+ }
+
+ /**
+ * 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 parameterizedType(Type type)
+ {
+ Class result = findParameterizedTypeFromGenericType(type);
+
+ if (result == null)
+ throw new IllegalArgumentException(IOCMessages.genericTypeNotSupported(type));
+
+ return result;
+ }
+
+ private static Class findParameterizedTypeFromGenericType(Type type)
+ {
+ // 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();
+ if (types.length != 1)
+ return null;
+
+ Type actualType = types[0];
+
+ return actualType instanceof Class ? (Class) actualType : null;
+
+ }
+
+ /**
* Invoked from the proxy to create the actual service implementation.
*/
public Object createService()
@@ -78,7 +192,7 @@
Object[] parameters = calculateParametersForMethod(
_builderMethod,
_resources,
- _parameterDefaults);
+ getParameterDefaultsWithConfigurations());
result = _builderMethod.invoke(_moduleBuilder, parameters);
}
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=425525&r1=425524&r2=425525&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 Tue Jul 25 14:12:14 2006
@@ -18,7 +18,7 @@
import org.apache.tapestry.internal.util.InternalUtils;
import org.apache.tapestry.ioc.ServiceCreator;
-import org.apache.tapestry.ioc.ServiceResources;
+import org.apache.tapestry.ioc.ServiceCreatorResources;
import org.apache.tapestry.ioc.def.ServiceDef;
/**
@@ -53,7 +53,7 @@
return _builderMethod;
}
- public ServiceCreator createServiceCreator(Object moduleBuilder, ServiceResources resources)
+ public ServiceCreator createServiceCreator(Object moduleBuilder, ServiceCreatorResources resources)
{
return new ServiceBuilderMethodInvoker(_builderMethod, moduleBuilder, resources);
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java?rev=425525&r1=425524&r2=425525&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java Tue Jul 25 14:12:14 2006
@@ -14,16 +14,25 @@
package org.apache.tapestry.internal.ioc;
+import java.util.Collection;
+
import org.apache.commons.logging.Log;
-import org.apache.tapestry.ioc.ServiceResources;
+import org.apache.tapestry.ioc.ServiceCreatorResources;
import org.apache.tapestry.ioc.def.ServiceDef;
+import static org.apache.tapestry.ioc.IOCUtilities.toQualifiedId;
+
/**
- * Implementation of {@link org.apache.tapestry.ioc.ServiceResources}.
+ * Implementation of {@link org.apache.tapestry.ioc.ServiceCreatorResources}. We just have one
+ * implementation that fills the purposes of methods that need a
+ * {@link org.apache.tapestry.ioc.ServiceResources} (which includes service decorator methods) as
+ * well as methods that need a {@link org.apache.tapestry.ioc.ServiceCreatorResources} (which is
+ * just service builder methods). Since it is most commonly used for the former, we'll just leave
+ * the name as ServiceResourcesImpl.
*
* @author Howard M. Lewis Ship
*/
-public class ServiceResourcesImpl implements ServiceResources
+public class ServiceResourcesImpl implements ServiceCreatorResources
{
private final InternalRegistry _registry;
@@ -33,7 +42,8 @@
private Log _log;
- public ServiceResourcesImpl(InternalRegistry registry, Module module, ServiceDef serviceDef, Log log)
+ public ServiceResourcesImpl(InternalRegistry registry, Module module, ServiceDef serviceDef,
+ Log log)
{
_registry = registry;
_module = module;
@@ -53,7 +63,10 @@
public <T> T getService(String serviceId, Class<T> serviceInterface)
{
- return _registry.getService(serviceId, serviceInterface, _module);
+ return _registry.getService(
+ toQualifiedId(_module.getModuleId(), serviceId),
+ serviceInterface,
+ _module);
}
public <T> T getService(Class<T> serviceInterface)
@@ -66,4 +79,8 @@
return _log;
}
+ public <T> Collection<T> getUnorderedConfiguration(Class<T> objectType)
+ {
+ return _module.getUnorderedConfiguration(_serviceDef.getServiceId(), objectType);
+ }
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapper.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapper.java?rev=425525&r1=425524&r2=425525&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapper.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapper.java Tue Jul 25 14:12:14 2006
@@ -15,6 +15,7 @@
package org.apache.tapestry.internal.ioc;
import org.apache.commons.logging.Log;
+import org.apache.tapestry.internal.annotations.SuppressNullCheck;
import org.apache.tapestry.ioc.Configuration;
import org.apache.tapestry.ioc.def.ContributionDef;
@@ -23,7 +24,8 @@
*
* @author Howard M. Lewis Ship
*/
-public class ValidatingConfigurationWrapper implements Configuration
+@SuppressNullCheck
+public class ValidatingConfigurationWrapper<T> implements Configuration<T>
{
private final String _serviceId;
@@ -47,13 +49,15 @@
_expectedClass = expectedClass;
}
- public void add(Object object)
+ 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 (!_expectedClass.isInstance(object))
{
Modified: 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=425525&r1=425524&r2=425525&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java Tue Jul 25 14:12:14 2006
@@ -69,14 +69,14 @@
setReturnValue(decorators);
}
- protected final Module newModule()
- {
- return newMock(Module.class);
- }
-
protected void trainFindDecoratorsForService(InternalRegistry registry)
{
registry.findDecoratorsForService(EasyMock.isA(ServiceDef.class));
setReturnValue(CollectionFactory.newList());
+ }
+
+ protected final InternalRegistry newInternalRegistry()
+ {
+ return newMock(InternalRegistry.class);
}
}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java?rev=425525&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java Tue Jul 25 14:12:14 2006
@@ -0,0 +1,30 @@
+// 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.Collection;
+
+/**
+ * Extends {@link org.apache.tapestry.ioc.ServiceResources} with additional methods needed only by
+ * the service builder method, related to accessing a service's configuration.
+ *
+ * @author Howard M. Lewis Ship
+ */
+public interface ServiceCreatorResources extends ServiceResources
+{
+ <T> Collection<T> getUnorderedConfiguration(Class<T> objectType);
+
+ // More to come!
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java?rev=425525&r1=425524&r2=425525&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java Tue Jul 25 14:12:14 2006
@@ -15,7 +15,7 @@
package org.apache.tapestry.ioc.def;
import org.apache.tapestry.ioc.ServiceCreator;
-import org.apache.tapestry.ioc.ServiceResources;
+import org.apache.tapestry.ioc.ServiceCreatorResources;
/**
* Service definition derived, by default, from a service builder method.
@@ -30,10 +30,10 @@
* @param moduleBuilder
* the module builder instance for the module containing the service
* @param resources
- * used to resolve dependencies of the service
+ * used to resolve dependencies of the service, or access its configuration
* @return an object that can (later) be used to instantiate the service itself
*/
- ServiceCreator createServiceCreator(Object moduleBuilder, ServiceResources resources);
+ ServiceCreator createServiceCreator(Object moduleBuilder, ServiceCreatorResources resources);
/** Returns the fully qualified service id, derived from the method name. */
String getServiceId();
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java?rev=425525&r1=425524&r2=425525&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 Tue Jul 25 14:12:14 2006
@@ -31,15 +31,19 @@
import org.apache.commons.logging.Log;
import org.apache.hivemind.Resource;
import org.apache.tapestry.internal.annotations.SuppressNullCheck;
+import org.apache.tapestry.internal.ioc.Module;
import org.apache.tapestry.ioc.Configuration;
import org.apache.tapestry.ioc.LogSource;
import org.apache.tapestry.ioc.MappedConfiguration;
import org.apache.tapestry.ioc.OrderedConfiguration;
import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ServiceCreatorResources;
import org.apache.tapestry.ioc.ServiceDecorator;
import org.apache.tapestry.ioc.ServiceLocator;
import org.apache.tapestry.ioc.ServiceResources;
import org.apache.tapestry.ioc.def.ContributionDef;
+import org.apache.tapestry.ioc.def.DecoratorDef;
+import org.apache.tapestry.ioc.def.ModuleDef;
import org.apache.tapestry.ioc.def.ServiceDef;
import org.apache.tapestry.model.MutableComponentModel;
import org.apache.tapestry.transform.ClassTransformation;
@@ -280,6 +284,38 @@
protected final ContributionDef newContributionDef()
{
return newMock(ContributionDef.class);
+ }
+
+ protected final ServiceCreatorResources newServiceCreatorResources()
+ {
+ return newMock(ServiceCreatorResources.class);
+ }
+
+ protected final Module newModule()
+ {
+ return newMock(Module.class);
+ }
+
+ protected final void trainGetModuleId(ModuleDef def, String moduleId)
+ {
+ def.getModuleId();
+ setReturnValue(moduleId);
+ }
+
+ protected final ModuleDef newModuleDef()
+ {
+ return newMock(ModuleDef.class);
+ }
+
+ protected final void trainMatches(DecoratorDef decoratorDef, ServiceDef serviceDef, boolean matches)
+ {
+ decoratorDef.matches(serviceDef);
+ setReturnValue(matches);
+ }
+
+ protected final DecoratorDef newDecoratorDef()
+ {
+ return newMock(DecoratorDef.class);
}
}
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=425525&r1=425524&r2=425525&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 Tue Jul 25 14:12:14 2006
@@ -49,10 +49,16 @@
too-many-contribution-parameters=Service contribution method {0} contains more than one parameter of type Configuration, \
OrderedConfiguration, or MappedConfiguration. Exactly one such parameter is required for a service contribution method. \
The method has been ignored.
+too-many-configuration-parameters=Service builder method {0} contains more than one parameter of type \
+ Collection, List, or Map. Parameters of this type are the way in which service configuration values, \
+ collected from service contributor methods, are provided to the service builder. \
+ Services are only allowed a single configuration. Unexpected results or failures may occur.
no-contribution-parameter=Service contribution method {0} does not contain a parameter of type \
Configuration, OrderedConfiguration or MappedConfiguration. This parameter is how the method \
make contributions into the service's configuration. The method has been ignored.
contribution-method-error=Error invoking service contribution method {0}: {1}
contribution-was-null=Service contribution (to service ''{0}'', by {1}) was null and has been ignored.
contribution-wrong-value-type=Service contribution (to service ''{0}'', by {1}) was an instance of {2}, \
- but {3} was expected. The contribution has been ignored.
\ No newline at end of file
+ but {3} was expected. The contribution has been ignored.
+generic-type-not-supported=Generic type ''{0}'' is not supported. Only simple parameterized lists are \
+ supported.
\ No newline at end of file
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java?rev=425525&r1=425524&r2=425525&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java Tue Jul 25 14:12:14 2006
@@ -40,7 +40,7 @@
@Test
public void get_service_by_id_exists()
{
- InternalRegistry registry = newMock(InternalRegistry.class);
+ InternalRegistry registry = newInternalRegistry();
Log log = newLog();
ModuleDef moduleDef = new DefaultModuleDefImpl(ModuleImplTestModule.class, log);
@@ -77,7 +77,7 @@
@Test
public void get_service_by_id_private()
{
- InternalRegistry registry = newMock(InternalRegistry.class);
+ InternalRegistry registry = newInternalRegistry();
Log log = newLog();
ModuleDef moduleDef = new DefaultModuleDefImpl(ModuleImplTestModule.class, log);
@@ -116,7 +116,7 @@
@Test
public void get_service_by_id_private_wrong_module()
{
- InternalRegistry registry = newMock(InternalRegistry.class);
+ InternalRegistry registry = newInternalRegistry();
Log log = newLog();
ModuleDef moduleDef = new DefaultModuleDefImpl(ModuleImplTestModule.class, log);
@@ -143,7 +143,7 @@
@Test
public void find_service_ids_for_interface()
{
- InternalRegistry registry = newMock(InternalRegistry.class);
+ InternalRegistry registry = newInternalRegistry();
Log log = newLog();
ModuleDef moduleDef = new DefaultModuleDefImpl(ModuleImplTestModule.class, log);
@@ -169,7 +169,7 @@
@Test
public void find_decorator_defs_for_service()
{
- InternalRegistry registry = newMock(InternalRegistry.class);
+ InternalRegistry registry = newInternalRegistry();
ServiceDef serviceDef = newServiceDef();
DecoratorDef def1 = newDecoratorDef();
DecoratorDef def2 = newDecoratorDef();
@@ -198,20 +198,21 @@
verify();
}
- protected ModuleDef newModuleDef()
+ @Test
+ public void get_module_id()
{
- return newMock(ModuleDef.class);
- }
+ InternalRegistry registry = newInternalRegistry();
+ ModuleDef def = newModuleDef();
- protected void trainMatches(DecoratorDef decoratorDef, ServiceDef serviceDef, boolean matches)
- {
- decoratorDef.matches(serviceDef);
- setReturnValue(matches);
- }
+ trainGetModuleId(def, "foo.bar");
- protected final DecoratorDef newDecoratorDef()
- {
- return newMock(DecoratorDef.class);
+ replay();
+
+ Module module = new ModuleImpl(registry, def);
+
+ assertEquals(module.getModuleId(), "foo.bar");
+
+ verify();
}
private Registry buildRegistry()
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvokerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvokerTest.java?rev=425525&r1=425524&r2=425525&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvokerTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvokerTest.java Tue Jul 25 14:12:14 2006
@@ -15,15 +15,21 @@
package org.apache.tapestry.internal.ioc;
import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.tapestry.internal.test.InternalBaseTestCase;
import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ServiceCreatorResources;
import org.apache.tapestry.ioc.ServiceResources;
import org.apache.tapestry.ioc.annotations.InjectService;
import org.testng.Assert;
import org.testng.annotations.Test;
+import static org.apache.tapestry.internal.ioc.ServiceBuilderMethodInvoker.parameterizedType;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertSame;
@@ -46,10 +52,12 @@
private FoeService _expectedFoe;
+ private Object _expectedConfiguration;
+
@Test
public void noargs_method()
{
- ServiceResources resources = newServiceResources();
+ ServiceCreatorResources resources = newServiceCreatorResources();
Log log = newLog();
_fie = newFieService();
@@ -69,7 +77,7 @@
verify();
}
- private void trainForConstructor(ServiceResources resources, Log log)
+ private void trainForConstructor(ServiceCreatorResources resources, Log log)
{
trainGetServiceId(resources, SERVICE_ID);
@@ -82,7 +90,7 @@
public void method_with_args()
{
Method method = findMethod("build_args");
- ServiceResources resources = newServiceResources();
+ ServiceCreatorResources resources = newServiceCreatorResources();
Log log = newLog();
@@ -113,7 +121,7 @@
@Test
public void injected_service_method()
{
- ServiceResources resources = newServiceResources();
+ ServiceCreatorResources resources = newServiceCreatorResources();
Log log = newLog();
_fie = newFieService();
@@ -137,6 +145,41 @@
verify();
}
+ @Test
+ public void injected_unordered_collection()
+ {
+ ServiceCreatorResources resources = newServiceCreatorResources();
+ Log log = newLog();
+
+ _fie = newFieService();
+ _expectedConfiguration = newMock(Collection.class);
+
+ trainForConstructor(resources, log);
+
+ trainIsDebugEnabled(log, false);
+
+ resources.getUnorderedConfiguration(Runnable.class);
+ setReturnValue(_expectedConfiguration);
+
+ replay();
+
+ ServiceCreator sc = new ServiceBuilderMethodInvoker(
+ findMethod("buildWithUnorderedConfiguration"), this, resources);
+
+ Object actual = sc.createService();
+
+ assertSame(actual, _fie);
+
+ verify();
+ }
+
+ public FieService buildWithUnorderedConfiguration(Collection<Runnable> configuration)
+ {
+ assertSame(configuration, _expectedConfiguration);
+
+ return _fie;
+ }
+
private FoeService newFoe()
{
return newFoeService();
@@ -145,7 +188,7 @@
@Test
public void builder_method_returns_null()
{
- ServiceResources resources = newServiceResources();
+ ServiceCreatorResources resources = newServiceCreatorResources();
Log log = newLog();
_fie = null;
@@ -176,7 +219,7 @@
@Test
public void builder_method_failed()
{
- ServiceResources resources = newServiceResources();
+ ServiceCreatorResources resources = newServiceCreatorResources();
Log log = newLog();
_fie = null;
@@ -214,7 +257,7 @@
{
Method method = findMethod("build_auto");
- ServiceResources resources = newServiceResources();
+ ServiceCreatorResources resources = newServiceCreatorResources();
Log log = newLog();
_fie = newFieService();
@@ -235,6 +278,63 @@
verify();
assertSame(actual, _fie);
+ }
+
+ @Test
+ public void parameterized_type_of_generic_parameter()
+ {
+ Method m = findMethod("methodWithParameterizedList");
+
+ assertEquals(m.getParameterTypes()[0], List.class);
+ Type type = m.getGenericParameterTypes()[0];
+
+ assertEquals(type.toString(), "java.util.List<java.lang.Runnable>");
+ assertEquals(parameterizedType(type), Runnable.class);
+ }
+
+ public void methodWithParameterizedList(List<Runnable> list)
+ {
+ }
+
+ @Test
+ public void parameterized_type_of_nongeneric_parameter()
+ {
+ Method m = findMethod("methodWithList");
+
+ assertEquals(m.getParameterTypes()[0], List.class);
+ Type type = m.getGenericParameterTypes()[0];
+
+ assertEquals(type.toString(), "interface java.util.List");
+ assertEquals(parameterizedType(type), Object.class);
+ }
+
+ public void methodWithList(List list)
+ {
+
+ }
+
+ @Test
+ public void parameterize_type_for_non_supported_type()
+ {
+ Method m = findMethod("methodWithWildcardList");
+
+ assertEquals(m.getParameterTypes()[0], List.class);
+ Type type = m.getGenericParameterTypes()[0];
+
+ try
+ {
+ parameterizedType(type);
+ unreachable();
+ }
+ catch (IllegalArgumentException ex)
+ {
+ assertEquals(ex.getMessage(), IOCMessages.genericTypeNotSupported(type));
+ }
+ }
+
+ public void methodWithWildcardList(List<? super ArrayList> list)
+ {
+
}
private FoeService newFoeService()
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapperTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapperTest.java?rev=425525&r1=425524&r2=425525&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapperTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ValidatingConfigurationWrapperTest.java Tue Jul 25 14:12:14 2006
@@ -45,6 +45,62 @@
verify();
}
+ @Test
+ public void null_contribution()
+ {
+ Log log = newLog();
+ Configuration configuration = newConfiguration();
+ ContributionDef def = new ContributionDefImpl("foo.Bar",
+ findMethod("contributeUnorderedNull"));
+
+ log.warn(IOCMessages.contributionWasNull("foo.Bar", def));
+
+ replay();
+
+ Configuration wrapper = new ValidatingConfigurationWrapper("foo.Bar", log, Runnable.class,
+ def, configuration);
+
+ wrapper.add(null);
+
+ verify();
+ }
+
+ @Test
+ public void wrong_type_of_contribution()
+ {
+ Log log = newLog();
+ Configuration configuration = newConfiguration();
+ ContributionDef def = new ContributionDefImpl("foo.Bar",
+ findMethod("contributeUnorderedNull"));
+
+ log.warn(IOCMessages.contributionWrongValueType(
+ "foo.Bar",
+ def,
+ String.class,
+ Runnable.class));
+
+ replay();
+
+ Configuration wrapper = new ValidatingConfigurationWrapper("foo.Bar", log, Runnable.class,
+ def, configuration);
+
+ wrapper.add("runnable");
+
+ verify();
+ }
+
+ // Just a placeholder to give the errors something to report about
+
+ public void contributeUnorderedNull()
+ {
+
+ }
+
+ public void contributeWrongType()
+ {
+
+ }
+
private Runnable newRunnable()
{
return newMock(Runnable.class);
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/BarneyModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/BarneyModule.java?rev=425525&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/BarneyModule.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/BarneyModule.java Tue Jul 25 14:12:14 2006
@@ -0,0 +1,71 @@
+// 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.List;
+
+import org.apache.tapestry.annotations.Match;
+import org.apache.tapestry.ioc.annotations.After;
+import org.apache.tapestry.ioc.annotations.Contribute;
+import org.apache.tapestry.ioc.annotations.Id;
+
+import static org.apache.tapestry.util.CollectionFactory.newList;
+
+/**
+ * Module used to demonstrate decorator ordering.
+ *
+ * @author Howard M. Lewis Ship
+ */
+
+@Id("barney")
+public class BarneyModule
+{
+ @Match("fred.*")
+ @After("fred.Beta")
+ public Object decorateGamma(Object delegate, DecoratorList list)
+ {
+ list.add("gamma");
+
+ return null;
+ }
+
+ /**
+ * Put DecoratorList in module barney, where so it won't accidentally be decorated (which
+ * recusively builds the service, and is caught as a failure).
+ */
+ public DecoratorList buildDecoratorList()
+ {
+ return new DecoratorList()
+ {
+ private List<String> _names = newList();
+
+ public void add(String name)
+ {
+ _names.add(name);
+ }
+
+ public List<String> getNames()
+ {
+ return _names;
+ }
+ };
+ }
+
+ @Contribute("fred.UnorderedNames")
+ public void contributeGamma(Configuration<String> configuration)
+ {
+ configuration.add("Gamma");
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/DecoratorList.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/DecoratorList.java?rev=425525&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/DecoratorList.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/DecoratorList.java Tue Jul 25 14:12:14 2006
@@ -0,0 +1,29 @@
+// 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.List;
+
+/**
+ * Used to track the order in which decorators are invoked.
+ *
+ * @author Howard M. Lewis Ship
+ */
+public interface DecoratorList
+{
+ void add(String name);
+
+ List<String> getNames();
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/FredModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/FredModule.java?rev=425525&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/FredModule.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/FredModule.java Tue Jul 25 14:12:14 2006
@@ -0,0 +1,125 @@
+// 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.Collection;
+
+import org.apache.tapestry.annotations.Match;
+import org.apache.tapestry.ioc.annotations.Before;
+import org.apache.tapestry.ioc.annotations.Contribute;
+import org.apache.tapestry.ioc.annotations.Id;
+import org.apache.tapestry.ioc.annotations.InjectService;
+import org.apache.tapestry.ioc.annotations.Private;
+
+/**
+ * Module used to demonstrate decorator ordering.
+ *
+ * @author Howard M. Lewis Ship
+ */
+@Id("fred")
+public class FredModule
+{
+
+ /**
+ * Doesn't matter what the service does, we just want to verify that the decorators are invoked
+ * in the order we expect.
+ */
+ public Runnable buildFred()
+ {
+ return new Runnable()
+ {
+ public void run()
+ {
+ }
+ };
+ }
+
+ @Private
+ public Runnable buildPrivateFred()
+ {
+ return buildFred();
+ }
+
+ /** A public alias of a private service. */
+ public Runnable buildPrivateFredAlias(@InjectService("PrivateFred")
+ Runnable privateFred)
+ {
+ return privateFred;
+ }
+
+ @Match("fred.*")
+ @Before("Beta")
+ public Object decorateAlpha(Object delegate, DecoratorList list)
+ {
+ list.add("alpha");
+
+ return null;
+ }
+
+ @Match("fred.*")
+ public Object decorateBeta(Object delegate, DecoratorList list)
+ {
+ list.add("beta");
+
+ return null;
+ }
+
+ public UnorderedNames buildUnorderedNames(final Collection<String> configuration)
+ {
+ return new UnorderedNames()
+ {
+
+ public Collection<String> getNames()
+ {
+ return configuration;
+ }
+
+ };
+ }
+
+ public void contributeUnorderedNames(Configuration<String> configuration)
+ {
+ configuration.add("UnorderedNames");
+ }
+
+ @Contribute("UnorderedNames")
+ public void contributeBeta(Configuration<String> configuration)
+ {
+ configuration.add("Beta");
+ }
+
+ @Private
+ public UnorderedNames buildPrivateUnorderedNames(final Collection<String> configuration)
+ {
+ return buildUnorderedNames(configuration);
+ }
+
+ public void contributePrivateUnorderedNames(Configuration<String> configuration)
+ {
+ configuration.add("PrivateUnorderedNames");
+ }
+
+ @Contribute("PrivateUnorderedNames")
+ public void contributeOmega(Configuration<String> configuration)
+ {
+ configuration.add("Omega");
+ }
+
+ public UnorderedNames buildPrivateUnorderedNamesAlias(@InjectService("PrivateUnorderedNames")
+ UnorderedNames privateService)
+ {
+ return privateService;
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java?rev=425525&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java Tue Jul 25 14:12:14 2006
@@ -0,0 +1,127 @@
+// 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.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.tapestry.internal.ioc.TapestryIOCModule;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.util.CollectionFactory;
+import org.testng.annotations.Test;
+
+import static org.apache.tapestry.util.CollectionFactory.newList;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * A few tests that are easiest (or even just possible) by building a Registry and trying out a few
+ * things.
+ *
+ * @author Howard M. Lewis Ship
+ */
+public class IntegrationTest extends InternalBaseTestCase
+{
+ private Registry buildRegistry()
+ {
+ RegistryBuilder builder = new RegistryBuilder();
+ builder.add(TapestryIOCModule.class, FredModule.class, BarneyModule.class);
+
+ return builder.build();
+ }
+
+ /**
+ * Along the way, we also test a few other things, such as decorator matching and automatic
+ * dependency resolution.
+ */
+ @Test
+ public void public_service_decorator_order()
+ {
+ Registry r = buildRegistry();
+
+ Runnable service = r.getService("fred.Fred", Runnable.class);
+
+ // Force creation
+
+ service.run();
+
+ List<String> names = r.getService(DecoratorList.class).getNames();
+
+ // Note that the order of invocation appears backwards, since we build back-to-front
+
+ assertEquals(names, Arrays.asList("gamma", "beta", "alpha"));
+ }
+
+ /**
+ * Along the way, we are demonstrating that decorators can target multiple services within a
+ * module, and can target services in other modules. The main point, though, is the difference
+ * between a private and a public service in terms of decoration.
+ */
+ @Test
+ public void private_service_decorator_order()
+ {
+ Registry r = buildRegistry();
+
+ Runnable service = r.getService("fred.PrivateFredAlias", Runnable.class);
+
+ // Force creation
+
+ service.run();
+
+ List<String> names = r.getService(DecoratorList.class).getNames();
+
+ // The trick here is that the public service (PrivateFredAlias) was decorated first with the
+ // full set (the same as the previous test), then the private service (PrivateFred) was
+ // decorated just with decorators from module fred.
+
+ assertEquals(names, Arrays.asList("gamma", "beta", "alpha", "beta", "alpha"));
+ }
+
+ @Test
+ public void public_service_unordered_configuration()
+ {
+ Registry r = buildRegistry();
+
+ UnorderedNames service = r.getService("fred.UnorderedNames", UnorderedNames.class);
+
+ List<String> names = sortedNames(service);
+
+ assertEquals(names, Arrays.asList("Beta", "Gamma", "UnorderedNames"));
+ }
+
+ @Test
+ public void private_service_unordered_configuration()
+ {
+ Registry r = buildRegistry();
+
+ UnorderedNames service = r.getService(
+ "fred.PrivateUnorderedNamesAlias",
+ UnorderedNames.class);
+
+ List<String> names = sortedNames(service);
+
+ assertEquals(names, Arrays.asList("Omega", "PrivateUnorderedNames"));
+
+ }
+
+ private List<String> sortedNames(UnorderedNames service)
+ {
+ List<String> names = newList(service.getNames());
+
+ Collections.sort(names);
+ return names;
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/UnorderedNames.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/UnorderedNames.java?rev=425525&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/UnorderedNames.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/UnorderedNames.java Tue Jul 25 14:12:14 2006
@@ -0,0 +1,27 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.ioc;
+
+import java.util.Collection;
+
+/**
+ * Used for testing of unordered contributions. The names are contributed in from multiple modules.
+ *
+ * @author Howard M. Lewis Ship
+ */
+public interface UnorderedNames
+{
+ public Collection<String> getNames();
+}