blob: 7fa9e43fbb4b65e6013ec8575a8b21360930e352 [file] [log] [blame]
/*
* 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();
}
}
}