FELIX-4020 simplify how edgeInfo is obtained.  Change some locking. Incomplete although SingleStaticCustomizer avoids the specific problem in the issue

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1470393 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
index 84d04d2..e7bd23e 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
@@ -882,8 +882,6 @@
         m_dependenciesCollected = false;
     }
 
-    abstract EdgeInfo getEdgeInfo( S implObject, DependencyManager<S, ?> dependencyManager);
-    
     abstract <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount );
 
     abstract <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount );
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
index 8ff8956..8f20e3a 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
@@ -278,11 +278,6 @@
         return true;
     }
 
-    EdgeInfo getEdgeInfo( S implObject, DependencyManager<S, ?> dependencyManager) 
-    {
-        return null;
-    }
-
     <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<T> ref, int trackingCount )
     {
     }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
index 92398a7..dd25e40 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
@@ -661,29 +661,34 @@
         public void addedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
-        	boolean tracked = false;
+            boolean tracked = false;
             if ( getPreviousRefMap().remove( serviceReference ) == null )
             {
                 if (isActive() )
                 {
-                    if ( this.refPair == null || ( !isReluctant() && refPair.getRef().compareTo( this.refPair.getRef() ) > 0 ) )
+                    boolean invokeBind;
+                    synchronized ( getTracker().tracked() )
                     {
-                        synchronized ( refPair )
-                        {
-                            getServiceObject( m_bindMethods.getBind(), refPair );
-                        }
+                        invokeBind = this.refPair == null
+                                || ( !isReluctant() && refPair.getRef().compareTo( this.refPair.getRef() ) > 0 );
+                    }
+                    if ( invokeBind )
+                    {
+                        getServiceObject( m_bindMethods.getBind(), refPair );
                         if ( !refPair.isFailed() )
                         {
                             m_componentManager.invokeBindMethod( DependencyManager.this, refPair, trackingCount );
                             if ( this.refPair != null )
                             {
-                                m_componentManager.invokeUnbindMethod( DependencyManager.this, this.refPair, trackingCount );
+                                m_componentManager.invokeUnbindMethod( DependencyManager.this, this.refPair,
+                                        trackingCount );
                                 closeRefPair();
                             }
                         }
                         else
                         {
-                            m_componentManager.registerMissingDependency( DependencyManager.this, serviceReference, trackingCount );
+                            m_componentManager.registerMissingDependency( DependencyManager.this, serviceReference,
+                                    trackingCount );
                         }
                         this.refPair = refPair;
                     }
@@ -699,14 +704,19 @@
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic added {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
             if ( !tracked )
             {
-				tracked(trackingCount);
-			}
+                tracked(trackingCount);
+            }
         }
 
         public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
-            if (isActive())
+            boolean invokeUpdated;
+            synchronized (getTracker().tracked())
+            {
+                invokeUpdated = isActive() && refPair == this.refPair;
+            }
+            if ( invokeUpdated )
             {
                 m_componentManager.invokeUpdatedMethod( DependencyManager.this, refPair, trackingCount );
             }
@@ -718,80 +728,97 @@
         public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
-            if (refPair == this.refPair)
+            boolean deactivate = false;
+            boolean untracked = true;
+            synchronized ( getTracker().tracked() )
             {
-                if ( isActive() )
+                if ( refPair == this.refPair )
                 {
-                    RefPair<T> nextRefPair = null;
-                    if ( !getTracker().isEmpty() )
+                    if ( isActive() )
                     {
-                        AtomicInteger trackingCount2 = new AtomicInteger( );
-                        SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true, trackingCount2 );
-                        nextRefPair = tracked.values().iterator().next();
-                        synchronized ( nextRefPair )
+                        RefPair<T> nextRefPair = null;
+                        if ( !getTracker().isEmpty() )
                         {
-                            if (!getServiceObject( m_bindMethods.getBind(), nextRefPair ))
+                            AtomicInteger trackingCount2 = new AtomicInteger();
+                            SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true,
+                                    trackingCount2 );
+                            nextRefPair = tracked.values().iterator().next();
+                            synchronized ( nextRefPair )
                             {
-                                //TODO error???
+                                if ( !getServiceObject( m_bindMethods.getBind(), nextRefPair ) )
+                                {
+                                    //TODO error???
+                                }
+                            }
+                            if ( !nextRefPair.isFailed() )
+                            {
+                                m_componentManager
+                                        .invokeBindMethod( DependencyManager.this, nextRefPair, trackingCount );
                             }
                         }
-                        if ( !nextRefPair.isFailed() )
+
+                        if ( isOptional() || nextRefPair != null )
                         {
-                            m_componentManager.invokeBindMethod( DependencyManager.this, nextRefPair, trackingCount );
+                            RefPair<T> oldRefPair = this.refPair;
+                            this.refPair = null;
+                            this.trackingCount = trackingCount;
+                            m_componentManager.invokeUnbindMethod( DependencyManager.this, oldRefPair, trackingCount );
+                            this.refPair = nextRefPair;
+                            tracked( trackingCount );
+                            untracked = false;
+                            ungetService( oldRefPair );
+                        }
+                        else
+                        //required and no replacement service, deactivate
+                        {
+                            deactivate = true;
                         }
                     }
-
-                    if ( isOptional() || nextRefPair != null)
+                    else
+                    //not active  This should not happen, close should have nulled this.refPair.
                     {
-                        RefPair<T> oldRefPair = this.refPair;
                         this.refPair = null;
                         this.trackingCount = trackingCount;
-                        m_componentManager.invokeUnbindMethod( DependencyManager.this, oldRefPair, trackingCount );
-                        this.refPair = nextRefPair;
                         tracked( trackingCount );
-                        ungetService( oldRefPair );
+                        untracked = false;
                     }
-                    else //required and no replacement service, deactivate
-                    {
-                        this.trackingCount = trackingCount;
-                        tracked( trackingCount );
-                        m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, trackingCount );
-                    }
-                }
-                else
-                {
-                    this.refPair = null;
-                    this.trackingCount = trackingCount;
-                    tracked( trackingCount );
                 }
             }
