FELIX-4069 synchronize access to service instance map

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1484207 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
index 2c4e84a..4d214aa 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
@@ -19,6 +19,8 @@
 package org.apache.felix.scr.impl.manager;
 
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.IdentityHashMap;
 import java.util.Iterator;
 
@@ -80,13 +82,12 @@
         {
             throw new IllegalStateException( "need write lock (deleteComponent)" );
         }
-        for (Iterator<ComponentContextImpl> i = serviceContexts.values().iterator(); i.hasNext(); )
+        for (ComponentContextImpl componentContext: getComponentContexts() )
         {
-            ComponentContextImpl componentContext = i.next();
             disposeImplementationObject( componentContext, reason );
-            i.remove();
             log( LogService.LOG_DEBUG, "Unset implementation object for component {0} in deleteComponent for reason {1}", new Object[] { getName(), REASONS[ reason ] },  null );
         }
+        serviceContexts.clear();
     }
 
 
@@ -139,12 +140,18 @@
         {
             public void presetComponentContext( ComponentContextImpl<S> componentContext )
             {
-                serviceContexts.put( componentContext.getImplementationObject( false ), componentContext );
+                synchronized ( serviceContexts )
+                {
+                    serviceContexts.put( componentContext.getImplementationObject( false ), componentContext );
+                }
             }
 
             public void resetImplementationObject( S implementationObject )
             {
-                serviceContexts.remove( implementationObject );
+                synchronized ( serviceContexts )
+                {
+                    serviceContexts.remove( implementationObject );
+                }
             }
 
         } );
@@ -180,21 +187,34 @@
         // When the ungetServiceMethod is called, the implementation object must be deactivated
         // private ComponentContext and implementation instances
         final ComponentContextImpl<S> serviceContext;
-        serviceContext = serviceContexts.get( service );
-
-        disposeImplementationObject( serviceContext, ComponentConstants.DEACTIVATION_REASON_DISPOSED );
-        serviceContexts.remove( service );
-        // if this was the last use of the component, go back to REGISTERED state
-        if ( serviceContexts.isEmpty() && getState() == STATE_ACTIVE )
+        synchronized ( serviceContexts )
         {
-            changeState( Registered.getInstance() );
-            unsetDependenciesCollected();
+            serviceContext = serviceContexts.get( service );
+        }
+        disposeImplementationObject( serviceContext, ComponentConstants.DEACTIVATION_REASON_DISPOSED );
+        synchronized ( serviceContexts )
+        {
+            serviceContexts.remove( service );
+            // if this was the last use of the component, go back to REGISTERED state
+            if ( serviceContexts.isEmpty() && getState() == STATE_ACTIVE )
+            {
+                changeState( Registered.getInstance() );
+                unsetDependenciesCollected();
+            }
+        }
+    }
+
+    private Collection<ComponentContextImpl> getComponentContexts()
+    {
+        synchronized ( serviceContexts )
+        {
+            return new ArrayList<ComponentContextImpl>( serviceContexts.values() );
         }
     }
 
     <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount )
     {
-        for ( ComponentContextImpl<S> cc : serviceContexts.values() )
+        for ( ComponentContextImpl<S> cc : getComponentContexts() )
         {
             dependencyManager.invokeBindMethod( cc.getImplementationObject( false ), refPair, trackingCount, cc.getEdgeInfo( dependencyManager ) );
         }
@@ -202,7 +222,7 @@
 
     <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount )
     {
-        for ( ComponentContextImpl<S> cc : serviceContexts.values() )
+        for ( ComponentContextImpl<S> cc : getComponentContexts() )
         {
             dependencyManager.invokeUpdatedMethod( cc.getImplementationObject( false ), refPair, trackingCount, cc.getEdgeInfo( dependencyManager ) );
         }
@@ -210,7 +230,7 @@
 
     <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> oldRefPair, int trackingCount )
     {
-        for ( ComponentContextImpl<S> cc : serviceContexts.values() )
+        for ( ComponentContextImpl<S> cc : getComponentContexts() )
         {
             dependencyManager.invokeUnbindMethod( cc.getImplementationObject( false ), oldRefPair, trackingCount, cc.getEdgeInfo( dependencyManager ) );
         }
@@ -220,7 +240,7 @@
     {
         ModifiedMethod modifiedMethod = getComponentMethods().getModifiedMethod();
         MethodResult result = MethodResult.VOID;
-        for ( ComponentContextImpl componentContext : serviceContexts.values() )
+        for ( ComponentContextImpl componentContext : getComponentContexts() )
         {
             Object instance = componentContext.getImplementationObject(true);
             result = modifiedMethod.invoke( instance,