/******************************************************************************* * Copyright (c) 2013, 2016 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.IdentityHashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.osgi.internal.debug.Debug; import org.eclipse.osgi.internal.framework.BundleContextImpl; import org.eclipse.osgi.internal.messages.Msg; import org.osgi.framework.*; /** * This class represents the use of a service by a bundle. One is created for each * service acquired by a bundle. * *
* This class manages a prototype service factory.
*
* @ThreadSafe
*/
public class PrototypeServiceFactoryUse extends ServiceFactoryUse {
/** Service objects returned by PrototypeServiceFactory.getService() and their use count. */
/* @GuardedBy("this") */
private final Map serviceObjects;
/**
* Constructs a service use encapsulating the service object.
*
* @param context bundle getting the service
* @param registration ServiceRegistration of the service
*/
PrototypeServiceFactoryUse(BundleContextImpl context, ServiceRegistrationImpl registration) {
super(context, registration);
this.serviceObjects = new IdentityHashMap<>();
}
/**
* Create a new service object for the service.
*
*
* * @return The service object. */ /* @GuardedBy("this") */ @Override S newServiceObject() { assert Thread.holdsLock(this); if (debug.DEBUG_SERVICES) { Debug.println("getServiceObject[factory=" + registration.getBundle() + "](" + context.getBundleImpl() + "," + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } final S service = factoryGetService(); if (service == null) { return null; } AtomicInteger useCount = serviceObjects.get(service); if (useCount == null) { serviceObjects.put(service, new AtomicInteger(1)); } else { if (useCount.getAndIncrement() == Integer.MAX_VALUE) { useCount.getAndDecrement(); throw new ServiceException(Msg.SERVICE_USE_OVERFLOW); } } return service; } /** * Release a service object for the service. * * @param service The service object to release. * @return true if the service was released; otherwise false. * @throws IllegalArgumentException If the specified service was not * provided by this object. */ /* @GuardedBy("this") */ @Override boolean releaseServiceObject(final S service) { assert Thread.holdsLock(this); if ((service == null) || !serviceObjects.containsKey(service)) { throw new IllegalArgumentException(Msg.SERVICE_OBJECTS_UNGET_ARGUMENT_EXCEPTION); } if (debug.DEBUG_SERVICES) { Debug.println("ungetService[factory=" + registration.getBundle() + "](" + context.getBundleImpl() + "," + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } AtomicInteger useCount = serviceObjects.get(service); if (useCount.decrementAndGet() < 1) { serviceObjects.remove(service); factoryUngetService(service); } return true; } /** * Release all uses of the service and reset the use count to zero. * *