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();