/******************************************************************************
* 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.mock;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
/**
* ServiceReference mock.
*
* <p/> This mock tries to adhere to the OSGi spec as much as possible by
* providing the mandatory serviceId properties such as
* {@link Constants#SERVICE_ID}, {@link Constants#OBJECTCLASS} and
* {@link Constants#SERVICE_RANKING}.
*
* @author Costin Leau
*
*/
public class MockServiceReference implements ServiceReference {
private Bundle bundle;
private static long GLOBAL_SERVICE_ID = System.currentTimeMillis();
private long serviceId;
// private ServiceRegistration registration;
private Dictionary properties;
private String[] objectClass = new String[] { Object.class.getName() };
/**
* Constructs a new <code>MockServiceReference</code> instance using
* defaults.
*/
public MockServiceReference() {
this(null, null, null);
}
/**
* Constructs a new <code>MockServiceReference</code> instance associated
* with the given bundle.
*
* @param bundle associated reference bundle
*/
public MockServiceReference(Bundle bundle) {
this(bundle, null, null);
}
/**
* Constructs a new <code>MockServiceReference</code> instance matching
* the given class namess.
*
* @param classes associated class names
*/
public MockServiceReference(String[] classes) {
this(null, null, null, classes);
}
/**
* Constructs a new <code>MockServiceReference</code> instance associated
* with the given bundle and matching the given class names.
*
* @param bundle associated bundle
* @param classes matching class names
*/
public MockServiceReference(Bundle bundle, String[] classes) {
this(bundle, null, null, classes);
}
/**
* Constructs a new <code>MockServiceReference</code> instance associated
* with the given service registration.
*
* @param registration service registration
*/
public MockServiceReference(ServiceRegistration registration) {
this(null, null, registration);
}
/**
* Constructs a new <code>MockServiceReference</code> instance associated
* with the given bundle, service registration and having the given service
* properties.
*
* @param bundle associated bundle
* @param properties reference properties
* @param registration associated service registrations
*/
public MockServiceReference(Bundle bundle, Dictionary properties, ServiceRegistration registration) {
this(bundle, properties, registration, null);
}
/**
* Constructs a new <code>MockServiceReference</code> instance. This
* constructor gives access to all the parameters of the mock service
* reference such as associated bundle, reference properties, service
* registration and reference class names.
*
* @param bundle associated bundle
* @param properties reference properties
* @param registration service registration
* @param classes reference class names
*/
public MockServiceReference(Bundle bundle, Dictionary properties, ServiceRegistration registration, String[] classes) {
this.bundle = (bundle == null ? new MockBundle() : bundle);
// this.registration = (registration == null ? new
// MockServiceRegistration() :
// registration);
this.properties = (properties == null ? new Hashtable() : properties);
if (classes != null && classes.length > 0)
this.objectClass = classes;
addMandatoryProperties(this.properties);
}
private void addMandatoryProperties(Dictionary dict) {
// add mandatory properties
Object id = dict.get(Constants.SERVICE_ID);
if (id == null || !(id instanceof Long))
dict.put(Constants.SERVICE_ID, new Long(GLOBAL_SERVICE_ID++));
if (dict.get(Constants.OBJECTCLASS) == null)
dict.put(Constants.OBJECTCLASS, objectClass);
Object ranking = dict.get(Constants.SERVICE_RANKING);
if (ranking == null || !(ranking instanceof Integer))
dict.put(Constants.SERVICE_RANKING, new Integer(0));
serviceId = ((Long) dict.get(Constants.SERVICE_ID)).longValue();
}
public Bundle getBundle() {
return bundle;
}
public Object getProperty(String key) {
return properties.get(key);
}
public String[] getPropertyKeys() {
String[] keys = new String[this.properties.size()];
Enumeration ks = this.properties.keys();
for (int i = 0; i < keys.length && ks.hasMoreElements(); i++) {
keys[i] = (String) ks.nextElement();
}
return keys;
}
public Bundle[] getUsingBundles() {
return new Bundle[] {};
}
public boolean isAssignableTo(Bundle bundle, String className) {
return false;
}
/**
* Sets the properties associated with this reference.
*
* @param properties
*/
public void setProperties(Dictionary properties) {
if (properties != null) {
// copy mandatory properties
properties.put(Constants.SERVICE_ID, this.properties.get(Constants.SERVICE_ID));
properties.put(Constants.OBJECTCLASS, this.properties.get(Constants.OBJECTCLASS));
// optional property
if (properties.get(Constants.SERVICE_RANKING) == null)
properties.put(Constants.SERVICE_RANKING, this.properties.get(Constants.SERVICE_RANKING));
this.properties = properties;
}
}
/**
* Two mock service references are equal if they contain the same service
* id.
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj instanceof MockServiceReference) {
return this.hashCode() == ((MockServiceReference) obj).hashCode();
}
return false;
}
/**
* {@inheritDoc}
*
* Returns a hash code based on the class and service id.
*/
public int hashCode() {
return MockServiceReference.class.hashCode() * 13 + (int) serviceId;
}
public String toString() {
return "mock service reference [owning bundle id=" + bundle.hashCode() + "|props : " + properties + "]";
}
public int compareTo(Object reference) {
ServiceReference other = (ServiceReference) reference;
// compare based on service ranking
Object ranking = this.getProperty(Constants.SERVICE_RANKING);
// if the property is not supplied or of incorrect type, use the default
int rank1 = ((ranking != null && ranking instanceof Integer) ? ((Integer) ranking).intValue() : 0);
ranking = other.getProperty(Constants.SERVICE_RANKING);
int rank2 = ((ranking != null && ranking instanceof Integer) ? ((Integer) ranking).intValue() : 0);
int result = rank1 - rank2;
if (result == 0) {
long id1 = serviceId;
long id2 = ((Long) other.getProperty(Constants.SERVICE_ID)).longValue();
// when comparing IDs, make sure to return inverse results (i.e. lower
// id, means higher service)
return (int) (id2 - id1);
}
return result;
}
}