-            else
+            if (untracked) // not ours
             {
                 this.trackingCount = trackingCount;
                 tracked( trackingCount );
             }
+            if (deactivate)
+            {
+                this.trackingCount = trackingCount;
+                tracked( trackingCount );
+                m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, trackingCount );
+
+            }
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic removed {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
         public boolean open()
         {
             boolean success = m_dependencyMetadata.isOptional();
-            if ( success || !getTracker().isEmpty() )
+            synchronized ( getTracker().tracked() )
             {
-                AtomicInteger trackingCount = new AtomicInteger( );
-                SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true, trackingCount );
-                if ( !tracked.isEmpty() )
+                if ( success || !getTracker().isEmpty() )
                 {
-                    RefPair<T> refPair = tracked.values().iterator().next();
-                    synchronized ( refPair )
+                    AtomicInteger trackingCount = new AtomicInteger();
+                    SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true, trackingCount );
+                    if ( !tracked.isEmpty() )
                     {
+                        RefPair<T> refPair = tracked.values().iterator().next();
                         success |= getServiceObject( m_bindMethods.getBind(), refPair );
+                        if ( refPair.isFailed() )
+                        {
+                            m_componentManager.registerMissingDependency( DependencyManager.this, refPair.getRef(),
+                                    trackingCount.get() );
+                        }
+                        this.refPair = refPair;
                     }
-                    if (refPair.isFailed())
-                    {
-                        m_componentManager.registerMissingDependency( DependencyManager.this, refPair.getRef(), trackingCount.get() );
-                    }
-                    this.refPair = refPair;
                 }
             }
             return success;
@@ -799,8 +826,11 @@
 
         public void close()
         {
-            closeRefPair();
-            getTracker().deactivate();
+            synchronized ( getTracker().tracked() )
+            {
+                closeRefPair();
+                getTracker().deactivate();
+            }
         }
 
         private void closeRefPair()
@@ -814,8 +844,19 @@
 
         public Collection<RefPair<T>> getRefs( AtomicInteger trackingCount )
         {
-            trackingCount.set( this.trackingCount );
-            return refPair == null? Collections.<RefPair<T>>emptyList(): Collections.singleton( refPair );
+            Object monitor = getTracker().tracked();
+            if ( monitor != null )
+            {
+                synchronized ( monitor )
+                {
+                    trackingCount.set( this.trackingCount );
+                    return refPair == null? Collections.<RefPair<T>> emptyList(): Collections.singleton( refPair );
+                }
+            }
+            else
+            {
+                return Collections.<RefPair<T>> emptyList();
+            }
         }
     }
 
