Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBJ Hargrave2016-02-01 16:33:03 -0500
committerThomas Watson2017-06-16 08:38:08 -0400
commita5083a05d9fbc19d8281009b4a3006f9625e0246 (patch)
treeaf02d4f8afdb5aa93a0bfc95123f3279476d63dc
parentad0a1c7723fd796be14047262db64e50a0c06e9b (diff)
downloadrt.equinox.framework-a5083a05d9fbc19d8281009b4a3006f9625e0246.tar.gz
rt.equinox.framework-a5083a05d9fbc19d8281009b4a3006f9625e0246.tar.xz
rt.equinox.framework-a5083a05d9fbc19d8281009b4a3006f9625e0246.zip
Bug 486947: Use count objects returned by PrototypeServiceFactory
For OSGi R6 the framework does not use count the 'same' objects that get returned by a PrototypeServiceFactory. When a bundle calls ServiceObjects.getService() multiple times a PrototypeServiceFactory may return the 'same' object multiple times. The bundle then may call ServiceObjects.ungetService(S) with the 'same' service object multiple times. Currently the framework implementation will throw an IllegalArgumentException on the second call to ungetService(S) if the 'same' service object is passed in more than once. This is because we do not use count the service object for ServiceObjects.getService() The core expert group has decided the framework must use count the service objects returned by ServiceObjects.getService() and decrement the use count on calls to ServiceObjects.ungetService(S).
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/PrototypeServiceFactoryUse.java32
1 files changed, 23 insertions, 9 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/PrototypeServiceFactoryUse.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/PrototypeServiceFactoryUse.java
index 661021b5a..52d935d01 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/PrototypeServiceFactoryUse.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/PrototypeServiceFactoryUse.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 IBM Corporation and others.
+ * Copyright (c) 2013, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,7 +11,9 @@
package org.eclipse.osgi.internal.serviceregistry;
-import java.util.*;
+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;
@@ -27,9 +29,9 @@ import org.osgi.framework.*;
* @ThreadSafe
*/
public class PrototypeServiceFactoryUse<S> extends ServiceFactoryUse<S> {
- /** Service objects returned by PrototypeServiceFactory.getService() */
+ /** Service objects returned by PrototypeServiceFactory.getService() and their use count. */
/* @GuardedBy("this") */
- private final Set<S> serviceObjects;
+ private final Map<S, AtomicInteger> serviceObjects;
/**
* Constructs a service use encapsulating the service object.
@@ -39,7 +41,7 @@ public class PrototypeServiceFactoryUse<S> extends ServiceFactoryUse<S> {
*/
PrototypeServiceFactoryUse(BundleContextImpl context, ServiceRegistrationImpl<S> registration) {
super(context, registration);
- this.serviceObjects = Collections.newSetFromMap(new IdentityHashMap<S, Boolean>());
+ this.serviceObjects = new IdentityHashMap<S, AtomicInteger>();
}
/**
@@ -60,7 +62,15 @@ public class PrototypeServiceFactoryUse<S> extends ServiceFactoryUse<S> {
if (service == null) {
return null;
}
- serviceObjects.add(service);
+ 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;
}
@@ -76,13 +86,17 @@ public class PrototypeServiceFactoryUse<S> extends ServiceFactoryUse<S> {
@Override
boolean releaseServiceObject(final S service) {
assert Thread.holdsLock(this);
- if ((service == null) || !serviceObjects.remove(service)) {
+ 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$
}
- factoryUngetService(service);
+ AtomicInteger useCount = serviceObjects.get(service);
+ if (useCount.decrementAndGet() < 1) {
+ serviceObjects.remove(service);
+ factoryUngetService(service);
+ }
return true;
}
@@ -99,7 +113,7 @@ public class PrototypeServiceFactoryUse<S> extends ServiceFactoryUse<S> {
@Override
void release() {
super.release();
- for (S service : serviceObjects) {
+ for (S service : serviceObjects.keySet()) {
if (debug.DEBUG_SERVICES) {
Debug.println("releaseService[factory=" + registration.getBundle() + "](" + context.getBundleImpl() + "," + registration + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}

Back to the top