| /******************************************************************************* |
| * Copyright (c) 2013 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 org.eclipse.osgi.internal.framework.BundleContextImpl; |
| import org.eclipse.osgi.internal.messages.Msg; |
| import org.osgi.framework.*; |
| |
| /** |
| * ServiceObjects implementation. |
| */ |
| public class ServiceObjectsImpl<S> implements ServiceObjects<S> { |
| /** Service registration */ |
| private final ServiceRegistrationImpl<S> registration; |
| /** Reference to service */ |
| private final ServiceReference<S> reference; |
| /** BundleContext associated with this service use */ |
| private final BundleContextImpl user; |
| |
| /** |
| * Constructs a service objects encapsulating the service object. |
| * |
| * @param user bundle getting the service |
| * @param registration ServiceRegistration of the service |
| */ |
| ServiceObjectsImpl(BundleContextImpl user, ServiceRegistrationImpl<S> registration) { |
| this.registration = registration; |
| this.reference = registration.getReference(); |
| this.user = user; |
| } |
| |
| /** |
| * Returns a service object for the {@link #getServiceReference() |
| * referenced} service. |
| * |
| * <p> |
| * This {@code ServiceObjects} object can be used to obtain multiple service |
| * objects for the referenced service if the service has |
| * {@link Constants#SCOPE_PROTOTYPE prototype} scope. If the referenced |
| * service has {@link Constants#SCOPE_SINGLETON singleton} or |
| * {@link Constants#SCOPE_BUNDLE bundle} scope, this method behaves the same |
| * as calling the {@link BundleContext#getService(ServiceReference)} method |
| * for the referenced service. That is, only one, use-counted service object |
| * is available from this {@link ServiceObjects} object. |
| * |
| * <p> |
| * This method will always return {@code null} when the referenced service |
| * has been unregistered. |
| * |
| * <p> |
| * For a prototype scope service, the following steps are required to get |
| * the service object: |
| * <ol> |
| * <li>If the referenced service has been unregistered, {@code null} is |
| * returned.</li> |
| * <li>The |
| * {@link PrototypeServiceFactory#getService(Bundle, ServiceRegistration)} |
| * method is called to create a service object for the caller.</li> |
| * <li>If the service object returned by the {@code PrototypeServiceFactory} |
| * object is {@code null}, not an {@code instanceof} all the classes named |
| * when the service was registered or the {@code PrototypeServiceFactory} |
| * object throws an exception, {@code null} is returned and a Framework |
| * event of type {@link FrameworkEvent#ERROR} containing a |
| * {@link ServiceException} describing the error is fired.</li> |
| * <li>The service object is returned.</li> |
| * </ol> |
| * |
| * @return A service object for the referenced service or {@code null} if |
| * the service is not registered, the service object returned by a |
| * {@code ServiceFactory} does not implement the classes under which |
| * it was registered or the {@code ServiceFactory} threw an |
| * exception. |
| * @throws IllegalStateException If the BundleContext used to create this |
| * {@code ServiceObjects} object is no longer valid. |
| * @see #ungetService(Object) |
| */ |
| @Override |
| public S getService() { |
| user.checkValid(); |
| return registration.getService(user, ServiceConsumer.prototypeConsumer); |
| } |
| |
| /** |
| * Releases a service object for the {@link #getServiceReference() |
| * referenced} service. |
| * |
| * <p> |
| * This {@code ServiceObjects} object can be used to obtain multiple service |
| * objects for the referenced service if the service has |
| * {@link Constants#SCOPE_PROTOTYPE prototype} scope. If the referenced |
| * service has {@link Constants#SCOPE_SINGLETON singleton} or |
| * {@link Constants#SCOPE_BUNDLE bundle} scope, this method behaves the same |
| * as calling the {@link BundleContext#ungetService(ServiceReference)} |
| * method for the referenced service. That is, only one, use-counted service |
| * object is available from this {@link ServiceObjects} object. |
| * |
| * <p> |
| * For a prototype scope service, the following steps are required to |
| * release the service object: |
| * <ol> |
| * <li>If the referenced service has been unregistered, this method returns |
| * without doing anything.</li> |
| * <li>The |
| * {@link PrototypeServiceFactory#ungetService(Bundle, ServiceRegistration, Object)} |
| * method is called to release the specified service object.</li> |
| * </ol> |
| * |
| * <p> |
| * The specified service object must no longer be used and all references to |
| * it should be destroyed after calling this method. |
| * |
| * @param service A service object previously provided by this |
| * {@code ServiceObjects} object. |
| * @throws IllegalStateException If the BundleContext used to create this |
| * {@code ServiceObjects} object is no longer valid. |
| * @throws IllegalArgumentException If the specified service was not |
| * provided by this {@code ServiceObjects} object. |
| * @see #getService() |
| */ |
| @Override |
| public void ungetService(S service) { |
| user.checkValid(); |
| boolean removed = registration.ungetService(user, ServiceConsumer.prototypeConsumer, service); |
| if (!removed) { |
| if (registration.isUnregistered()) { |
| return; |
| } |
| throw new IllegalArgumentException(Msg.SERVICE_OBJECTS_UNGET_ARGUMENT_EXCEPTION); |
| } |
| } |
| |
| /** |
| * Returns the {@link ServiceReference} for the service associated with this |
| * {@code ServiceObjects} object. |
| * |
| * @return The {@link ServiceReference} for the service associated with this |
| * {@code ServiceObjects} object. |
| */ |
| @Override |
| public ServiceReference<S> getServiceReference() { |
| return reference; |
| } |
| } |