Author: cziegeler
Date: Fri Oct 26 13:35:24 2012
New Revision: 1402507
URL: http://svn.apache.org/viewvc?rev=1402507&view=rev
Log:
SLING-2630 : Cannot have multiple Adapter Factories configured to have same
adapter / adaptable combination . Applied patch from Will McGauley
Modified:
sling/trunk/bundles/extensions/adapter/src/main/java/org/apache/sling/adapter/internal/AdapterManagerImpl.java
sling/trunk/bundles/extensions/adapter/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java
Modified:
sling/trunk/bundles/extensions/adapter/src/main/java/org/apache/sling/adapter/internal/AdapterManagerImpl.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/adapter/src/main/java/org/apache/sling/adapter/internal/AdapterManagerImpl.java?rev=1402507&r1=1402506&r2=1402507&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/adapter/src/main/java/org/apache/sling/adapter/internal/AdapterManagerImpl.java
(original)
+++
sling/trunk/bundles/extensions/adapter/src/main/java/org/apache/sling/adapter/internal/AdapterManagerImpl.java
Fri Oct 26 13:35:24 2012
@@ -24,12 +24,10 @@ import static org.apache.sling.api.adapt
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -67,7 +65,7 @@ import org.slf4j.LoggerFactory;
})
@Reference(name="AdapterFactory", referenceInterface=AdapterFactory.class,
- cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
policy=ReferencePolicy.DYNAMIC)
+cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
policy=ReferencePolicy.DYNAMIC)
public class AdapterManagerImpl implements AdapterManager {
private final Logger log = LoggerFactory.getLogger(getClass());
@@ -104,8 +102,8 @@ public class AdapterManagerImpl implemen
* {@link #getAdapterFactories(Class)} method. It is cleared
* whenever an adapter factory is registered on unregistered.
*/
- private final ConcurrentMap<String, Map<String, AdapterFactoryDescriptor>>
factoryCache
- = new ConcurrentHashMap<String, Map<String,
AdapterFactoryDescriptor>>();
+ private final ConcurrentMap<String, Map<String,
List<AdapterFactoryDescriptor>>> factoryCache
+ = new ConcurrentHashMap<String, Map<String,
List<AdapterFactoryDescriptor>>>();
/**
* The service tracker for the event admin
@@ -125,18 +123,28 @@ public class AdapterManagerImpl implemen
final Class<AdapterType> type) {
// get the adapter factories for the type of adaptable object
- final Map<String, AdapterFactoryDescriptor> factories =
getAdapterFactories(adaptable.getClass());
+ final Map<String, List<AdapterFactoryDescriptor>> factories =
getAdapterFactories(adaptable.getClass());
// get the factory for the target type
- final AdapterFactoryDescriptor desc = factories.get(type.getName());
- final AdapterFactory factory = desc == null ? null : desc.getFactory();
+ final List<AdapterFactoryDescriptor> descList =
factories.get(type.getName());
- // have the factory adapt the adaptable if the factory exists
- if (factory != null) {
- log.debug("Using adapter factory {} to map {} to {}",
- new Object [] { factory, adaptable, type });
-
- return factory.getAdapter(adaptable, type);
+ if (descList != null && descList.size() > 0) {
+ for (AdapterFactoryDescriptor desc : descList) {
+ final AdapterFactory factory = desc == null ? null :
desc.getFactory();
+
+ // have the factory adapt the adaptable if the factory exists
+ if (factory != null) {
+ log.debug("Trying adapter factory {} to map {} to {}",
+ new Object [] { factory, adaptable, type });
+
+ AdapterType adaptedObject = factory.getAdapter(adaptable,
type);
+ if (adaptedObject != null) {
+ log.debug("Using adapter factory {} to map {} to {}",
+ new Object [] { factory, adaptable, type });
+ return adaptedObject;
+ }
+ }
+ }
}
// no factory has been found, so we cannot adapt
@@ -221,7 +229,7 @@ public class AdapterManagerImpl implemen
* <strong><em>THIS METHOD IS FOR UNIT TESTING ONLY. IT MAY BE REMOVED OR
* MODIFIED WITHOUT NOTICE.</em></strong>
*/
- Map<String, Map<String, AdapterFactoryDescriptor>> getFactoryCache() {
+ Map<String, Map<String, List<AdapterFactoryDescriptor>>> getFactoryCache()
{
return factoryCache;
}
@@ -235,12 +243,12 @@ public class AdapterManagerImpl implemen
final String[] adapters =
PropertiesUtil.toStringArray(reference.getProperty(ADAPTER_CLASSES));
if (adaptables == null || adaptables.length == 0 || adapters == null
- || adapters.length == 0) {
+ || adapters.length == 0) {
return;
}
final AdapterFactoryDescriptor factoryDesc = new
AdapterFactoryDescriptor(context,
- reference, adapters);
+ reference, adapters);
for (final String adaptable : adaptables) {
AdapterFactoryDescriptorMap adfMap = null;
@@ -282,7 +290,7 @@ public class AdapterManagerImpl implemen
final String[] adapters =
PropertiesUtil.toStringArray(reference.getProperty(ADAPTER_CLASSES));
if (adaptables == null || adaptables.length == 0 || adapters == null
- || adapters.length == 0) {
+ || adapters.length == 0) {
return;
}
@@ -323,14 +331,13 @@ public class AdapterManagerImpl implemen
*
* @param clazz The adaptable <code>Class</code> for which to return the
* adapter factory map by target class name.
- * @param cache The cache of already defined adapter factory mappings
* @return The map of adapter factories by target class name. The map may
be
* empty if there is no adapter factory for the adaptable
* <code>clazz</code>.
*/
- private Map<String, AdapterFactoryDescriptor> getAdapterFactories(final
Class<?> clazz) {
+ private Map<String, List<AdapterFactoryDescriptor>>
getAdapterFactories(final Class<?> clazz) {
final String className = clazz.getName();
- Map<String, AdapterFactoryDescriptor> entry =
this.factoryCache.get(className);
+ Map<String, List<AdapterFactoryDescriptor>> entry =
this.factoryCache.get(className);
if (entry == null) {
// create entry
entry = createAdapterFactoryMap(clazz);
@@ -344,8 +351,7 @@ public class AdapterManagerImpl implemen
* Creates a new target adapter factory map for the given
<code>clazz</code>.
* First all factories defined to support the adaptable class by
* registration are taken. Next all factories for the implemented
interfaces
- * and finally all base class factories are copied. Later adapter factory
- * entries do NOT overwrite earlier entries.
+ * and finally all base class factories are copied.
*
* @param clazz The adaptable <code>Class</code> for which to build the
* adapter factory map by target class name.
@@ -353,8 +359,8 @@ public class AdapterManagerImpl implemen
* empty if there is no adapter factory for the adaptable
* <code>clazz</code>.
*/
- private Map<String, AdapterFactoryDescriptor>
createAdapterFactoryMap(final Class<?> clazz) {
- final Map<String, AdapterFactoryDescriptor> afm = new HashMap<String,
AdapterFactoryDescriptor>();
+ private Map<String, List<AdapterFactoryDescriptor>>
createAdapterFactoryMap(final Class<?> clazz) {
+ final Map<String, List<AdapterFactoryDescriptor>> afm = new
HashMap<String, List<AdapterFactoryDescriptor>>();
// AdapterFactories for this class
AdapterFactoryDescriptorMap afdMap = null;
@@ -362,18 +368,20 @@ public class AdapterManagerImpl implemen
afdMap = this.descriptors.get(clazz.getName());
}
if (afdMap != null) {
- final Set<AdapterFactoryDescriptor> afdSet;
+ final List<AdapterFactoryDescriptor> afdSet;
synchronized ( afdMap ) {
- afdSet = new
HashSet<AdapterFactoryDescriptor>(afdMap.values());
+ afdSet = new
ArrayList<AdapterFactoryDescriptor>(afdMap.values());
}
for (final AdapterFactoryDescriptor afd : afdSet) {
final String[] adapters = afd.getAdapters();
for (final String adapter : adapters) {
- // to handle service ranking, we only add if the map does
not
- // have a value for this adapter yet
- if (!afm.containsKey(adapter)) {
- afm.put(adapter, afd);
+ // to handle service ranking, we add to the end of the
list or create a new list
+ List<AdapterFactoryDescriptor> factoryDescriptors =
afm.get(adapter);
+ if (factoryDescriptors == null) {
+ factoryDescriptors = new
ArrayList<AdapterFactoryDescriptor>();
+ afm.put(adapter, factoryDescriptors);
}
+ factoryDescriptors.add(afd);
}
}
}
@@ -405,17 +413,23 @@ public class AdapterManagerImpl implemen
* @param clazz The adaptable class whose adapter factories are considered
* for adding into <code>dest</code>.
*/
- private void copyAdapterFactories(final Map<String,
AdapterFactoryDescriptor> dest,
+ private void copyAdapterFactories(final Map<String,
List<AdapterFactoryDescriptor>> dest,
final Class<?> clazz) {
// get the adapter factories for the adaptable clazz
- final Map<String, AdapterFactoryDescriptor> scMap =
getAdapterFactories(clazz);
+ final Map<String, List<AdapterFactoryDescriptor>> scMap =
getAdapterFactories(clazz);
- // for each target class copy the entry to dest if dest does
- // not contain the target class already
- for (Map.Entry<String, AdapterFactoryDescriptor> entry :
scMap.entrySet()) {
- if (!dest.containsKey(entry.getKey())) {
- dest.put(entry.getKey(), entry.getValue());
+ // for each target class copy the entry to dest and put it in the list
or create the list
+ for (Map.Entry<String, List<AdapterFactoryDescriptor>> entry :
scMap.entrySet()) {
+
+ List<AdapterFactoryDescriptor> factoryDescriptors =
dest.get(entry.getKey());
+
+ if (factoryDescriptors == null) {
+ factoryDescriptors = new ArrayList<AdapterFactoryDescriptor>();
+ dest.put(entry.getKey(), factoryDescriptors);
+ }
+ for (AdapterFactoryDescriptor descriptor : entry.getValue()) {
+ factoryDescriptors.add(descriptor);
}
}
}
Modified:
sling/trunk/bundles/extensions/adapter/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/adapter/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java?rev=1402507&r1=1402506&r2=1402507&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/adapter/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java
(original)
+++
sling/trunk/bundles/extensions/adapter/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java
Fri Oct 26 13:35:24 2012
@@ -18,16 +18,11 @@
*/
package org.apache.sling.adapter.internal;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Map;
-
import org.apache.sling.adapter.mock.MockAdapterFactory;
import org.apache.sling.api.adapter.AdapterFactory;
import org.apache.sling.api.adapter.SlingAdaptable;
+import org.hamcrest.Matcher;
+import org.hamcrest.core.IsAnything;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
@@ -41,6 +36,13 @@ import org.osgi.framework.ServiceListene
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
@RunWith(JMock.class)
public class AdapterManagerTest {
@@ -90,11 +92,39 @@ public class AdapterManagerTest {
return ctx;
}
+ /**
+ * Helper method to create a mock component context
+ */
+ protected ComponentContext createMultipleAdaptersComponentContext(final
ServiceReference firstServiceReference, final ServiceReference
secondServiceReference) throws Exception {
+ final BundleContext bundleCtx = this.context.mock(BundleContext.class);
+ final Filter filter = this.context.mock(Filter.class);
+ final ComponentContext ctx = this.context.mock(ComponentContext.class);
+ this.context.checking(new Expectations() {{
+ allowing(ctx).locateService(with(any(String.class)),
with(firstServiceReference));
+ will(returnValue(new FirstImplementationAdapterFactory()));
+ allowing(ctx).locateService(with(any(String.class)),
with(secondServiceReference));
+ will(returnValue(new SecondImplementationAdapterFactory()));
+ allowing(ctx).getBundleContext();
+ will(returnValue(bundleCtx));
+ allowing(bundleCtx).createFilter(with(any(String.class)));
+ will(returnValue(filter));
+
allowing(bundleCtx).addServiceListener(with(any(ServiceListener.class)),
with(any(String.class)));
+ allowing(bundleCtx).getServiceReferences(with(any(String.class)),
with(any(String.class)));
+ will(returnValue(null));
+
allowing(bundleCtx).removeServiceListener(with(any(ServiceListener.class)));
+ }});
+ return ctx;
+ }
+
+ public static <T> Matcher<T> any(@SuppressWarnings("unused") Class<T>
type) {
+ return new IsAnything<T>();
+ }
+
/**
* Helper method to create a mock service reference
*/
protected ServiceReference createServiceReference() {
- final ServiceReference ref = new ServiceReferenceImpl(1, new String[]{
TestSlingAdaptable.class.getName() }, ITestAdapter.class.getName());
+ final ServiceReference ref = new ServiceReferenceImpl(1, new String[]{
TestSlingAdaptable.class.getName() }, new
String[]{ITestAdapter.class.getName()});
return ref;
}
@@ -102,9 +132,9 @@ public class AdapterManagerTest {
private int ranking;
private String[] adapters;
- private String classes;
+ private String[] classes;
- public ServiceReferenceImpl(final int order, final String[] adapters,
final String classes) {
+ public ServiceReferenceImpl(final int order, final String[] adapters,
final String[] classes) {
this.ranking = order;
this.adapters = adapters;
this.classes = classes;
@@ -154,7 +184,7 @@ public class AdapterManagerTest {
* Helper method to create a mock service reference
*/
protected ServiceReference createServiceReference2() {
- final ServiceReference ref = new ServiceReferenceImpl(2, new String[]{
TestSlingAdaptable2.class.getName() }, TestAdapter.class.getName());
+ final ServiceReference ref = new ServiceReferenceImpl(2, new String[]{
TestSlingAdaptable2.class.getName() }, new
String[]{TestAdapter.class.getName()});
return ref;
}
@@ -289,6 +319,144 @@ public class AdapterManagerTest {
assertTrue(adapter instanceof TestAdapter);
}
+ @org.junit.Test public void testAdaptMultipleAdapterFactories() throws
Exception {
+ final ServiceReference firstAdaptable = new ServiceReferenceImpl(1,
new String[]{AdapterObject.class.getName()}, new String[]{
ParentInterface.class.getName(), FirstImplementation.class.getName()});
+ final ServiceReference secondAdaptable = new ServiceReferenceImpl(2,
new String[]{ AdapterObject.class.getName() }, new
String[]{ParentInterface.class.getName(),
SecondImplementation.class.getName()});
+
+
am.activate(this.createMultipleAdaptersComponentContext(firstAdaptable,
secondAdaptable));
+
+ AdapterObject first = new AdapterObject(Want.FIRST_IMPL);
+ assertNull("Expect no adapter", am.getAdapter(first,
ParentInterface.class));
+
+ AdapterObject second = new AdapterObject(Want.SECOND_IMPL);
+ assertNull("Expect no adapter", am.getAdapter(second,
ParentInterface.class));
+
+ am.bindAdapterFactory(firstAdaptable);
+ am.bindAdapterFactory(secondAdaptable);
+
+ Object adapter = am.getAdapter(first, ParentInterface.class);
+ assertNotNull("Did not get an adapter back for first implementation,
service ranking 1", adapter);
+ assertTrue("Did not get the correct adaptable back for first
implementation, service ranking 1, ", adapter instanceof FirstImplementation);
+
+ adapter = am.getAdapter(second, ParentInterface.class);
+ assertNotNull("Did not get an adapter back for second implementation,
service ranking 2", adapter);
+ assertTrue("Did not get the correct adaptable back for second
implementation, service ranking 2, ", adapter instanceof SecondImplementation);
+
+ adapter = am.getAdapter(first, FirstImplementation.class);
+ assertNotNull("Did not get an adapter back for first implementation,
service ranking 1", adapter);
+ assertTrue("Did not get the correct adaptable back for first
implementation, service ranking 1, ", adapter instanceof FirstImplementation);
+
+ adapter = am.getAdapter(second, SecondImplementation.class);
+ assertNotNull("Did not get an adapter back for second implementation,
service ranking 2", adapter);
+ assertTrue("Did not get the correct adaptable back for second
implementation, service ranking 2, ", adapter instanceof SecondImplementation);
+ }
+
+ @org.junit.Test public void
testAdaptMultipleAdapterFactoriesReverseOrder() throws Exception {
+ final ServiceReference firstAdaptable = new ServiceReferenceImpl(2,
new String[]{AdapterObject.class.getName()}, new String[]{
ParentInterface.class.getName()});
+ final ServiceReference secondAdaptable = new ServiceReferenceImpl(1,
new String[]{AdapterObject.class.getName()}, new String[]{
ParentInterface.class.getName()});
+
am.activate(this.createMultipleAdaptersComponentContext(firstAdaptable,
secondAdaptable));
+
+ AdapterObject first = new AdapterObject(Want.FIRST_IMPL);
+ assertNull("Expect no adapter", am.getAdapter(first,
ParentInterface.class));
+
+ AdapterObject second = new AdapterObject(Want.SECOND_IMPL);
+ assertNull("Expect no adapter", am.getAdapter(second,
ParentInterface.class));
+
+ am.bindAdapterFactory(firstAdaptable);
+ am.bindAdapterFactory(secondAdaptable);
+
+ Object adapter = am.getAdapter(first, ParentInterface.class);
+ assertNotNull("Did not get an adapter back for first implementation,
service ranking 2", adapter);
+ assertTrue("Did not get the correct adaptable back for first
implementation, service ranking 2, ", adapter instanceof FirstImplementation);
+
+ }
+
+ @org.junit.Test public void
testAdaptMultipleAdapterFactoriesServiceRanking() throws Exception {
+ final ServiceReference firstAdaptable = new ServiceReferenceImpl(1,
new String[]{AdapterObject.class.getName()}, new String[]{
ParentInterface.class.getName(), FirstImplementation.class.getName()});
+ final ServiceReference secondAdaptable = new ServiceReferenceImpl(2,
new String[]{ AdapterObject.class.getName() }, new
String[]{ParentInterface.class.getName(),
SecondImplementation.class.getName()});
+
+
am.activate(this.createMultipleAdaptersComponentContext(firstAdaptable,
secondAdaptable));
+
+ AdapterObject first = new AdapterObject(Want.INDIFFERENT);
+ assertNull("Expect no adapter", am.getAdapter(first,
ParentInterface.class));
+
+ AdapterObject second = new AdapterObject(Want.INDIFFERENT);
+ assertNull("Expect no adapter", am.getAdapter(second,
ParentInterface.class));
+
+ am.bindAdapterFactory(firstAdaptable);
+ am.bindAdapterFactory(secondAdaptable);
+
+ Object adapter = am.getAdapter(first, ParentInterface.class);
+ assertNotNull("Did not get an adapter back for first implementation
(from ParentInterface), service ranking 1", adapter);
+ assertTrue("Did not get the correct adaptable back for first
implementation, service ranking 1, ", adapter instanceof FirstImplementation);
+
+ adapter = am.getAdapter(first, FirstImplementation.class);
+ assertNotNull("Did not get an adapter back for first implementation,
service ranking 1", adapter);
+ assertTrue("Did not get the correct adaptable back for first
implementation, service ranking 1, ", adapter instanceof FirstImplementation);
+
+ adapter = am.getAdapter(second, SecondImplementation.class);
+ assertNotNull("Did not get an adapter back for second implementation,
service ranking 2", adapter);
+ assertTrue("Did not get the correct adaptable back for second
implementation, service ranking 2, ", adapter instanceof SecondImplementation);
+ }
+
+ @org.junit.Test public void
testAdaptMultipleAdapterFactoriesServiceRankingSecondHigherOrder() throws
Exception {
+ final ServiceReference firstAdaptable = new ServiceReferenceImpl(2,
new String[]{AdapterObject.class.getName()}, new String[]{
ParentInterface.class.getName(), FirstImplementation.class.getName()});
+ final ServiceReference secondAdaptable = new ServiceReferenceImpl(1,
new String[]{ AdapterObject.class.getName() }, new
String[]{ParentInterface.class.getName(),
SecondImplementation.class.getName()});
+
+
am.activate(this.createMultipleAdaptersComponentContext(firstAdaptable,
secondAdaptable));
+
+ AdapterObject first = new AdapterObject(Want.INDIFFERENT);
+ assertNull("Expect no adapter", am.getAdapter(first,
ParentInterface.class));
+
+ AdapterObject second = new AdapterObject(Want.INDIFFERENT);
+ assertNull("Expect no adapter", am.getAdapter(second,
ParentInterface.class));
+
+ am.bindAdapterFactory(firstAdaptable);
+ am.bindAdapterFactory(secondAdaptable);
+
+ Object adapter = am.getAdapter(first, ParentInterface.class);
+ assertNotNull("Did not get an adapter back for second implementation
(from ParentInterface), service ranking 1", adapter);
+ assertTrue("Did not get the correct adaptable back for second
implementation, service ranking 1, ", adapter instanceof SecondImplementation);
+
+ adapter = am.getAdapter(first, FirstImplementation.class);
+ assertNotNull("Did not get an adapter back for first implementation,
service ranking 1", adapter);
+ assertTrue("Did not get the correct adaptable back for first
implementation, service ranking 1, ", adapter instanceof FirstImplementation);
+
+ adapter = am.getAdapter(second, SecondImplementation.class);
+ assertNotNull("Did not get an adapter back for second implementation,
service ranking 2", adapter);
+ assertTrue("Did not get the correct adaptable back for second
implementation, service ranking 2, ", adapter instanceof SecondImplementation);
+ }
+
+ @org.junit.Test public void
testAdaptMultipleAdapterFactoriesServiceRankingReverse() throws Exception {
+ final ServiceReference firstAdaptable = new ServiceReferenceImpl(1,
new String[]{AdapterObject.class.getName()}, new String[]{
ParentInterface.class.getName(), FirstImplementation.class.getName()});
+ final ServiceReference secondAdaptable = new ServiceReferenceImpl(2,
new String[]{ AdapterObject.class.getName() }, new
String[]{ParentInterface.class.getName(),
SecondImplementation.class.getName()});
+
+
am.activate(this.createMultipleAdaptersComponentContext(firstAdaptable,
secondAdaptable));
+
+ AdapterObject first = new AdapterObject(Want.INDIFFERENT);
+ assertNull("Expect no adapter", am.getAdapter(first,
ParentInterface.class));
+
+ AdapterObject second = new AdapterObject(Want.INDIFFERENT);
+ assertNull("Expect no adapter", am.getAdapter(second,
ParentInterface.class));
+
+ // bind these in reverse order from the non-reverse test
+ am.bindAdapterFactory(secondAdaptable);
+ am.bindAdapterFactory(firstAdaptable);
+
+ Object adapter = am.getAdapter(first, ParentInterface.class);
+ assertNotNull("Did not get an adapter back for first implementation
(from ParentInterface), service ranking 1", adapter);
+ assertTrue("Did not get the correct adaptable back for first
implementation, service ranking 1, ", adapter instanceof FirstImplementation);
+
+ adapter = am.getAdapter(first, FirstImplementation.class);
+ assertNotNull("Did not get an adapter back for first implementation,
service ranking 1", adapter);
+ assertTrue("Did not get the correct adaptable back for first
implementation, service ranking 1, ", adapter instanceof FirstImplementation);
+
+ adapter = am.getAdapter(second, SecondImplementation.class);
+ assertNotNull("Did not get an adapter back for second implementation,
service ranking 2", adapter);
+ assertTrue("Did not get the correct adaptable back for second
implementation, service ranking 2, ", adapter instanceof SecondImplementation);
+ }
+
+
//---------- Test Adaptable and Adapter Classes ---------------------------
public static class TestSlingAdaptable extends SlingAdaptable {
@@ -307,4 +475,77 @@ public class AdapterManagerTest {
}
+ public class FirstImplementationAdapterFactory implements AdapterFactory {
+
+ public <AdapterType> AdapterType getAdapter(Object adaptable,
Class<AdapterType> type) {
+ if (adaptable instanceof AdapterObject) {
+ AdapterObject adapterObject = (AdapterObject) adaptable;
+ switch (adapterObject.getWhatWeWant()) {
+ case FIRST_IMPL:
+ case INDIFFERENT:
+ return (AdapterType) new FirstImplementation();
+ case SECOND_IMPL:
+ return null;
+ }
+ }
+ throw new RuntimeException("Must pass the correct adaptable");
+ }
+ }
+
+ public class SecondImplementationAdapterFactory implements AdapterFactory {
+
+ public <AdapterType> AdapterType getAdapter(Object adaptable,
Class<AdapterType> type) {
+ if (adaptable instanceof AdapterObject) {
+ AdapterObject adapterObject = (AdapterObject) adaptable;
+ switch (adapterObject.getWhatWeWant()) {
+ case SECOND_IMPL:
+ case INDIFFERENT:
+ return (AdapterType) new SecondImplementation();
+ case FIRST_IMPL:
+ return null;
+ }
+ }
+ throw new RuntimeException("Must pass the correct adaptable");
+ }
+ }
+
+ public static interface ParentInterface {
+ }
+
+ public static class FirstImplementation implements ParentInterface {
+ }
+
+ public static class SecondImplementation implements ParentInterface {
+ }
+
+ public enum Want {
+
+ /**
+ * Indicates we definitively want the "first implementation" adapter
factory to execute the adapt
+ */
+ FIRST_IMPL,
+
+ /**
+ * Indicates we definitively want the "second implementation" adapter
factory to execute the adapt
+ */
+ SECOND_IMPL,
+
+ /**
+ * Indicates we are indifferent to which factory is used to execute
the adapt, used for testing service ranking
+ */
+ INDIFFERENT
+ }
+
+ public static class AdapterObject {
+ private Want whatWeWant;
+
+ public AdapterObject(Want whatWeWant) {
+ this.whatWeWant = whatWeWant;
+ }
+
+ public Want getWhatWeWant() {
+ return whatWeWant;
+ }
+ }
+
}