Bugfixes for several issues with required service dependencies with callbacks in scenarios where multiple dependencies are available.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1039035 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java
index c9ee905..618a211 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java
@@ -25,10 +25,10 @@
 import java.util.List;
 import java.util.Map;
 
-import org.apache.felix.dm.Dependency;
-import org.apache.felix.dm.DependencyManager;
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.ComponentStateListener;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
@@ -184,8 +184,7 @@
     public void removed(URL resource) {
         Component newService = (Component) m_services.remove(resource);
         if (newService == null) {
-            System.out.println("Service should not be null here, dumping stack.");
-            Thread.dumpStack();
+            throw new IllegalStateException("Service should not be null here.");
         }
         else {
             m_manager.remove(newService);
@@ -202,8 +201,7 @@
     public void removed(ServiceReference ref, Object service) {
         Component newService = (Component) m_services.remove(ref);
         if (newService == null) {
-            System.out.println("Service should not be null here, dumping stack.");
-            Thread.dumpStack();
+            throw new IllegalStateException("Service should not be null here.");
         }
         else {
             m_manager.remove(newService);
@@ -220,8 +218,7 @@
     public void removed(Bundle bundle) {
         Component newService = (Component) m_services.remove(bundle);
         if (newService == null) {
-            System.out.println("Service should not be null here, dumping stack.");
-            Thread.dumpStack();
+            throw new IllegalStateException("Service should not be null here.");
         }
         else {
             m_manager.remove(newService);
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ComponentImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ComponentImpl.java
index b1bb057..fc9c0d8 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ComponentImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ComponentImpl.java
@@ -1008,21 +1008,12 @@
     }
 
     private void unconfigureServices(State state) {
-        System.err.println("unconfigureServices " + state);
         Iterator i = state.getDependencies().iterator();
         while (i.hasNext()) {
             Dependency dependency = (Dependency) i.next();
             if (dependency.isRequired()) {
-                System.err.println("unconfigureServices invokeremoved " + dependency);
                 dependency.invokeRemoved(this);
             }
-//            if (dependency instanceof ServiceDependencyImpl) {
-//                ServiceDependencyImpl sd = (ServiceDependencyImpl) dependency;
-//                // for required dependencies, we invoke any callbacks here
-//                if (sd.isRequired()) {
-//                    sd.invokeRemoved(this, sd.lookupServiceReference(), sd.lookupService());
-//                }
-//            }
         }
     }
 
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
index e1e471b..7d37db5 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
@@ -25,6 +25,7 @@
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Dictionary;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -37,7 +38,6 @@
 import org.apache.felix.dm.DependencyService;
 import org.apache.felix.dm.InvocationUtil;
 import org.apache.felix.dm.ServiceDependency;
-import org.apache.felix.dm.ServiceUtil;
 import org.apache.felix.dm.impl.DefaultNullObject;
 import org.apache.felix.dm.impl.Logger;
 import org.apache.felix.dm.tracker.ServiceTracker;
@@ -75,10 +75,10 @@
     private Object m_defaultImplementation;
     private Object m_defaultImplementationInstance;
     private boolean m_isAvailable;
-    private ServiceReference[] m_references;
     private boolean m_propagate;
     private Object m_propagateCallbackInstance;
     private String m_propagateCallbackMethod;
+    private Map m_sr = new HashMap(); /* <DependencyService, Set<ServiceReference>> */
     
     private static final Comparator COMPARATOR = new Comparator() {
         public int getRank(ServiceReference ref) {
@@ -443,7 +443,11 @@
                 // because if not, then our dependency would not be active); or the dependency is required,
                 // meaning that either the service is not yet started, or already started.
                 // In all cases, we have to inject the required dependency.
-                invokeAdded(ds, ref, service);
+                
+                // we only try to invoke the method here if we are really already instantiated
+                if (ds.isInstantiated() && ds.getCompositionInstances().length > 0) {
+                    invokeAdded(ds, ref, service);
+                }
             }
         }
     }
@@ -465,8 +469,6 @@
     public void removedService(ServiceReference ref, Object service) {
         boolean makeUnavailable = makeUnavailable();
         
-        System.out.println("removedService: " + makeUnavailable + " for " + ServiceUtil.toString(ref));
-        
         Object[] services;
         synchronized (this) {
             services = m_services.toArray();
@@ -490,10 +492,16 @@
 
     }
 
+    
     public void invokeAdded(DependencyService dependencyService, ServiceReference reference, Object service) {
-        invoke(dependencyService, reference, service, m_callbackAdded);
-        //marrs
-        m_refs.add(reference);
+        Set set = (Set) m_sr.get(dependencyService);
+        if (set == null) {
+            set = new HashSet();
+            m_sr.put(dependencyService, set);
+        }
+        if (set.add(reference)) {
+            invoke(dependencyService, reference, service, m_callbackAdded);
+        }
     }
     
     public void invokeChanged(DependencyService dependencyService, ServiceReference reference, Object service) {
@@ -501,9 +509,10 @@
     }
 
     public void invokeRemoved(DependencyService dependencyService, ServiceReference reference, Object service) {
-        invoke(dependencyService, reference, service, m_callbackRemoved);
-        //marrs
-        m_refs.remove(reference);
+        Set set = (Set) m_sr.get(dependencyService);
+        if (set != null && set.remove(reference)) {
+            invoke(dependencyService, reference, service, m_callbackRemoved);
+        }
     }
 
     public void invoke(DependencyService dependencyService, ServiceReference reference, Object service, String name) {
@@ -809,48 +818,29 @@
         return "service";
     }
 
-    private List m_refs = new ArrayList();
-    
     public void invokeAdded(DependencyService service) {
         ServiceReference[] refs = m_tracker.getServiceReferences();
         if (refs != null) {
             for (int i = 0; i < refs.length; i++) {
                 ServiceReference sr = refs[i];
                 Object svc = m_context.getService(sr);
-                System.out.println("invokeAdded " + i + " " + ServiceUtil.toString(sr));
                 invokeAdded(service, sr, svc);
-                
-                //marrs
-                m_refs.add(sr);
             }
         }
-        m_references = refs;
-        
     }
     
     public void invokeRemoved(DependencyService service) {
-        ServiceReference[] refs = m_references;
-        
-        
-        if (refs != null) {
-            //marrs
-            refs = (ServiceReference[]) m_refs.toArray(refs);
-            
-            for (int i = 0; i < refs.length; i++) {
-                ServiceReference sr = refs[i];
-                Object svc = m_context.getService(sr);
-                System.out.println("invokeRemoved " + i + " " + ServiceUtil.toString(sr));
-                if (sr.getBundle() == null) {
-                    System.out.println("invokeRemoved OLD SHIT .. SKIPPING .. not");
-//                    break;
-                }
-                invokeRemoved(service, sr, svc);
-            }
+        Set references = (Set) m_sr.get(service);
+        ServiceReference[] refs = (ServiceReference[]) (references != null ? references.toArray(new ServiceReference[references.size()]) : new ServiceReference[0]);
+    
+        for (int i = 0; i < refs.length; i++) {
+            ServiceReference sr = refs[i];
+            Object svc = m_context.getService(sr);
+            invokeRemoved(service, sr, svc);
         }
-        m_references = null;
-        
-        //marrs
-        m_refs.clear();
+        if (references != null) {
+            references.clear();
+        }
     }
 
     public Dictionary getProperties() {