SLING-7194 AdapterManager sorts AdapterFactory implementations lowest ranking first
diff --git a/src/main/java/org/apache/sling/adapter/internal/AdapterFactoryDescriptorMap.java b/src/main/java/org/apache/sling/adapter/internal/AdapterFactoryDescriptorMap.java
index 4de3d08..c36f7dc 100644
--- a/src/main/java/org/apache/sling/adapter/internal/AdapterFactoryDescriptorMap.java
+++ b/src/main/java/org/apache/sling/adapter/internal/AdapterFactoryDescriptorMap.java
@@ -18,6 +18,7 @@
*/
package org.apache.sling.adapter.internal;
+import java.util.Comparator;
import java.util.TreeMap;
import org.apache.sling.api.adapter.AdapterFactory;
@@ -41,4 +42,16 @@
private static final long serialVersionUID = 2L;
+ public AdapterFactoryDescriptorMap() {
+ super(new Comparator<ServiceReference<AdapterFactory>>() {
+ @Override
+ public int compare(ServiceReference<AdapterFactory> o1, ServiceReference<AdapterFactory> o2) {
+ // compareTo of ServiceReference implements service-ranking lowest-first/service id highest-first
+ // but we want service-ranking highest-first/service id lowest-first as it is done e.g. for BundleContext.getService
+ // so explicitly reverse the comparison (SLING-7194)
+ return o2.compareTo(o1);
+ }
+ });
+ }
+
}
diff --git a/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java b/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java
index 1208c85..635ab83 100644
--- a/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java
+++ b/src/test/java/org/apache/sling/adapter/internal/AdapterManagerTest.java
@@ -395,34 +395,6 @@
}
@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()});
@@ -438,21 +410,49 @@
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);
+ assertNotNull("Did not get an adapter back for first implementation (from ParentInterface), service ranking 2", adapter);
+ assertTrue("Did not get the correct adaptable back for first implementation, service ranking 2, ", 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);
+ 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);
adapter = am.getAdapter(second, SecondImplementation.class);
- assertNotNull("Did not get an adapter back for second implementation, service ranking 2", adapter);
+ assertNotNull("Did not get an adapter back for second implementation, service ranking 1", adapter);
+ assertTrue("Did not get the correct adaptable back for second implementation, service ranking 1, ", adapter instanceof SecondImplementation);
+ }
+
+ @org.junit.Test public void testAdaptMultipleAdapterFactoriesServiceRankingSecondHigherOrder() 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 second implementation (from ParentInterface), 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 2", adapter);
+ assertTrue("Did not get the correct adaptable back for first implementation, service ranking 2, ", adapter instanceof FirstImplementation);
+
+ adapter = am.getAdapter(second, SecondImplementation.class);
+ assertNotNull("Did not get an adapter back for second implementation, service ranking 1", adapter);
+ assertTrue("Did not get the correct adaptable back for second implementation, service ranking 1, ", 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()});
+ 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));
@@ -467,16 +467,16 @@
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);
+ assertNotNull("Did not get an adapter back for first implementation (from ParentInterface), service ranking 2", adapter);
+ assertTrue("Did not get the correct adaptable back for first implementation, service ranking 2, ", 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);
+ 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);
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);
+ assertNotNull("Did not get an adapter back for second implementation, service ranking 1", adapter);
+ assertTrue("Did not get the correct adaptable back for second implementation, service ranking 1, ", adapter instanceof SecondImplementation);
}