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 2011/10/22 00:08:11 UTC
svn commit: r1187574 - in /tapestry/tapestry5/trunk:
tapestry-core/src/test/java/org/apache/tapestry5/internal/test/
tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/
tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/
tapestry-ioc/src/...
Author: hlship
Date: Fri Oct 21 22:08:10 2011
New Revision: 1187574
URL: http://svn.apache.org/viewvc?rev=1187574&view=rev
Log:
TAP5-546: ObjectLocator.getService(Class) should be expanded to pass a varargs of marker annotation types
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ObjectLocator.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/Marker.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ObjectLocatorImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryWrapper.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/MasterObjectProvider.java
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/IOCInternalTestCase.java
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java?rev=1187574&r1=1187573&r2=1187574&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java Fri Oct 21 22:08:10 2011
@@ -44,6 +44,7 @@ import org.testng.annotations.AfterSuite
import org.testng.annotations.BeforeSuite;
import java.io.*;
+import java.lang.annotation.Annotation;
import static org.easymock.EasyMock.isA;
@@ -90,7 +91,7 @@ public class InternalBaseTestCase extend
return registry.getObject(objectType, annotationProvider);
}
- public final <T> T getService(Class<T> serviceInterface)
+ public final <T> T getService(Class<T> serviceInterface, Class<? extends Annotation>... markerTypes)
{
return registry.getService(serviceInterface);
}
@@ -171,7 +172,7 @@ public class InternalBaseTestCase extend
}
protected final void train_resolvePageClassNameToPageName(ComponentClassResolver resolver, String pageClassName,
- String pageName)
+ String pageName)
{
expect(resolver.resolvePageClassNameToPageName(pageClassName)).andReturn(pageName);
}
@@ -245,7 +246,8 @@ public class InternalBaseTestCase extend
expect(cache.get(pageName)).andReturn(page).atLeastOnce();
}
- protected final LinkCreationListener2 mockLinkCreationListener2() {
+ protected final LinkCreationListener2 mockLinkCreationListener2()
+ {
return newMock(LinkCreationListener2.class);
}
@@ -274,8 +276,7 @@ public class InternalBaseTestCase extend
* leading/trailing
* whitespace.
*
- * @param file
- * trim each line of whitespace
+ * @param file trim each line of whitespace
*/
protected final String readFile(String file) throws Exception
{
@@ -309,7 +310,7 @@ public class InternalBaseTestCase extend
}
protected final void train_canonicalizePageName(ComponentClassResolver resolver, String pageName,
- String canonicalized)
+ String canonicalized)
{
expect(resolver.canonicalizePageName(pageName)).andReturn(canonicalized);
}
@@ -370,13 +371,13 @@ public class InternalBaseTestCase extend
}
protected final void train_getPropertyAdapter(ClassPropertyAdapter classPropertyAdapter, String propertyName,
- PropertyAdapter propertyAdapter)
+ PropertyAdapter propertyAdapter)
{
expect(classPropertyAdapter.getPropertyAdapter(propertyName)).andReturn(propertyAdapter).atLeastOnce();
}
protected final void train_getAdapter(PropertyAccess access, Object object,
- ClassPropertyAdapter classPropertyAdapter)
+ ClassPropertyAdapter classPropertyAdapter)
{
expect(access.getAdapter(object)).andReturn(classPropertyAdapter);
}
@@ -397,7 +398,7 @@ public class InternalBaseTestCase extend
}
protected final void train_setLocaleFromLocaleName(LocalizationSetter localizationSetter, String localeName,
- boolean recognized)
+ boolean recognized)
{
expect(localizationSetter.setLocaleFromLocaleName(localeName)).andReturn(recognized);
}
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ObjectLocator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ObjectLocator.java?rev=1187574&r1=1187573&r2=1187574&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ObjectLocator.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ObjectLocator.java Fri Oct 21 22:08:10 2011
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2010 The Apache Software Foundation
+// Copyright 2006, 2007, 2010, 2011 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.
@@ -17,6 +17,8 @@ package org.apache.tapestry5.ioc;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.services.MasterObjectProvider;
+import java.lang.annotation.Annotation;
+
/**
* Defines an object which can provide access to services defined within a {@link org.apache.tapestry5.ioc.Registry}, or
* to objects or object instances available by other means. Services are accessed via service id, or
@@ -32,50 +34,43 @@ public interface ObjectLocator
* interface as the actual service, and is used to instantiate the actual service only as needed
* (this is
* transparent to the application).
- *
+ *
* @param <T>
- * @param serviceId
- * unique Service id used to locate the service object (may contain <em>symbols</em>,
- * which
- * will be expanded), case is ignored
- * @param serviceInterface
- * the interface implemented by the service (or an interface extended by the service
- * interface)
+ * @param serviceId unique Service id used to locate the service object (may contain <em>symbols</em>,
+ * which
+ * will be expanded), case is ignored
+ * @param serviceInterface the interface implemented by the service (or an interface extended by the service
+ * interface)
* @return the service instance
- * @throws RuntimeException
- * if the service is not defined, or if an error occurs instantiating it
+ * @throws RuntimeException if the service is not defined, or if an error occurs instantiating it
*/
<T> T getService(String serviceId, Class<T> serviceInterface);
/**
- * Locates a service given just a service interface. A single service must implement the service
- * interface (which
- * can be hard to guarantee). The search takes into account inheritance of the service interface
+ * Locates a service given a service interface and (optionally) some marker annotation types. A single service must implement the service
+ * interface (which * can be hard to guarantee) and by marked by all the marker types. The search takes into account inheritance of the service interface
* (not the service <em>implementation</em>), which may result in a failure due to extra
- * matches.
- *
- * @param <T>
- * @param serviceInterface
- * the interface the service implements
+ * matches. The ability to specify marker annotation types was added in 5.3
+ *
+ * @param serviceInterface the interface the service implements
+ * @param markerTypes
* @return the service's proxy
- * @throws RuntimeException
- * if the service does not exist (this is considered programmer error), or multiple
- * services directly implement, or extend from, the service interface
+ * @throws RuntimeException if the service does not exist (this is considered programmer error), or multiple
+ * services directly implement, or extend from, the service interface
+ * @see org.apache.tapestry5.ioc.annotations.Marker
*/
- <T> T getService(Class<T> serviceInterface);
+ <T> T getService(Class<T> serviceInterface, Class<? extends Annotation>... markerTypes);
/**
* Obtains an object indirectly, using the {@link org.apache.tapestry5.ioc.services.MasterObjectProvider} service.
- *
- * @param objectType
- * the type of object to be returned
- * @param annotationProvider
- * provides access to annotations on the field or parameter for which a value is to
- * be
- * obtained, which may be utilized in selecting an appropriate object, use
- * <strong>null</strong> when annotations are not available (in which case, selection
- * will
- * be based only on the object type)
+ *
+ * @param objectType the type of object to be returned
+ * @param annotationProvider provides access to annotations on the field or parameter for which a value is to
+ * be
+ * obtained, which may be utilized in selecting an appropriate object, use
+ * <strong>null</strong> when annotations are not available (in which case, selection
+ * will
+ * be based only on the object type)
* @param <T>
* @return the requested object
* @see ObjectProvider
@@ -89,13 +84,11 @@ public interface ObjectLocator
* an arbitrary object. In the former case, many <em>service resources</em> are also available for injection, not
* just dependencies or objects provided via
* {@link MasterObjectProvider#provide(Class, AnnotationProvider, ObjectLocator, boolean)}.
- *
+ *
* @param <T>
- * @param clazz
- * the type of object to instantiate
+ * @param clazz the type of object to instantiate
* @return the instantiated instance
- * @throws RuntimeException
- * if the autobuild fails
+ * @throws RuntimeException if the autobuild fails
* @see MasterObjectProvider
*/
<T> T autobuild(Class<T> clazz);
@@ -103,15 +96,12 @@ public interface ObjectLocator
/**
* Preferred version of {@link #autobuild(Class)} that tracks the operation using
* {@link OperationTracker#invoke(String, Invokable)}.
- *
+ *
* @param <T>
- * @param description
- * description used with {@link OperationTracker}
- * @param clazz
- * the type of object to instantiate
+ * @param description description used with {@link OperationTracker}
+ * @param clazz the type of object to instantiate
* @return the instantiated instance
- * @throws RuntimeException
- * if the autobuild fails
+ * @throws RuntimeException if the autobuild fails
* @see MasterObjectProvider
* @since 5.2.0
*/
@@ -123,16 +113,14 @@ public interface ObjectLocator
* proxy to prevent service construction cycles, particularly when contributing (directly or indirectly) to the
* {@link org.apache.tapestry5.ioc.services.MasterObjectProvider} (which is itself at the heart
* of autobuilding).
- * <p>
+ * <p/>
* If the class file for the class is a file on the file system (not a file packaged in a JAR), then the proxy will
* <em>autoreload</em>: changing the class file will result in the new class being reloaded and re-instantiated
* (with dependencies).
- *
+ *
* @param <T>
- * @param interfaceClass
- * the interface implemented by the proxy
- * @param implementationClass
- * a concrete class that implements the interface
+ * @param interfaceClass the interface implemented by the proxy
+ * @param implementationClass a concrete class that implements the interface
* @return a proxy
* @see #autobuild(Class)
*/
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/Marker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/Marker.java?rev=1187574&r1=1187573&r2=1187574&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/Marker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/Marker.java Fri Oct 21 22:08:10 2011
@@ -1,4 +1,4 @@
-// Copyright 2007, 2009 The Apache Software Foundation
+// Copyright 2007, 2009, 2011 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.
@@ -17,11 +17,12 @@ package org.apache.tapestry5.ioc.annotat
import org.apache.tapestry5.ioc.def.ServiceDef;
import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
-import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import java.lang.annotation.Target;
/**
* Used to define one or more {@linkplain ServiceDef#getMarkers() marker annotations} for a service implementation. This
@@ -32,9 +33,11 @@ import java.lang.annotation.Target;
* additive, so a Marker annotation on the implementation class and/or specified with {@link
* org.apache.tapestry5.ioc.ServiceBindingOptions#withMarker(Class[])} will accumulate; a service may have any number of
* markers. Generally one or two is enough.
+ *
+ * @see org.apache.tapestry5.ioc.ObjectLocator#getService(Class, Class[])
*/
@Target(
- { TYPE, METHOD })
+ {TYPE, METHOD})
@Retention(RUNTIME)
@Documented
@UseWith({AnnotationUseContext.SERVICE, AnnotationUseContext.MODULE})
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ObjectLocatorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ObjectLocatorImpl.java?rev=1187574&r1=1187573&r2=1187574&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ObjectLocatorImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ObjectLocatorImpl.java Fri Oct 21 22:08:10 2011
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2010 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 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.
@@ -17,6 +17,8 @@ package org.apache.tapestry5.ioc.interna
import org.apache.tapestry5.ioc.AnnotationProvider;
import org.apache.tapestry5.ioc.ObjectLocator;
+import java.lang.annotation.Annotation;
+
/**
* Base service locator class used when only the module is known (i.e., when instantiating a module
* class).
@@ -40,9 +42,9 @@ public class ObjectLocatorImpl implement
return registry.getService(expandedServiceId, serviceInterface);
}
- public <T> T getService(Class<T> serviceInterface)
+ public <T> T getService(Class<T> serviceInterface, Class<? extends Annotation>... markerTypes)
{
- return registry.getService(serviceInterface);
+ return registry.getService(serviceInterface, markerTypes);
}
public <T> T getObject(Class<T> objectType, AnnotationProvider annotationProvider)
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java?rev=1187574&r1=1187573&r2=1187574&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java Fri Oct 21 22:08:10 2011
@@ -30,7 +30,11 @@ import org.apache.tapestry5.ioc.util.Unk
import org.apache.tapestry5.services.UpdateListenerHub;
import org.slf4j.Logger;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.util.*;
@SuppressWarnings("all")
@@ -108,6 +112,8 @@ public class RegistryImpl implements Reg
private final TypeCoercerProxy typeCoercerProxy = new TypeCoercerProxyImpl(this);
+ private final Map<Class<? extends Annotation>, Annotation> cachedAnnotationProxies = CollectionFactory.newConcurrentMap();
+
/**
* Constructs the registry from a set of module definitions and other resources.
*
@@ -627,10 +633,20 @@ public class RegistryImpl implements Reg
}
}
- public <T> T getService(Class<T> serviceInterface)
+ public <T> T getService(Class<T> serviceInterface, Class<? extends Annotation>... markerTypes)
{
lock.check();
+ if (markerTypes.length == 0)
+ {
+ return findServiceByTypeAlone(serviceInterface);
+ }
+
+ return findServiceByTypeAndMarkers(serviceInterface, markerTypes);
+ }
+
+ private <T> T findServiceByTypeAlone(Class<T> serviceInterface)
+ {
List<String> serviceIds = findServiceIdsForInterface(serviceInterface);
if (serviceIds == null)
@@ -656,6 +672,67 @@ public class RegistryImpl implements Reg
}
}
+ private <T> T findServiceByTypeAndMarkers(Class<T> serviceInterface, Class<? extends Annotation>... markerTypes)
+ {
+ AnnotationProvider provider = createAnnotationProvider(markerTypes);
+
+ Set<ServiceDef2> matches = CollectionFactory.newSet();
+ List<Class> markers = CollectionFactory.newList();
+
+ findServiceDefsMatchingMarkerAndType(serviceInterface, provider, null, markers, matches);
+
+ return extractServiceFromMatches(serviceInterface, markers, matches);
+ }
+
+ private AnnotationProvider createAnnotationProvider(Class<? extends Annotation>... markerTypes)
+ {
+ final Map<Class<? extends Annotation>, Annotation> map = CollectionFactory.newMap();
+
+ for (Class<? extends Annotation> markerType : markerTypes)
+ {
+ map.put(markerType, createAnnotationProxy(markerType));
+ }
+
+ return new AnnotationProvider()
+ {
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
+ {
+ return annotationClass.cast(map.get(annotationClass));
+ }
+ };
+ }
+
+ private <A extends Annotation> Annotation createAnnotationProxy(final Class<A> annotationType)
+ {
+ Annotation result = cachedAnnotationProxies.get(annotationType);
+
+ if (result == null)
+ {
+ // We create a JDK proxy because its pretty quick and easy.
+
+ InvocationHandler handler = new InvocationHandler()
+ {
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+ {
+ if (method.getName().equals("annotationType"))
+ {
+ return annotationType;
+ }
+
+ return method.invoke(proxy, args);
+ }
+ };
+
+ result = (Annotation) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
+ new Class[]{annotationType},
+ handler);
+
+ cachedAnnotationProxies.put(annotationType, result);
+ }
+
+ return result;
+ }
+
private List<String> findServiceIdsForInterface(Class serviceInterface)
{
List<String> result = CollectionFactory.newList();
@@ -805,34 +882,29 @@ public class RegistryImpl implements Reg
if (provider == null)
return null;
- boolean localOnly = localModule != null && provider.getAnnotation(Local.class) != null;
-
Set<ServiceDef2> matches = CollectionFactory.newSet();
-
- matches.addAll(filterByType(objectType, localOnly ? moduleToServiceDefs.get(localModule) : allServiceDefs));
-
List<Class> markers = CollectionFactory.newList();
- if (localOnly)
- markers.add(Local.class);
-
- for (Class marker : markerToServiceDef.keySet())
- {
- if (provider.getAnnotation(marker) == null)
- continue;
-
- markers.add(marker);
+ findServiceDefsMatchingMarkerAndType(objectType, provider, localModule, markers, matches);
- matches = intersection(matches, markerToServiceDef.get(marker));
- }
// If didn't see @Local or any recognized marker annotation, then don't try to filter that
- // way.
- // Continue on, eventually to the MasterObjectProvider service.
+ // way. Continue on, eventually to the MasterObjectProvider service.
if (markers.isEmpty())
+ {
return null;
+ }
+ return extractServiceFromMatches(objectType, markers, matches);
+ }
+
+ /**
+ * Given markers and matches processed by {@link #findServiceDefsMatchingMarkerAndType(Class, org.apache.tapestry5.ioc.AnnotationProvider, Module, java.util.List, java.util.Set)}, this
+ * finds the singular match, or reports an error for 0 or 2+ matches.
+ */
+ private <T> T extractServiceFromMatches(Class<T> objectType, List<Class> markers, Set<ServiceDef2> matches)
+ {
switch (matches.size())
{
@@ -859,28 +931,36 @@ public class RegistryImpl implements Reg
}
}
- /**
- * Filters the set into a new set, containing only elements shared between the set and the
- * filter collection.
- *
- * @param set to be filtered
- * @param filter values to keep from the set
- * @return a new set containing only the shared values
- */
- private static <T> Set<T> intersection(Set<T> set, Collection<T> filter)
+ private <T> void findServiceDefsMatchingMarkerAndType(Class<T> objectType, AnnotationProvider provider, Module localModule, List<Class> markers,
+ Set<ServiceDef2> matches)
{
- if (set.isEmpty())
- return Collections.emptySet();
+ assert provider != null;
- Set<T> result = CollectionFactory.newSet();
+ boolean localOnly = localModule != null && provider.getAnnotation(Local.class) != null;
+
+ matches.addAll(filterByType(objectType, localOnly ? moduleToServiceDefs.get(localModule) : allServiceDefs));
- for (T elem : filter)
+ if (localOnly)
{
- if (set.contains(elem))
- result.add(elem);
+ markers.add(Local.class);
}
- return result;
+ for (Class marker : markerToServiceDef.keySet())
+ {
+ if (provider.getAnnotation(marker) == null)
+ {
+ continue;
+ }
+
+ markers.add(marker);
+
+ matches.retainAll(markerToServiceDef.get(marker));
+
+ if (matches.isEmpty())
+ {
+ return;
+ }
+ }
}
public <T> T getObject(Class<T> objectType, AnnotationProvider annotationProvider)
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryWrapper.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryWrapper.java?rev=1187574&r1=1187573&r2=1187574&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryWrapper.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryWrapper.java Fri Oct 21 22:08:10 2011
@@ -1,4 +1,4 @@
-// Copyright 2007, 2010 The Apache Software Foundation
+// Copyright 2007, 2010, 2011 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,9 +18,11 @@ import org.apache.tapestry5.ioc.Annotati
import org.apache.tapestry5.ioc.ObjectLocator;
import org.apache.tapestry5.ioc.Registry;
+import java.lang.annotation.Annotation;
+
/**
* A wrapper around {@link InternalRegistry} that exists to expand symbols in a service id before
- * invoking {@link ObjectLocator#getService(Class)}.
+ * invoking {@link ObjectLocator#getService(String, Class)}.
*/
public class RegistryWrapper implements Registry
{
@@ -53,9 +55,9 @@ public class RegistryWrapper implements
return registry.getService(expandedServiceId, serviceInterface);
}
- public <T> T getService(Class<T> serviceInterface)
+ public <T> T getService(Class<T> serviceInterface, Class<? extends Annotation>... markerTypes)
{
- return registry.getService(serviceInterface);
+ return registry.getService(serviceInterface, markerTypes);
}
public <T> T autobuild(Class<T> clazz)
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/MasterObjectProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/MasterObjectProvider.java?rev=1187574&r1=1187573&r2=1187574&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/MasterObjectProvider.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/MasterObjectProvider.java Fri Oct 21 22:08:10 2011
@@ -39,7 +39,8 @@ public interface MasterObjectProvider
* decorator method. The locator parameter provides access to the services visible <em>to that context</em>.
* <p/>
* When the value is required and no {@link ObjectProvider} provided a non-null value, then {@link
- * ObjectLocator#getService(Class)} is invoked, to provide a uniquely matching service, or throw a failure exception
+ * ObjectLocator#getService(Class, Class[])} is invoked (with no marker annotations),
+ * to provide a uniquely matching service, or throw a failure exception
* if no <em>single</em> service can be found.
*
* @param objectType the expected object type
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java?rev=1187574&r1=1187573&r2=1187574&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java Fri Oct 21 22:08:10 2011
@@ -827,6 +827,19 @@ public class IntegrationTest extends IOC
}
@Test
+ public void get_service_by_type_and_markers()
+ {
+ Registry r = buildRegistry(GreeterModule.class);
+
+ Greeter blue = r.getService(Greeter.class, BlueMarker.class);
+
+ assert blue.getGreeting().equals("Blue");
+
+ r.shutdown();
+ }
+
+
+ @Test
public void service_activity_scoreboard_perthread() throws InterruptedException
{
final Registry r = buildRegistry(GreeterModule.class, PerThreadModule.class);
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/IOCInternalTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/IOCInternalTestCase.java?rev=1187574&r1=1187573&r2=1187574&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/IOCInternalTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/IOCInternalTestCase.java Fri Oct 21 22:08:10 2011
@@ -14,11 +14,6 @@
package org.apache.tapestry5.ioc.internal;
-import static org.easymock.EasyMock.isA;
-
-import java.util.Collections;
-import java.util.List;
-
import org.apache.tapestry5.ioc.AnnotationProvider;
import org.apache.tapestry5.ioc.Registry;
import org.apache.tapestry5.ioc.RegistryBuilder;
@@ -31,6 +26,12 @@ import org.testng.annotations.AfterMetho
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
+import java.lang.annotation.Annotation;
+import java.util.Collections;
+import java.util.List;
+
+import static org.easymock.EasyMock.isA;
+
public class IOCInternalTestCase extends IOCTestCase implements Registry
{
private static Registry registry;
@@ -60,9 +61,9 @@ public class IOCInternalTestCase extends
return registry.getObject(objectType, annotationProvider);
}
- public final <T> T getService(Class<T> serviceInterface)
+ public final <T> T getService(Class<T> serviceInterface, Class<? extends Annotation>... markerTypes)
{
- return registry.getService(serviceInterface);
+ return registry.getService(serviceInterface, markerTypes);
}
public final <T> T getService(String serviceId, Class<T> serviceInterface)
@@ -146,7 +147,7 @@ public class IOCInternalTestCase extends
}
protected final <T> void train_getService(InternalRegistry registry, String serviceId, Class<T> serviceInterface,
- T service)
+ T service)
{
expect(registry.getService(serviceId, serviceInterface)).andReturn(service);
}
@@ -156,7 +157,9 @@ public class IOCInternalTestCase extends
return newMock(ServiceActivityTracker.class);
}
- /** @since 5.3 */
+ /**
+ * @since 5.3
+ */
protected final TypeCoercerProxy mockTypeCoercerProxy()
{
return newMock(TypeCoercerProxy.class);