/****************************************************************************** * Copyright (c) 2006, 2010 VMware Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0 * is available at http://www.opensource.org/licenses/apache2.0.php. * You may elect to redistribute this code under either of these licenses. * * Contributors: * VMware Inc. *****************************************************************************/ package org.eclipse.gemini.blueprint.service.importer.support.internal.util; import java.io.Serializable; import java.util.Comparator; import org.eclipse.gemini.blueprint.service.importer.ImportedOsgiServiceProxy; import org.eclipse.gemini.blueprint.util.OsgiServiceReferenceUtils; import org.osgi.framework.ServiceReference; /** * Default comparator for sorted collections. It uses the service id property of an OSGi service to determine the order. * Thus, by using this comparator, the services added to a collection will be sorted in the order in which they are * published to the OSGi platform. * * <p/> This comparator version, provides <i>natural</i> ordering for service references for pre OSGI 4.1 platforms, * using the contract from OSGi 4.1 spec: * * <blockquote> If this ServiceReference and the specified ServiceReference have the same service id they are equal. * This ServiceReference is less than the specified ServiceReference if it has a lower service ranking and greater if it * has a higher service ranking. Otherwise, if this ServiceReference and the specified ServiceReference have the same * service ranking, this ServiceReference is less than the specified ServiceReference if it has a higher service id and * greater if it has a lower service id. </blockquote> * * @see Comparator * @author Costin Leau * */ public class ServiceReferenceComparator implements Comparator, Serializable { private static final long serialVersionUID = 7552328574956669890L; private static final int hashCode = ServiceReferenceComparator.class.hashCode() * 13; public int compare(Object o1, Object o2) { ServiceReference ref1, ref2; if (o1 == null || o2 == null) { if (o1 == o2) return 0; else throw new ClassCastException("Cannot compare null with a non-null object"); } // look first for service references if (o1 instanceof ServiceReference) { ref1 = (ServiceReference) o1; } else { ImportedOsgiServiceProxy obj1 = (ImportedOsgiServiceProxy) o1; ref1 = obj1.getServiceReference(); } if (o2 instanceof ServiceReference) { ref2 = (ServiceReference) o2; } else { ImportedOsgiServiceProxy obj2 = (ImportedOsgiServiceProxy) o2; ref2 = obj2.getServiceReference(); } return compare(ref1, ref2); } private int compare(ServiceReference ref1, ServiceReference ref2) { // compare based on service ranking int rank1 = OsgiServiceReferenceUtils.getServiceRanking(ref1); int rank2 = OsgiServiceReferenceUtils.getServiceRanking(ref2); int result = rank1 - rank2; if (result == 0) { long id1 = OsgiServiceReferenceUtils.getServiceId(ref1); long id2 = OsgiServiceReferenceUtils.getServiceId(ref2); // when comparing IDs, make sure to return inverse results (i.e. lower // id, means higher service) return (int) (id2 - id1); } return result; } public boolean equals(Object obj) { return (this == obj || obj instanceof ServiceReferenceComparator); } public int hashCode() { return hashCode; } }