Copyright (c) 2003, 2017 IBM Corporation and others.
This program and the accompanying materials
are made available under the terms of the Eclipse Public License 2.0
which accompanies this distribution, and is available at
https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
IBM Corporation - initial API and implementation
/*******************************************************************************
* Copyright (c) 2003, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.internal.serviceregistry;
import java.util.Dictionary;
import org.osgi.framework.*;
A reference to a service.
The Framework returns ServiceReference
objects from the
BundleContext.getServiceReference
and
BundleContext.getServiceReferences
methods.
A ServiceReference
object may be shared between bundles and
can be used to examine the properties of the service and to get the service
object.
Every service registered in the Framework has a unique
ServiceRegistration
object and may have multiple, distinct
ServiceReference
objects referring to it.
ServiceReference
objects associated with a
ServiceRegistration
object have the same hashCode
and are considered equal (more specifically, their equals()
method will return true
when compared).
If the same service object is registered multiple times,
ServiceReference
objects associated with different
ServiceRegistration
objects are not equal.
See Also: - getServiceReference.getServiceReference
- BundleContext.getServiceReferences
- BundleContext.getService
@ThreadSafe
/**
* A reference to a service.
*
* <p>
* The Framework returns <code>ServiceReference</code> objects from the
* <code>BundleContext.getServiceReference</code> and
* <code>BundleContext.getServiceReferences</code> methods.
* <p>
* A <code>ServiceReference</code> object may be shared between bundles and
* can be used to examine the properties of the service and to get the service
* object.
* <p>
* Every service registered in the Framework has a unique
* <code>ServiceRegistration</code> object and may have multiple, distinct
* <code>ServiceReference</code> objects referring to it.
* <code>ServiceReference</code> objects associated with a
* <code>ServiceRegistration</code> object have the same <code>hashCode</code>
* and are considered equal (more specifically, their <code>equals()</code>
* method will return <code>true</code> when compared).
* <p>
* If the same service object is registered multiple times,
* <code>ServiceReference</code> objects associated with different
* <code>ServiceRegistration</code> objects are not equal.
*
* @see BundleContext#getServiceReference
* @see BundleContext#getServiceReferences
* @see BundleContext#getService
* @ThreadSafe
*/
public class ServiceReferenceImpl<S> implements ServiceReference<S> {
Registered Service object. /** Registered Service object. */
private final ServiceRegistrationImpl<S> registration;
Construct a reference.
/**
* Construct a reference.
*
*/
ServiceReferenceImpl(ServiceRegistrationImpl<S> registration) {
this.registration = registration;
/* We must not dereference registration in the constructor
* since it is "leaked" to us in the ServiceRegistrationImpl
* constructor.
*/
}
Returns the property value to which the specified property key is mapped
in the properties Dictionary
object of the service
referenced by this ServiceReference
object.
Property keys are case-insensitive.
This method must continue to return property values after the service has
been unregistered. This is so references to unregistered services (for
example, ServiceReference
objects stored in the log) can
still be interrogated.
Params: - key – The property key.
Returns: The property value to which the key is mapped; null
if there is no property named after the key.
/**
* Returns the property value to which the specified property key is mapped
* in the properties <code>Dictionary</code> object of the service
* referenced by this <code>ServiceReference</code> object.
*
* <p>
* Property keys are case-insensitive.
*
* <p>
* This method must continue to return property values after the service has
* been unregistered. This is so references to unregistered services (for
* example, <code>ServiceReference</code> objects stored in the log) can
* still be interrogated.
*
* @param key The property key.
* @return The property value to which the key is mapped; <code>null</code>
* if there is no property named after the key.
*/
@Override
public Object getProperty(String key) {
return registration.getProperty(key);
}
Returns an array of the keys in the properties Dictionary
object of the service referenced by this ServiceReference
object.
This method will continue to return the keys after the service has been
unregistered. This is so references to unregistered services (for
example, ServiceReference
objects stored in the log) can
still be interrogated.
This method is case-preserving ; this means that every key in the
returned array must have the same case as the corresponding key in the
properties Dictionary
that was passed to the BundleContext.registerService(String[], Object, Dictionary<String,?>)
or ServiceRegistration.setProperties
methods.
Returns: An array of property keys.
/**
* Returns an array of the keys in the properties <code>Dictionary</code>
* object of the service referenced by this <code>ServiceReference</code>
* object.
*
* <p>
* This method will continue to return the keys after the service has been
* unregistered. This is so references to unregistered services (for
* example, <code>ServiceReference</code> objects stored in the log) can
* still be interrogated.
*
* <p>
* This method is <i>case-preserving </i>; this means that every key in the
* returned array must have the same case as the corresponding key in the
* properties <code>Dictionary</code> that was passed to the
* {@link BundleContext#registerService(String[],Object,java.util.Dictionary)}
* or {@link ServiceRegistration#setProperties} methods.
*
* @return An array of property keys.
*/
@Override
public String[] getPropertyKeys() {
return registration.getPropertyKeys();
}
Returns the bundle that registered the service referenced by this
ServiceReference
object.
This method must return null
when the service has been
unregistered. This can be used to determine if the service has been
unregistered.
See Also: Returns: The bundle that registered the service referenced by this
ServiceReference
object; null
if
that service has already been unregistered.
/**
* Returns the bundle that registered the service referenced by this
* <code>ServiceReference</code> object.
*
* <p>
* This method must return <code>null</code> when the service has been
* unregistered. This can be used to determine if the service has been
* unregistered.
*
* @return The bundle that registered the service referenced by this
* <code>ServiceReference</code> object; <code>null</code> if
* that service has already been unregistered.
* @see BundleContext#registerService(String[],Object,java.util.Dictionary)
*/
@Override
public Bundle getBundle() {
return registration.getBundle();
}
Returns the bundles that are using the service referenced by this
ServiceReference
object. Specifically, this method returns
the bundles whose usage count for that service is greater than zero.
Returns: An array of bundles whose usage count for the service referenced
by this ServiceReference
object is greater than
zero; null
if no bundles are currently using that
service. Since: 1.1
/**
* Returns the bundles that are using the service referenced by this
* <code>ServiceReference</code> object. Specifically, this method returns
* the bundles whose usage count for that service is greater than zero.
*
* @return An array of bundles whose usage count for the service referenced
* by this <code>ServiceReference</code> object is greater than
* zero; <code>null</code> if no bundles are currently using that
* service.
*
* @since 1.1
*/
@Override
public Bundle[] getUsingBundles() {
return registration.getUsingBundles();
}
Tests if the bundle that registered the service referenced by this
ServiceReference
and the specified bundle use the same
source for the package of the specified class name.
This method performs the following checks:
- Get the package name from the specified class name.
- For the bundle that registered the service referenced by this
ServiceReference
(registrant bundle); find the source for
the package. If no source is found then return true
if the
registrant bundle is equal to the specified bundle; otherwise return
false
.
- If the package source of the registrant bundle is equal to the
package source of the specified bundle then return
true
;
otherwise return false
.
Params: - bundle – The
Bundle
object to check. - className – The class name to check.
Returns: true
if the bundle which registered the service
referenced by this ServiceReference
and the
specified bundle use the same source for the package of the
specified class name. Otherwise false
is returned.Since: 1.3
/**
* Tests if the bundle that registered the service referenced by this
* <code>ServiceReference</code> and the specified bundle use the same
* source for the package of the specified class name.
* <p>
* This method performs the following checks:
* <ol>
* <li>Get the package name from the specified class name.</li>
* <li>For the bundle that registered the service referenced by this
* <code>ServiceReference</code> (registrant bundle); find the source for
* the package. If no source is found then return <code>true</code> if the
* registrant bundle is equal to the specified bundle; otherwise return
* <code>false</code>.</li>
* <li>If the package source of the registrant bundle is equal to the
* package source of the specified bundle then return <code>true</code>;
* otherwise return <code>false</code>.</li>
* </ol>
*
* @param bundle The <code>Bundle</code> object to check.
* @param className The class name to check.
* @return <code>true</code> if the bundle which registered the service
* referenced by this <code>ServiceReference</code> and the
* specified bundle use the same source for the package of the
* specified class name. Otherwise <code>false</code> is returned.
*
* @since 1.3
*/
@Override
public boolean isAssignableTo(Bundle bundle, String className) {
return registration.isAssignableTo(bundle, className);
}
Compares this ServiceReference
with the specified
ServiceReference
for order.
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.
Params: - object – The
ServiceReference
to be compared.
Returns: Returns a negative integer, zero, or a positive integer if this
ServiceReference
is less than, equal to, or
greater than the specified ServiceReference
. Since: 1.4
/**
* Compares this <code>ServiceReference</code> with the specified
* <code>ServiceReference</code> for order.
*
* <p>
* If this <code>ServiceReference</code> and the specified
* <code>ServiceReference</code> have the same
* {@link Constants#SERVICE_ID service id} they are equal. This
* <code>ServiceReference</code> is less than the specified
* <code>ServiceReference</code> if it has a lower
* {@link Constants#SERVICE_RANKING service ranking} and greater if it has a
* higher service ranking. Otherwise, if this <code>ServiceReference</code>
* and the specified <code>ServiceReference</code> have the same
* {@link Constants#SERVICE_RANKING service ranking}, this
* <code>ServiceReference</code> is less than the specified
* <code>ServiceReference</code> if it has a higher
* {@link Constants#SERVICE_ID service id} and greater if it has a lower
* service id.
*
* @param object The <code>ServiceReference</code> to be compared.
* @return Returns a negative integer, zero, or a positive integer if this
* <code>ServiceReference</code> is less than, equal to, or
* greater than the specified <code>ServiceReference</code>.
* @since 1.4
*/
@Override
public int compareTo(Object object) {
ServiceRegistrationImpl<?> other = ((ServiceReferenceImpl<?>) object).registration;
final int thisRanking = registration.getRanking();
final int otherRanking = other.getRanking();
if (thisRanking != otherRanking) {
if (thisRanking < otherRanking) {
return -1;
}
return 1;
}
final long thisId = registration.getId();
final long otherId = other.getId();
if (thisId == otherId) {
return 0;
}
if (thisId < otherId) {
return 1;
}
return -1;
}
Returns a hash code value for the object.
Returns: a hash code value for this object.
/**
* Returns a hash code value for the object.
*
* @return a hash code value for this object.
*/
@Override
public int hashCode() {
return registration.hashCode();
}
Indicates whether some other object is "equal to" this one.
Params: - obj – the reference object with which to compare.
Returns: true
if this object is the same as the obj
argument; false
otherwise.
/**
* Indicates whether some other object is "equal to" this one.
*
* @param obj the reference object with which to compare.
* @return <code>true</code> if this object is the same as the obj
* argument; <code>false</code> otherwise.
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof ServiceReferenceImpl<?>)) {
return false;
}
ServiceReferenceImpl<?> other = (ServiceReferenceImpl<?>) obj;
return registration == other.registration;
}
Return a string representation of this reference.
Returns: String
/**
* Return a string representation of this reference.
*
* @return String
*/
@Override
public String toString() {
return registration.toString();
}
Return the ServiceRegistrationImpl for this ServiceReferenceImpl.
Returns: The ServiceRegistrationImpl for this ServiceReferenceImpl.
/**
* Return the ServiceRegistrationImpl for this ServiceReferenceImpl.
*
* @return The ServiceRegistrationImpl for this ServiceReferenceImpl.
*/
public ServiceRegistrationImpl<S> getRegistration() {
return registration;
}
Return the classes under which the referenced service was registered.
Returns: array of class names.
/**
* Return the classes under which the referenced service was registered.
*
* @return array of class names.
*/
String[] getClasses() {
return registration.getClasses();
}
Returns a copy of the properties of the service referenced by this ServiceReference
object. This method will continue to return the properties after the service has been unregistered. This is so references to unregistered services (for example, ServiceReference
objects stored in the log) can still be interrogated.
The returned Dictionary
object:
- Must map property values by using property keys in a
case-insensitive manner.
- Must return property keys is a case-preserving manner. This means that the keys must have the same case as the corresponding key in the properties
Dictionary
that was passed to the BundleContext.registerService(String[], Object, Dictionary<String,?>)
or ServiceRegistration.setProperties(Dictionary)
methods.
- Is the property of the caller and can be modified by the caller but any changes are not reflected in the properties of the service.
ServiceRegistration.setProperties(Dictionary)
must be called to modify the properties of the service.
Returns: A copy of the properties of the service referenced by this ServiceReference
object Since: 1.9
/**
* Returns a copy of the properties of the service referenced by this
* {@code ServiceReference} object.
* <p>
* This method will continue to return the properties after the service has
* been unregistered. This is so references to unregistered services (for
* example, {@code ServiceReference} objects stored in the log) can still be
* interrogated.
* <p>
* The returned {@code Dictionary} object:
* <ul>
* <li>Must map property values by using property keys in a
* <i>case-insensitive manner</i>.</li>
* <li>Must return property keys is a <i>case-preserving</i> manner. This
* means that the keys must have the same case as the corresponding key in
* the properties {@code Dictionary} that was passed to the
* {@link BundleContext#registerService(String[],Object,Dictionary)} or
* {@link ServiceRegistration#setProperties(Dictionary)} methods.</li>
* <li>Is the property of the caller and can be modified by the caller but
* any changes are not reflected in the properties of the service.
* {@link ServiceRegistration#setProperties(Dictionary)} must be called to
* modify the properties of the service.</li>
* </ul>
*
* @return A copy of the properties of the service referenced by this
* {@code ServiceReference} object
* @since 1.9
*/
@Override
public Dictionary<String, Object> getProperties() {
return registration.getPropertiesCopy();
}
}