You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2015/12/26 14:34:42 UTC
svn commit: r1721731 - in /sling/trunk/bundles/commons/osgi/src:
main/java/org/apache/sling/commons/osgi/
test/java/org/apache/sling/commons/osgi/
Author: kwin
Date: Sat Dec 26 13:34:42 2015
New Revision: 1721731
URL: http://svn.apache.org/viewvc?rev=1721731&view=rev
Log:
SLING-5041 allow to explicitly give ordering in RankedServices and in ServiceUtil
deprecate constructors not having a dedicated order parameter
Added:
sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/Order.java (with props)
Modified:
sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/RankedServices.java
sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/ServiceUtil.java
sling/trunk/bundles/commons/osgi/src/test/java/org/apache/sling/commons/osgi/RankedServicesTest.java
Added: sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/Order.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/Order.java?rev=1721731&view=auto
==============================================================================
--- sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/Order.java (added)
+++ sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/Order.java Sat Dec 26 13:34:42 2015
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sling.commons.osgi;
+
+/**
+ * Order for services being sorted by {@link ServiceUtil#getComparableForServiceRanking(java.util.Map, Order)}
+ * or {@link RankedServices}. Either {@link #ASCENDING} meaning services with lowest service ranking first or
+ * {@link #DESCENDING} meaning services with highest service ranking first.
+ */
+enum Order {
+ ASCENDING(-1, 1),
+ DESCENDING(1, -1);
+
+ public final int lessThan;
+ public final int greaterThan;
+
+ private Order(int lessThan, int greaterThan) {
+ this.lessThan = lessThan;
+ this.greaterThan = greaterThan;
+ }
+}
\ No newline at end of file
Propchange: sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/Order.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/RankedServices.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/RankedServices.java?rev=1721731&r1=1721730&r2=1721731&view=diff
==============================================================================
--- sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/RankedServices.java (original)
+++ sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/RankedServices.java Sat Dec 26 13:34:42 2015
@@ -27,6 +27,8 @@ import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
+import org.osgi.framework.BundleContext;
+
import aQute.bnd.annotation.ConsumerType;
import aQute.bnd.annotation.ProviderType;
@@ -39,7 +41,7 @@ import aQute.bnd.annotation.ProviderType
* <pre>
* @Reference(name = "myService", referenceInterface = MyService.class,
* cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC)
- * private final RankedServices<MyService> myServices = new RankedServices<MyService>();
+ * private final RankedServices<MyService> myServices = new RankedServices<MyService>(Order.DESCENDING);
* </pre>
* <p>2. Define bind/unbind methods that delegate to the RankedServices instance:</p>
* <pre>
@@ -67,19 +69,50 @@ public final class RankedServices<T> imp
private final ChangeListener changeListener;
private final SortedMap<Comparable<Object>, T> serviceMap = new TreeMap<Comparable<Object>, T>();
private volatile Collection<T> sortedServices = Collections.emptyList();
+ private final Order order;
/**
- * Instantiate without change listener.
+ * Instantiate without change listener in ascending order (lowest service ranking first).
+ * @deprecated Use {@link #RankedService(Order)}) to explicitly give the order.
*/
+ @Deprecated
public RankedServices() {
- this(null);
+ this(Order.ASCENDING, null);
+ }
+
+ /**
+ * Instantiate with change listener in ascending order ((lowest service ranking first).
+ * @param changeListener Change listener
+ * @deprecated use {@link #RankedServices(Order order, ChangeListener changeListener)} instead
+ */
+ @Deprecated
+ public RankedServices(ChangeListener changeListener) {
+ this(Order.ASCENDING, changeListener);
+ }
+
+ /**
+ * Instantiate without change listener but with a given order.
+ * @param order the order in which the services should be returned in {@link #iterator()} and {@link #get()}.
+ * Either {@link Order#ASCENDING} or {@link Order#DESCENDING}.
+ * Use {@link Order#DESCENDING} if you want to have the service with the highest ranking returned first
+ * (this is the service which would also be chosen by {@link BundleContext#getServiceReference(String)}).
+ * @since 2.4
+ */
+ public RankedServices(Order order) {
+ this(order, null);
}
/**
* Instantiate with change listener.
+ * @param order the order in which the services should be returned in {@link #iterator()} and {@link #get()}.
+ * Either {@link Order#ASCENDING} or {@link Order#DESCENDING}.
+ * Use {@link Order#DESCENDING} if you want to have the service with the highest ranking returned first
+ * (this is the service which would also be chosen by {@link BundleContext#getServiceReference(String)}).
* @param changeListener Change listener
+ * @since 2.4
*/
- public RankedServices(ChangeListener changeListener) {
+ public RankedServices(Order order, ChangeListener changeListener) {
+ this.order = order;
this.changeListener = changeListener;
}
@@ -90,7 +123,7 @@ public final class RankedServices<T> imp
*/
public void bind(T service, Map<String, Object> props) {
synchronized (serviceMap) {
- serviceMap.put(ServiceUtil.getComparableForServiceRanking(props), service);
+ serviceMap.put(ServiceUtil.getComparableForServiceRanking(props, order), service);
updateSortedServices();
}
}
@@ -102,7 +135,7 @@ public final class RankedServices<T> imp
*/
public void unbind(T service, Map<String, Object> props) {
synchronized (serviceMap) {
- serviceMap.remove(ServiceUtil.getComparableForServiceRanking(props));
+ serviceMap.remove(ServiceUtil.getComparableForServiceRanking(props, order));
updateSortedServices();
}
}
@@ -119,7 +152,8 @@ public final class RankedServices<T> imp
}
/**
- * Lists all services registered in OSGi, sorted by service ranking.
+ * Lists all services registered in OSGi, sorted by service ranking
+ * (either ascending or descending depending on the order given in the constructor).
* @return Collection of service instances
*/
public Collection<T> get() {
@@ -127,7 +161,8 @@ public final class RankedServices<T> imp
}
/**
- * Iterates all services registered in OSGi, sorted by service ranking.
+ * Iterates all services registered in OSGi, sorted by service ranking
+ * (either ascending or descending depending on the order given in the constructor).
* @return Iterator with service instances.
*/
public Iterator<T> iterator() {
Modified: sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/ServiceUtil.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/ServiceUtil.java?rev=1721731&r1=1721730&r2=1721731&view=diff
==============================================================================
--- sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/ServiceUtil.java (original)
+++ sling/trunk/bundles/commons/osgi/src/main/java/org/apache/sling/commons/osgi/ServiceUtil.java Sat Dec 26 13:34:42 2015
@@ -20,6 +20,7 @@ package org.apache.sling.commons.osgi;
import java.util.Map;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
@@ -31,22 +32,41 @@ import org.osgi.framework.ServiceReferen
public class ServiceUtil {
/**
+ * @deprecated Use {@link #getComparableForServiceRanking(Map, Order)} instead.
+ * @param props The service properties.
+ * @return the same comparable as returned by {@link #getComparableForServiceRanking(Map, Order.ASCENDING)}
+ * @see #getComparableForServiceRanking(Map, Order)
+ */
+ @Deprecated
+ public static Comparable<Object> getComparableForServiceRanking(final Map<String, Object> props) {
+ return getComparableForServiceRanking(props, Order.ASCENDING);
+ }
+
+ /**
* Create a comparable object out of the service properties. With the result
* it is possible to compare service properties based on the service ranking
- * of a service. Therefore this object acts like {@link ServiceReference#compareTo(Object)}.
+ * of a service. This object acts like {@link ServiceReference#compareTo(Object)}.
+ * The comparator will return the services in the given order. In ascending order the
+ * service with the lowest ranking comes first, in descending order the service with the
+ * highest ranking comes first. The latter is useful if you want to have the service
+ * returned first which is also chosen by {@link BundleContext#getServiceReference(String)}).
* @param props The service properties.
+ * @param order The order (either ascending or descending).
* @return A comparable for the ranking of the service
+ * @since 2.4
*/
- public static Comparable<Object> getComparableForServiceRanking(final Map<String, Object> props) {
- return new ComparableImplementation(props);
+ public static Comparable<Object> getComparableForServiceRanking(final Map<String, Object> props, Order order) {
+ return new ComparableImplementation(props, order);
}
private static final class ComparableImplementation implements Comparable<Object> {
private final Map<String, Object> props;
+ private final Order order;
- private ComparableImplementation(Map<String, Object> props) {
+ private ComparableImplementation(Map<String, Object> props, Order order) {
this.props = props;
+ this.order = order;
}
@SuppressWarnings("unchecked")
@@ -83,15 +103,15 @@ public class ServiceUtil {
Integer otherRank = (otherRankObj instanceof Integer)
? (Integer) otherRankObj : new Integer(0);
- // Sort by rank in ascending order.
+ // Sort by rank.
if (rank.compareTo(otherRank) < 0) {
- return -1; // lower rank
+ return order.lessThan; // lower rank
} else if (rank.compareTo(otherRank) > 0) {
- return 1; // higher rank
+ return order.greaterThan; // higher rank
}
- // If ranks are equal, then sort by service id in descending order.
- return (id.compareTo(otherId) < 0) ? 1 : -1;
+ // If ranks are equal, then sort by service id.
+ return (id.compareTo(otherId) < 0) ? order.greaterThan : order.lessThan;
}
@Override
Modified: sling/trunk/bundles/commons/osgi/src/test/java/org/apache/sling/commons/osgi/RankedServicesTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/osgi/src/test/java/org/apache/sling/commons/osgi/RankedServicesTest.java?rev=1721731&r1=1721730&r2=1721731&view=diff
==============================================================================
--- sling/trunk/bundles/commons/osgi/src/test/java/org/apache/sling/commons/osgi/RankedServicesTest.java (original)
+++ sling/trunk/bundles/commons/osgi/src/test/java/org/apache/sling/commons/osgi/RankedServicesTest.java Sat Dec 26 13:34:42 2015
@@ -45,7 +45,7 @@ public class RankedServicesTest {
.put(Constants.SERVICE_RANKING, 100).put(Constants.SERVICE_ID, 3L).build();
@Test
- public void testSortedServices() {
+ public void testSortedServicesAscending() {
RankedServices<Comparable> underTest = new RankedServices<Comparable>();
assertEquals(0, underTest.get().size());
@@ -69,6 +69,32 @@ public class RankedServicesTest {
assertSame(SERVICE_3, services[1]);
}
+
+ @Test
+ public void testSortedServicesDescending() {
+ RankedServices<Comparable> underTest = new RankedServices<Comparable>(Order.DESCENDING);
+ assertEquals(0, underTest.get().size());
+
+ underTest.bind(SERVICE_1, SERVICE_1_PROPS);
+ assertEquals(1, underTest.get().size());
+ Comparable[] services = Iterators.toArray(underTest.get().iterator(), Comparable.class);
+ assertSame(SERVICE_1, services[0]);
+
+ underTest.bind(SERVICE_2, SERVICE_2_PROPS);
+ underTest.bind(SERVICE_3, SERVICE_3_PROPS);
+ assertEquals(3, underTest.get().size());
+ services = Iterators.toArray(underTest.get().iterator(), Comparable.class);
+ assertSame(SERVICE_3, services[0]);
+ assertSame(SERVICE_1, services[1]);
+ assertSame(SERVICE_2, services[2]);
+
+ underTest.unbind(SERVICE_2, SERVICE_2_PROPS);
+ assertEquals(2, underTest.get().size());
+ services = Iterators.toArray(underTest.get().iterator(), Comparable.class);
+ assertSame(SERVICE_3, services[0]);
+ assertSame(SERVICE_1, services[1]);
+ }
+
@Test
public void testChangeListener() {
ChangeListener changeListener = mock(ChangeListener.class);