@@ -838,7 +879,12 @@
             tracked( trackingCount );
             if ( isActive() )
             {
-                if ( !isReluctant() && ( this.refPair == null || refPair.getRef().compareTo( this.refPair.getRef() ) > 0 ) )
+                boolean reactivate;
+                synchronized (getTracker().tracked())
+                {
+                    reactivate = !isReluctant() && ( this.refPair == null || refPair.getRef().compareTo( this.refPair.getRef() ) > 0 );
+                }
+                if ( reactivate )
                 {
                     m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, trackingCount );
                     m_componentManager.activateInternal( trackingCount );
@@ -862,7 +908,12 @@
         public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
-            if ( isActive() )
+            boolean invokeUpdated;
+            synchronized (getTracker().tracked())
+            {
+                invokeUpdated = isActive() && refPair == this.refPair;
+            }
+            if ( invokeUpdated )
             {
                 m_componentManager.invokeUpdatedMethod( DependencyManager.this, refPair, trackingCount );
             }
@@ -876,7 +927,12 @@
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             this.trackingCount = trackingCount;
             tracked( trackingCount );
-            if ( isActive() && refPair == this.refPair )
+            boolean reactivate;
+            synchronized (getTracker().tracked())
+            {
+                reactivate = isActive() && refPair == this.refPair;
+            }
+            if ( reactivate )
             {
                 m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, trackingCount );
                 m_componentManager.activateInternal( trackingCount );
@@ -889,16 +945,28 @@
             boolean success = m_dependencyMetadata.isOptional();
             if ( success || !getTracker().isEmpty() )
             {
-                AtomicInteger trackingCount = new AtomicInteger( );
-                SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true, trackingCount );
-                if ( !tracked.isEmpty() )
+                RefPair<T> refPair = null;
+                AtomicInteger trackingCount = new AtomicInteger();
+                synchronized ( getTracker().tracked() )
                 {
-                    RefPair<T> refPair = tracked.values().iterator().next();
+                    SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true, trackingCount );
+                    if ( !tracked.isEmpty() )
+                    {
+                        refPair = tracked.values().iterator().next();
+                        this.refPair = refPair;
+                    }
+                }
+                if ( refPair != null )
+                {
                     synchronized ( refPair )
                     {
                         success |= getServiceObject( m_bindMethods.getBind(), refPair );
+                        if ( refPair.isFailed() )
+                        {
+                            m_componentManager.registerMissingDependency( DependencyManager.this, refPair.getRef(),
+                                    trackingCount.get() );
+                        }
                     }
-                    this.refPair = refPair;
                 }
             }
             return success;
@@ -906,18 +974,32 @@
 
         public void close()
         {
-            if ( refPair != null )
+            synchronized ( getTracker().tracked() )
             {
-                ungetService( refPair );
+                if ( refPair != null )
+                {
+                    ungetService( refPair );
+                }
+                refPair = null;
+                getTracker().deactivate();
             }
-            refPair = null;
-            getTracker().deactivate();
         }
 
         public Collection<RefPair<T>> getRefs( AtomicInteger trackingCount )
         {
-            trackingCount.set( this.trackingCount );
-            return refPair == null ? Collections.<RefPair<T>>emptyList() : Collections.singleton( refPair );
+            Object monitor = getTracker().tracked();
+            if ( monitor != null )
+            {
+                synchronized ( monitor )
+                {
+                    trackingCount.set( this.trackingCount );
+                    return refPair == null? Collections.<RefPair<T>> emptyList(): Collections.singleton( refPair );
+                }
+            }
+            else
+            {
+                return Collections.<RefPair<T>> emptyList();
+            }
         }
     }
 
@@ -1310,11 +1392,12 @@
     /**
      * initializes a dependency. This method binds all of the service
      * occurrences to the instance object
+     * @param edgeInfo TODO
      *
      * @return true if the dependency is satisfied and at least the minimum
      *      number of services could be bound. Otherwise false is returned.
      */
