FELIX-3729 Revert to only one (removed) event for service removal

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1424306 13f79535-47bb-0310-9956-ffa450edef68
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 c9c1c26..5df26a4 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
@@ -188,6 +188,18 @@
             }
 
         }
+
+        protected void ungetService( RefPair<T> ref )
+        {
+            synchronized ( ref )
+            {
+                if ( ref.getServiceObject() != null )
+                {
+                    ref.setServiceObject( null );
+                    m_componentManager.getActivator().getBundleContext().ungetService( ref.getRef() );
+                }
+            }
+        }
     }
 
 
@@ -211,10 +223,6 @@
         {
         }
 
-        public void removingService( ServiceReference<T> item, RefPair<T> object, int size )
-        {
-        }
-
         public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
         {
             if ( !isOptional() )
@@ -246,6 +254,8 @@
 
     private class MultipleDynamicCustomizer extends AbstractCustomizer {
 
+        private RefPair<T> lastRefPair;
+
         public RefPair<T> addingService( ServiceReference<T> serviceReference )
         {
             RefPair<T> refPair = getPreviousRefMap().get( serviceReference );
@@ -289,28 +299,23 @@
             }
         }
 
-        public void removingService( ServiceReference<T> item, RefPair<T> refPair, int size )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
         {
             if ( isActive() )
             {
-                boolean unbind = isOptional() || size > 0;
+                boolean unbind = isOptional() || !getTracker().isEmpty();
                 if ( unbind )
                 {
                     m_componentManager.invokeUnbindMethod( DependencyManager.this, refPair );
                 }
                 else
                 {
+                    lastRefPair = refPair;
                     m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
+                    lastRefPair = null;
                 }
             }
-        }
-
-        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
-        {
-            if (refPair.getServiceObject() != null)
-            {
-                m_componentManager.getActivator().getBundleContext().ungetService( serviceReference );
-            }
+            ungetService( refPair );
         }
 
         public boolean open()
@@ -338,27 +343,28 @@
         {
             for ( RefPair<T> ref : getRefs() )
             {
-                if ( ref.getServiceObject() != null )
-                {
-                    ref.setServiceObject( null );
-                    m_componentManager.getActivator().getBundleContext().ungetService( ref.getRef() );
-                }
+                ungetService( ref );
             }
             getTracker().deactivate();
         }
 
+
         public Collection<RefPair<T>> getRefs()
         {
-            return getTracker().getTracked( true ).values();
+            if ( lastRefPair == null )
+            {
+                return getTracker().getTracked( true ).values();
+            }
+            else
+            {
+                return Collections.singletonList( lastRefPair );
+            }
         }
     }
 
     private class MultipleStaticGreedyCustomizer extends AbstractCustomizer {
 
 
-        private final AtomicInteger reactivateCount = new AtomicInteger(  );
-
-
         public RefPair<T> addingService( ServiceReference<T> serviceReference )
         {
             RefPair<T> refPair = new RefPair<T>( serviceReference  );
@@ -374,8 +380,8 @@
             if (isActive())
             {
                 m_componentManager.log( LogService.LOG_DEBUG,
-                    "Dependency Manager: Static dependency on {0}/{1} is broken", new Object[]
-                        { m_dependencyMetadata.getName(), m_dependencyMetadata.getInterface() }, null );
+                        "Dependency Manager: Static dependency on {0}/{1} is broken", new Object[]
+                        {m_dependencyMetadata.getName(), m_dependencyMetadata.getInterface()}, null );
                 m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
                 m_componentManager.activateInternal();
 
@@ -394,32 +400,20 @@
             }
         }
 
-        public void removingService( ServiceReference<T> item, RefPair<T> object, int size )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
         {
             if ( isActive() )
             {
                 //deactivate while ref is still tracked
-                    m_componentManager.log( LogService.LOG_DEBUG,
-                            "Dependency Manager: Static dependency on {0}/{1} is broken", new Object[]
-                            {m_dependencyMetadata.getName(), m_dependencyMetadata.getInterface()}, null );
-                    m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
-                    reactivateCount.incrementAndGet();
-            }
-        }
-
-        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
-        {
-            if ( reactivateCount.getAndDecrement() > 0 )
-            {
+                m_componentManager.log( LogService.LOG_DEBUG,
+                        "Dependency Manager: Static dependency on {0}/{1} is broken", new Object[]
+                        {m_dependencyMetadata.getName(), m_dependencyMetadata.getInterface()}, null );
+                m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
                 //try to reactivate after ref is no longer tracked.
                 m_componentManager.activateInternal();
-
             }
             //This is unlikely
-            if (refPair.getServiceObject() != null)
-            {
-                m_componentManager.getActivator().getBundleContext().ungetService( serviceReference );
-            }
+            ungetService( refPair );
         }
 
         public boolean open()
