FELIX-4950 : [DS][RFC-190] Within a component instance for each reference to the same service the same object needs to be injected
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1689302 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java
index ea41a50..a1be501 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentServiceObjectsHelper.java
@@ -23,6 +23,8 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceObjects;
@@ -31,7 +33,8 @@
/**
- * Utility methods for class handling used by method and field references.
+ * Utility class for handling references using a ComponentServiceObjects
+ * to get services.
*/
public class ComponentServiceObjectsHelper
{
@@ -41,6 +44,8 @@
private final Map<ServiceObjects, List<Object>> services = new HashMap<ServiceObjects, List<Object>>();
+ private final ConcurrentMap<ServiceReference, Object> prototypeInstances = new ConcurrentHashMap<ServiceReference, Object>();
+
public ComponentServiceObjectsHelper(final BundleContext bundleContext)
{
this.bundleContext = bundleContext;
@@ -60,6 +65,7 @@
services.clear();
serviceObjectsMap.clear();
}
+ prototypeInstances.clear();
}
public ComponentServiceObjects getServiceObjects(final ServiceReference<?> ref)
@@ -87,9 +93,11 @@
final ServiceObjects serviceObjects = so;
final List<Object> serviceList = services;
- return new ComponentServiceObjects() {
+ return new ComponentServiceObjects()
+ {
- public Object getService() {
+ public Object getService()
+ {
final Object service = serviceObjects.getService();
if ( service != null )
{
@@ -101,7 +109,8 @@
return service;
}
- public void ungetService(final Object service) {
+ public void ungetService(final Object service)
+ {
boolean remove;
synchronized ( serviceList )
{
@@ -112,7 +121,8 @@
}
}
- public ServiceReference<?> getServiceReference() {
+ public ServiceReference<?> getServiceReference()
+ {
return ref;
}
};
@@ -120,4 +130,23 @@
}
return null;
}
-}
+
+
+ public <T> T getPrototypeRefInstance(final ServiceReference<T> ref, ServiceObjects<T> serviceObjects)
+ {
+ T service = (T) prototypeInstances.get(ref);
+ if ( service == null )
+ {
+ service = serviceObjects.getService();
+ T oldService = (T)prototypeInstances.putIfAbsent(ref, service);
+ if ( oldService != null )
+ {
+ // another thread created the instance already
+ serviceObjects.ungetService(service);
+ service = oldService;
+ }
+ }
+ return service;
+ }
+
+ }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
index fd40ea5..ae2b33c 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
@@ -20,6 +20,8 @@
import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -29,6 +31,7 @@
import org.apache.felix.scr.impl.helper.ReadOnlyDictionary;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceObjects;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentInstance;
import org.osgi.service.log.LogService;
@@ -44,11 +47,11 @@
private final EdgeInfo[] edgeInfos;
- private final ComponentInstance m_componentInstance = new ComponentInstanceImpl(this);
+ private final ComponentInstance m_componentInstance = new ComponentInstanceImpl<S>(this);
private final Bundle m_usingBundle;
- private S m_implementationObject;
+ private volatile S m_implementationObject;
private volatile boolean m_implementationAccessible;
@@ -56,7 +59,7 @@
private final ComponentServiceObjectsHelper serviceObjectsHelper;
- public ComponentContextImpl( SingleComponentManager<S> componentManager, Bundle usingBundle )
+ public ComponentContextImpl( final SingleComponentManager<S> componentManager, final Bundle usingBundle )
{
m_componentManager = componentManager;
m_usingBundle = usingBundle;
@@ -73,7 +76,7 @@
this.serviceObjectsHelper.cleanup();
}
- public Object getComponentServiceObjectsHelper()
+ public ComponentServiceObjectsHelper getComponentServiceObjectsHelper()
{
return this.serviceObjectsHelper;
}
@@ -99,7 +102,7 @@
return edgeInfos[index];
}
- protected SingleComponentManager<S> getComponentManager()
+ protected SingleComponentManager<S> getComponentManager()
{
return m_componentManager;
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java
index 8b0c225..0460881 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java
@@ -44,13 +44,11 @@
}
@Override
- public Object getServiceObjects()
+ public ServiceObjects<T> getServiceObjects()
{
return serviceObjects;
}
-
-
@Override
public T getServiceObject(ComponentContextImpl<S> key)
{
@@ -79,7 +77,7 @@
public boolean getServiceObject(ComponentContextImpl<S> key, BundleContext context,
SimpleLogger logger)
{
- T service = serviceObjects.getService();
+ final T service = key.getComponentServiceObjectsHelper().getPrototypeRefInstance(this.getRef(), serviceObjects);
if ( service == null )
{
setFailed();
@@ -95,6 +93,4 @@
}
return true;
}
-
-
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java
index 435c6ab..da2f1a9 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java
@@ -22,10 +22,11 @@
import org.apache.felix.scr.impl.helper.SimpleLogger;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceObjects;
import org.osgi.framework.ServiceReference;
/**
- * @version $Rev:$ $Date:$
+ * @version $Rev$ $Date$
*/
public abstract class RefPair<S, T>
{
@@ -44,7 +45,7 @@
return ref;
}
- public Object getServiceObjects()
+ public ServiceObjects<T> getServiceObjects()
{
return null;
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/SinglePrototypeRefPair.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/SinglePrototypeRefPair.java
index 901cc79..c460d3d 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/SinglePrototypeRefPair.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/SinglePrototypeRefPair.java
@@ -40,7 +40,7 @@
}
@Override
- public Object getServiceObjects()
+ public ServiceObjects<T> getServiceObjects()
{
return serviceObjects;
}
@@ -55,7 +55,7 @@
public boolean getServiceObject(ComponentContextImpl<S> key, BundleContext context,
SimpleLogger logger)
{
- T service = serviceObjects.getService();
+ final T service = key.getComponentServiceObjectsHelper().getPrototypeRefInstance(this.getRef(), serviceObjects);
if ( service == null )
{
setFailed();