-    boolean open( S componentInstance )
+    boolean open( S componentInstance, EdgeInfo edgeInfo )
     {
         // If no references were received, we have to check if the dependency
         // is optional, if it is not then the dependency is invalid
@@ -1343,8 +1426,7 @@
         synchronized ( trackerRef.get().tracked() )
         {
             refs = customizer.getRefs( trackingCount );
-            EdgeInfo info = getEdgeInfo( componentInstance );
-            info.setOpen( trackingCount.get() );
+            edgeInfo.setOpen( trackingCount.get() );
         }
         m_componentManager.log( LogService.LOG_DEBUG,
             "For dependency {0}, optional: {1}; to bind: {2}",
@@ -1353,7 +1435,7 @@
         {
             if ( !refPair.isFailed() )
             {
-                if ( !invokeBindMethod( componentInstance, refPair, trackingCount.get() ) )
+                if ( !invokeBindMethod( componentInstance, refPair, trackingCount.get(), edgeInfo ) )
                 {
                     m_componentManager.log( LogService.LOG_DEBUG,
                             "For dependency {0}, failed to invoke bind method on object {1}",
@@ -1366,17 +1448,12 @@
         return success;
     }
 
-
-    private EdgeInfo getEdgeInfo( S componentInstance )
-    {
-        return m_componentManager.getEdgeInfo( componentInstance, this );
-    }
-    
     /**
      * Revoke the given bindings. This method cannot throw an exception since
      * it must try to complete all that it can
+     * @param edgeInfo TODO
      */
-    void close( S componentInstance )
+    void close( S componentInstance, EdgeInfo edgeInfo )
     {
         // only invoke the unbind method if there is an instance (might be null
         // in the delayed component situation) and the unbind method is declared.
@@ -1388,10 +1465,8 @@
         synchronized ( trackerRef.get().tracked() )
         {
             refPairs = customizer.getRefs( trackingCount );
-            EdgeInfo info = getEdgeInfo( componentInstance );
-            info.setClose( trackingCount.get() );
-            info.setLatch( latch );
-        }
+            edgeInfo.setClose( trackingCount.get() );
+            edgeInfo.setLatch( latch );
 
         m_componentManager.log( LogService.LOG_DEBUG,
                 "DependencyManager: {0} close component unbinding from {1} at tracking count {2} refpairs: {3}",
@@ -1401,10 +1476,11 @@
         {
             if ( doUnbind && !boundRef.isFailed() )
             {
-                invokeUnbindMethod( componentInstance, boundRef, trackingCount.get() );
+                invokeUnbindMethod( componentInstance, boundRef, trackingCount.get(), edgeInfo );
             }
 
         }
+        }
         latch.countDown();
     }
 
@@ -1457,15 +1533,15 @@
      *
      * @param componentInstance
      * @param refPair the service reference, service object tuple.
-     *
      * @param trackingCount
+     * @param edgeInfo TODO
      * @return true if the service should be considered bound. If no bind
      *      method is found or the method call fails, <code>true</code> is
      *      returned. <code>false</code> is only returned if the service must
      *      be handed over to the bind method but the service cannot be
      *      retrieved using the service reference.
      */
-    boolean invokeBindMethod( S componentInstance, RefPair refPair, int trackingCount )
+    boolean invokeBindMethod( S componentInstance, RefPair refPair, int trackingCount, EdgeInfo info )
     {
         // The bind method is only invoked if the implementation object is not
         // null. This is valid for both immediate and delayed components
@@ -1473,7 +1549,6 @@
         {
             synchronized ( trackerRef.get().tracked() )
             {
-                EdgeInfo info = getEdgeInfo( componentInstance );
                 if (info.outOfRange( trackingCount ) )
                 {
                     //ignore events before open started or we will have duplicate binds.
@@ -1511,8 +1586,9 @@
      *
      * @param componentInstance
      * @param refPair A service reference corresponding to the service whose service
+     * @param edgeInfo TODO
      */
-    void invokeUpdatedMethod( S componentInstance, final RefPair<T> refPair, int trackingCount )
+    void invokeUpdatedMethod( S componentInstance, final RefPair<T> refPair, int trackingCount, EdgeInfo info )
     {
         if ( m_dependencyMetadata.getUpdated() == null )
         {
@@ -1532,7 +1608,6 @@
             }
             synchronized ( trackerRef.get().tracked() )
             {
-                EdgeInfo info = getEdgeInfo( componentInstance );
                 if (info.outOfRange( trackingCount ) )
                 {
                     //ignore events after close started or we will have duplicate unbinds.
@@ -1574,18 +1649,14 @@
      * @param componentInstance
      * @param refPair A service reference corresponding to the service that will be
      * @param trackingCount
+     * @param info TODO
      */
-    void invokeUnbindMethod( S componentInstance, final RefPair<T> refPair, int trackingCount )
+    void invokeUnbindMethod( S componentInstance, final RefPair<T> refPair, int trackingCount, EdgeInfo info )
     {
         // The unbind method is only invoked if the implementation object is not
         // null. This is valid for both immediate and delayed components
         if ( componentInstance != null )
         {
-            EdgeInfo info;
-            synchronized ( trackerRef.get().tracked() )
-            {
-                info = getEdgeInfo( componentInstance );
-            }
             if (info.outOfRange( trackingCount ) )
             {
                 //wait for unbinds to complete
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
index 711632a..5136883 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
@@ -255,7 +255,7 @@
             // if a dependency turned unresolved since the validation check,
             // creating the instance fails here, so we deactivate and return
             // null.
-            boolean open = dm.open( implementationObject );
+            boolean open = dm.open( implementationObject, componentContext.getEdgeInfo( dm ) );
             if ( !open )
             {
                 log( LogService.LOG_ERROR, "Cannot create component instance due to failure to bind reference {0}",
@@ -265,7 +265,7 @@
                 // make sure, we keep no bindings
                 for ( DependencyManager md: getReversedDependencyManagers() )
                 {
-                    md.close( implementationObject );
+                    md.close( implementationObject, componentContext.getEdgeInfo( md ) );
                 }
 
                 setter.resetImplementationObject( implementationObject );
@@ -282,7 +282,7 @@
             // containing the exception with the Log Service and activation fails
             for ( DependencyManager md: getReversedDependencyManagers() )
             {
-                md.close( implementationObject );
+                md.close( implementationObject, null );
             }
 
             // make sure the implementation object is not available
@@ -319,7 +319,7 @@
         // 2. Unbind any bound services
         for ( DependencyManager md: getReversedDependencyManagers() )
         {
-            md.close( implementationObject );
+            md.close( implementationObject, componentContext.getEdgeInfo( md ) );
         }
 
     }
@@ -334,18 +334,14 @@
         return Active.getInstance();
     }
     
-    EdgeInfo getEdgeInfo( S implObject, DependencyManager<S, ?> dependencyManager) 
-    {
-        return m_componentContext.getEdgeInfo( dependencyManager );
-    }
-
     <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount )
     {
         ComponentContextImpl<S> componentContext = m_componentContext;
         if ( componentContext != null )
         {
             final S impl = componentContext.getImplementationObject( false );
-            dependencyManager.invokeBindMethod( impl, refPair, trackingCount );
+            EdgeInfo info = componentContext.getEdgeInfo( dependencyManager );
+            dependencyManager.invokeBindMethod( impl, refPair, trackingCount, info );
         }
     }
 
@@ -355,7 +351,8 @@
         if ( componentContext != null )
         {
             final S impl = componentContext.getImplementationObject( false );
-            dependencyManager.invokeUpdatedMethod( impl, refPair, trackingCount );
+            EdgeInfo info = componentContext.getEdgeInfo( dependencyManager );
+            dependencyManager.invokeUpdatedMethod( impl, refPair, trackingCount, info );
         }
     }
 
@@ -365,7 +362,8 @@
         if ( componentContext != null )
         {
             final S impl = componentContext.getImplementationObject( false );
-            dependencyManager.invokeUnbindMethod( impl, oldRefPair, trackingCount );
+            EdgeInfo info = componentContext.getEdgeInfo( dependencyManager );
+            dependencyManager.invokeUnbindMethod( impl, oldRefPair, trackingCount, info );
         }
     }
 
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 1d8c65e..2c4e84a 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
@@ -192,32 +192,27 @@
         }
     }
 
-    EdgeInfo getEdgeInfo( S implObject, DependencyManager<S, ?> dependencyManager) 
-    {
-        return serviceContexts.get( implObject ).getEdgeInfo( dependencyManager );
-    }
-
     <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount )
     {
-        for ( S implementationObject : serviceContexts.keySet() )
+        for ( ComponentContextImpl<S> cc : serviceContexts.values() )
         {
-            dependencyManager.invokeBindMethod( implementationObject, refPair, trackingCount );
+            dependencyManager.invokeBindMethod( cc.getImplementationObject( false ), refPair, trackingCount, cc.getEdgeInfo( dependencyManager ) );
         }
     }
 
     <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount )
     {
-        for ( S implementationObject : serviceContexts.keySet() )
+        for ( ComponentContextImpl<S> cc : serviceContexts.values() )
         {
-            dependencyManager.invokeUpdatedMethod( implementationObject, refPair, trackingCount );
+            dependencyManager.invokeUpdatedMethod( cc.getImplementationObject( false ), refPair, trackingCount, cc.getEdgeInfo( dependencyManager ) );
         }
     }
 
     <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> oldRefPair, int trackingCount )
     {
-        for ( S implementationObject : serviceContexts.keySet() )
+        for ( ComponentContextImpl<S> cc : serviceContexts.values() )
         {
-            dependencyManager.invokeUnbindMethod( implementationObject, oldRefPair, trackingCount );
+            dependencyManager.invokeUnbindMethod( cc.getImplementationObject( false ), oldRefPair, trackingCount, cc.getEdgeInfo( dependencyManager ) );
         }
     }