@@ -440,11 +434,7 @@
         {
             for ( RefPair<T> ref: getRefs())
             {
-                if ( ref.getServiceObject() != null)
-                {
-                    ref.setServiceObject( null );
-                    m_componentManager.getActivator().getBundleContext().ungetService( ref.getRef() );
-                }
+                ungetService( ref );
             }
             getTracker().deactivate();
         }
@@ -481,10 +471,6 @@
             }
         }
 
-        public void removingService( ServiceReference<T> item, RefPair<T> object, int size )
-        {
-        }
-
         public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
         {
             if ( isActive() )
@@ -502,10 +488,7 @@
 
                 }
             }
-            if (refPair.getServiceObject() != null)
-            {
-                m_componentManager.getActivator().getBundleContext().ungetService( serviceReference );
-            }
+            ungetService( refPair );
         }
 
         public boolean open()
@@ -527,11 +510,7 @@
         {
             for ( RefPair<T> ref: getRefs())
             {
-                if ( ref.getServiceObject() != null)
-                {
-                    ref.setServiceObject( null );
-                    m_componentManager.getActivator().getBundleContext().ungetService( ref.getRef() );
-                }
+                ungetService( ref );
             }
             refs.clear();
             getTracker().deactivate();
@@ -593,10 +572,6 @@
             }
         }
 
-        public void removingService( ServiceReference<T> item, RefPair<T> object, int size )
-        {
-        }
-
         public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
         {
             if (refPair == this.refPair)
@@ -666,10 +641,9 @@
 
         private void closeRefPair()
         {
-            if ( refPair != null && refPair.getServiceObject() != null )
+            if ( refPair != null )
             {
-                refPair.setServiceObject( null );
-                m_componentManager.getActivator().getBundleContext().ungetService( refPair.getRef() );
+                ungetService( refPair );
             }
             refPair = null;
         }
@@ -715,10 +689,6 @@
             }
         }
 
-        public void removingService( ServiceReference<T> item, RefPair<T> object, int size )
-        {
-        }
-
         public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
         {
             if ( isActive() && refPair == this.refPair )
@@ -749,10 +719,9 @@
 
         public void close()
         {
-            if ( refPair != null && refPair.getServiceObject() != null )
+            if ( refPair != null )
             {
-                refPair.setServiceObject( null );
-                m_componentManager.getActivator().getBundleContext().ungetService( refPair.getRef() );
+                ungetService( refPair );
             }
             refPair = null;
             getTracker().deactivate();
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java
index 41ce377..2e1eeec 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java
@@ -1001,11 +1001,6 @@
         private final LinkedList<S> initial;
 
         /**
-         * counter to show size after removed during remmoving event.
-         */
-        private int pendingRemovals;
-
-        /**
          * AbstractTracked constructor.
          */
         AbstractTracked() {
@@ -1234,21 +1229,7 @@
                              * adding
                              */
                 }
-                object = tracked.get( item );
-                if (object == null) {
-                    //this can happen if a service is removed concurrently with tracker.close().
-                    return;
-                }
-                pendingRemovals++;
-                size = tracked.size() - pendingRemovals;
-            }
-            /* Call customizer outside of synchronized region */
-            customizerRemoving(item, related, object, size );
-            synchronized (this) {
-                pendingRemovals--;
-
-                tracked.remove(item); /*
-                                                 * must remove from tracker before
+                object = tracked.remove(item); /*                                                 * must remove from tracker before
                                                  * calling customizer callback
                                                  */
                 modified(); /* increment modification count */
@@ -1375,8 +1356,6 @@
          */
         abstract void customizerModified(final S item, final R related, final T object);
 
-        abstract void customizerRemoving( final S item, final R related, final T object, int size );
-
         /**
          * Call the specific customizer removed method. This method must not be
          * called while synchronized on this object.
@@ -1482,12 +1461,6 @@
 			customizer.modifiedService(item, object);
 		}
 
-        @Override
-        void customizerRemoving( ServiceReference<S> item, ServiceEvent related, T object, int size )
-        {
-            customizer.removingService( item, object, size );
-        }
-
         /**
 		 * Call the specific customizer removed method. This method must not be
 		 * called while synchronized on this object.
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTrackerCustomizer.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTrackerCustomizer.java
index 8809db6..2868106 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTrackerCustomizer.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTrackerCustomizer.java
@@ -81,8 +81,6 @@
 	 */
 	public void modifiedService(ServiceReference<S> reference, T service);
 
-    void removingService( ServiceReference<S> item, T object, int size );
-
 	/**
 	 * A service tracked by the {@code ServiceTracker} has been removed.
 	 *