All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.osgi.internal.serviceregistry.ServiceReferenceImpl Maven / Gradle / Ivy

There is a newer version: 1.9.22.1
Show newest version
/*******************************************************************************
 * 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.eclipse.osgi.internal.framework.DTOBuilder;
import org.osgi.framework.AdaptPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.dto.ServiceReferenceDTO;

/**
 * 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 BundleContext#getServiceReference * @see BundleContext#getServiceReferences * @see BundleContext#getService * @ThreadSafe */ public class ServiceReferenceImpl implements ServiceReference { /** Registered Service object. */ private final ServiceRegistrationImpl registration; /** * Construct a reference. * */ ServiceReferenceImpl(ServiceRegistrationImpl 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. * * @param key The property key. * @return The property value to which the key is mapped; null * 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 * {@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. * * @return The bundle that registered the service referenced by this * ServiceReference object; null 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. * * @return 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 */ @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: *

    *
  1. Get the package name from the specified class name.
  2. *
  3. 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.
  4. *
  5. If the package source of the registrant bundle is equal to the * package source of the specified bundle then return true; * otherwise return false.
  6. *
* * @param bundle The Bundle object to check. * @param className The class name to check. * @return 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 */ @Override public boolean isAssignableTo(Bundle bundle, String className) { return registration.isAssignableTo(bundle, className, true); } /** * Compares this ServiceReference with the specified * ServiceReference for order. * *

* If this ServiceReference and the specified * ServiceReference have the same * {@link Constants#SERVICE_ID service id} they are equal. This * ServiceReference is less than the specified * ServiceReference if it has a lower * {@link Constants#SERVICE_RANKING service ranking} and greater if it has a * higher service ranking. Otherwise, if this ServiceReference * and the specified ServiceReference have the same * {@link Constants#SERVICE_RANKING service ranking}, this * ServiceReference is less than the specified * ServiceReference if it has a higher * {@link Constants#SERVICE_ID service id} and greater if it has a lower * service id. * * @param object The ServiceReference to be compared. * @return 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 */ @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. * * @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. * * @param obj the reference object with which to compare. * @return true if this object is the same as the obj * argument; false 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. * * @return String */ @Override public String toString() { return registration.toString(); } /** * Return the ServiceRegistrationImpl for this ServiceReferenceImpl. * * @return The ServiceRegistrationImpl for this ServiceReferenceImpl. */ public ServiceRegistrationImpl getRegistration() { return registration; } /** * 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 * {@code 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, {@code ServiceReference} objects stored in the log) can still be * interrogated. *

* The returned {@code 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 {@code Dictionary} that was passed to the * {@link BundleContext#registerService(String[],Object,Dictionary)} or * {@link 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. * {@link ServiceRegistration#setProperties(Dictionary)} must be called to * modify the properties of the service.
  • *
* * @return A copy of the properties of the service referenced by this * {@code ServiceReference} object * @since 1.9 */ @Override public Dictionary getProperties() { return registration.getPropertiesCopy(); } @SuppressWarnings("unchecked") @Override public A adapt(Class type) { checkAdaptPermission(type); if (ServiceReferenceDTO.class.equals(type)) { return (A) DTOBuilder.newServiceReferenceDTO(this); } return null; } private void checkAdaptPermission(Class adapterType) { SecurityManager sm = System.getSecurityManager(); if (sm == null) { return; } sm.checkPermission(new AdaptPermission(adapterType.getName(), registration.getRegisteringBundle(), AdaptPermission.ADAPT)); } }