/* * 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; import java.util.Map; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; /** * The <code>ServiceUtil</code> is a utility class providing some * useful utility methods for service handling. * @since 2.1 */ public class ServiceUtil { /** * @deprecated Use {@link #getComparableForServiceRanking(Map, Order)} instead. * @param props The service properties. * @return the same comparable as returned by {@code 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. 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, 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, Order order) { this.props = props; this.order = order; } @SuppressWarnings("unchecked") public int compareTo(Object reference) { final Long otherId; Object otherRankObj; if ( reference instanceof ServiceReference ) { final ServiceReference other = (ServiceReference) reference; otherId = (Long) other.getProperty(Constants.SERVICE_ID); otherRankObj = other.getProperty(Constants.SERVICE_RANKING); } else if (reference instanceof Map){ final Map<String, Object> otherProps = (Map<String, Object>)reference; otherId = (Long) otherProps.get(Constants.SERVICE_ID); otherRankObj = otherProps.get(Constants.SERVICE_RANKING); } else { final ComparableImplementation other = (ComparableImplementation)reference; otherId = (Long) other.props.get(Constants.SERVICE_ID); otherRankObj = other.props.get(Constants.SERVICE_RANKING); } final Long id = (Long) props.get(Constants.SERVICE_ID); if (id.equals(otherId)) { return 0; // same service } Object rankObj = props.get(Constants.SERVICE_RANKING); // If no rank, then spec says it defaults to zero. rankObj = (rankObj == null) ? new Integer(0) : rankObj; otherRankObj = (otherRankObj == null) ? new Integer(0) : otherRankObj; // If rank is not Integer, then spec says it defaults to zero. Integer rank = (rankObj instanceof Integer) ? (Integer) rankObj : new Integer(0); Integer otherRank = (otherRankObj instanceof Integer) ? (Integer) otherRankObj : new Integer(0); // Sort by rank. if (rank.compareTo(otherRank) < 0) { return order.lessThan; // lower rank } else if (rank.compareTo(otherRank) > 0) { return order.greaterThan; // higher rank } // If ranks are equal, then sort by service id. return (id.compareTo(otherId) < 0) ? order.greaterThan : order.lessThan; } @Override public boolean equals(Object obj) { if ( obj instanceof ComparableImplementation ) { return this.props.equals(((ComparableImplementation)obj).props); } return false; } @Override public int hashCode() { return this.props.hashCode(); } } }