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 084fe58..5c72943 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
@@ -28,7 +28,6 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -42,6 +41,7 @@
 import org.apache.felix.dm.InvocationUtil;
 import org.apache.felix.dm.ServiceDependency;
 import org.apache.felix.dm.ServiceUtil;
+import org.apache.felix.dm.impl.BlockingSerialExecutor;
 import org.apache.felix.dm.impl.DefaultNullObject;
 import org.apache.felix.dm.impl.Logger;
 import org.apache.felix.dm.tracker.ServiceTracker;
@@ -57,44 +57,42 @@
  * 
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class ServiceDependencyImpl extends DependencyBase implements ServiceDependency, ServiceTrackerCustomizer, ComponentDependencyDeclaration {
-    protected List m_services = new ArrayList();
+public class ServiceDependencyImpl extends DependencyBase implements ServiceDependency, ServiceTrackerCustomizer,
+        ComponentDependencyDeclaration {
+    protected final List m_services = new ArrayList();
     protected volatile ServiceTracker m_tracker;
-    protected BundleContext m_context;
+    protected final BundleContext m_context;
     protected volatile Class m_trackedServiceName;
-    private Object m_nullObject;
+    private volatile Object m_nullObject;
     private volatile String m_trackedServiceFilter;
     private volatile String m_trackedServiceFilterUnmodified;
     private volatile ServiceReference m_trackedServiceReference;
-    private Object m_callbackInstance;
-    private String m_callbackAdded;
-    private String m_callbackChanged;
-    private String m_callbackRemoved;
-    private String m_callbackSwapped;
+    private volatile Object m_callbackInstance;
+    private volatile String m_callbackAdded;
+    private volatile String m_callbackChanged;
+    private volatile String m_callbackRemoved;
+    private volatile String m_callbackSwapped;
     private boolean m_autoConfig;
-    protected ServiceReference m_reference;
-    protected Object m_serviceInstance;
-    private String m_autoConfigInstance;
+    private volatile String m_autoConfigInstance;
     private boolean m_autoConfigInvoked;
-    private Object m_defaultImplementation;
-    private Object m_defaultImplementationInstance;
+    private volatile Object m_defaultImplementation;
+    private volatile Object m_defaultImplementationInstance;
     private boolean m_isAvailable;
-    private boolean m_propagate;
-    private Object m_propagateCallbackInstance;
-    private String m_propagateCallbackMethod;
+    private volatile boolean m_propagate;
+    private volatile Object m_propagateCallbackInstance;
+    private volatile String m_propagateCallbackMethod;
     private final Map m_sr = new HashMap(); /* <DependencyService, Set<Tuple<ServiceReference, Object>> */
-	private Map m_componentByRank = new HashMap(); /* <Component, Map<Long, Map<Integer, Tuple>>> */
-	private boolean m_debug = false;
-	private String m_debugKey = null;
-	
-	private final LinkedList m_injectionQueue = new LinkedList();
-	
-	public ServiceDependency setDebug(String identifier) {
-		this.m_debug = true;
-		this.m_debugKey = identifier;
-		return this;
-	}
-    
+    private final Map m_componentByRank = new HashMap(); /* <Component, Map<Long, Map<Integer, Tuple>>> */
+    private volatile boolean m_debug = false;
+    private volatile String m_debugKey = null;
+
+    /**
+     * Executor used to ensure proper synchronization without holding locks. 
+     */
+    private final BlockingSerialExecutor _serial = new BlockingSerialExecutor();
+
+    // ----------------------- Inner classes --------------------------------------------------------------
+
     private static final Comparator COMPARATOR = new Comparator() {
         public int getRank(ServiceReference ref) {
             Object ranking = ref.getProperty(Constants.SERVICE_RANKING);
@@ -110,40 +108,39 @@
             int rankb = getRank(rb);
             if (ranka < rankb) {
                 return -1;
-            }
-            else if (ranka > rankb) {
+            } else if (ranka > rankb) {
                 return 1;
             }
             return 0;
         }
     };
-    
-    private static final class Tuple /* <ServiceReference, Object> */ {
+
+    private static final class Tuple /* <ServiceReference, Object> */{
         private final ServiceReference m_serviceReference;
         private final Object m_service;
-        
+
         public Tuple(ServiceReference first, Object last) {
             m_serviceReference = first;
             m_service = last;
         }
-        
+
         public ServiceReference getServiceReference() {
             return m_serviceReference;
         }
-        
+
         public Object getService() {
             return m_service;
         }
-        
+
         public boolean equals(Object obj) {
             return ((Tuple) obj).getServiceReference().equals(getServiceReference());
         }
-        
+
         public int hashCode() {
             return m_serviceReference.hashCode();
         }
     }
-    
+
     /**
      * Entry to wrap service properties behind a Map.
      */
@@ -218,7 +215,9 @@
             return set;
         }
     }
-        
+
+    // ----------------------- Public methods -----------------------------------------------------------
+
     /**
      * Creates a new service dependency.
      * 
@@ -230,7 +229,7 @@
         m_context = context;
         m_autoConfig = true;
     }
-    
+
     /** Copying constructor that clones an existing instance. */
     public ServiceDependencyImpl(ServiceDependencyImpl prototype) {
         super(prototype);
@@ -251,210 +250,50 @@
             m_defaultImplementation = prototype.m_defaultImplementation;
         }
     }
-    
+
+    //@Override
+    public ServiceDependency setDebug(String identifier) {
+        this.m_debug = true;
+        this.m_debugKey = identifier;
+        return this;
+    }
+
+    //@Override
     public Dependency createCopy() {
         return new ServiceDependencyImpl(this);
     }
-    
+
+    //@Override
     public synchronized boolean isAutoConfig() {
         return m_autoConfig;
     }
-    
+
+    //@Override
     public synchronized boolean isAvailable() {
         return m_isAvailable;
     }
 
-    public synchronized Object getService() {
-        Object service = null;
-        if (m_isStarted) {
-            service = m_tracker.getService();
-        }
-        if (service == null && isAutoConfig()) {
-            service = getDefaultImplementation();
-            if (service == null) {
-                service = getNullObject();
+    //@Override
+    public void start(final DependencyService service) {
+        _serial.execute(new Runnable() {
+            public void run() {
+                // this code is executed exclusively and without holding any locks
+                _start(service);
             }
-        }
-        return service;
+        });
     }
 
-    public Object lookupService() {
-        Object service = null;
-        if (m_isStarted) {
-            service = getService();
-        }
-        else {
-            ServiceReference[] refs = null;
-            ServiceReference ref = null;
-            if (m_trackedServiceName != null) {
-                if (m_trackedServiceFilter != null) {
-                    try {
-                        refs = m_context.getServiceReferences(m_trackedServiceName.getName(), m_trackedServiceFilter);
-                        if (refs != null) {
-                            Arrays.sort(refs, COMPARATOR);
-                            ref = refs[0];
-                        }
-                    }
-                    catch (InvalidSyntaxException e) {
-                        throw new IllegalStateException("Invalid filter definition for dependency.");
-                    }
-                }
-                else if (m_trackedServiceReference != null) {
-                    ref = m_trackedServiceReference;
-                }
-                else {
-                    ref = m_context.getServiceReference(m_trackedServiceName.getName());
-                }
-                if (ref != null) {
-                    service = m_context.getService(ref);
-                }
+    //@Override
+    public void stop(final DependencyService service) {
+        _serial.execute(new Runnable() {
+            public void run() {
+                // this code is executed exclusively and without holding any locks
+                _stop(service);
             }
-            else {
-                throw new IllegalStateException("Could not lookup dependency, no service name specified.");
-            }
-        }
-        if (service == null && isAutoConfig()) {
-            service = getDefaultImplementation();
-            if (service == null) {
-                service = getNullObject();
-            }
-        }
-        return service;
+        });
     }
 
-    // TODO lots of duplication in lookupService()
-    public ServiceReference lookupServiceReference() {
-        ServiceReference service = null;
-        if (m_isStarted) {
-            service = m_tracker.getServiceReference();
-        }
-        else {
-            ServiceReference[] refs = null;
-            ServiceReference ref = null;
-            if (m_trackedServiceName != null) {
-                if (m_trackedServiceFilter != null) {
-                    try {
-                        refs = m_context.getServiceReferences(m_trackedServiceName.getName(), m_trackedServiceFilter);
-                        if (refs != null) {
-                            Arrays.sort(refs, COMPARATOR);
-                            ref = refs[0];
-                        }
-                    }
-                    catch (InvalidSyntaxException e) {
-                        throw new IllegalStateException("Invalid filter definition for dependency.");
-                    }
-                }
-                else if (m_trackedServiceReference != null) {
-                    ref = m_trackedServiceReference;
-                }
-                else {
-                    ref = m_context.getServiceReference(m_trackedServiceName.getName());
-                }
-                if (ref != null) {
-                    service = ref;
-                }
-            }
-            else {
-                throw new IllegalStateException("Could not lookup dependency, no service name specified.");
-            }
-        }
-        return service;
-    }
-
-    private Object getNullObject() {
-        if (m_nullObject == null) {
-            Class trackedServiceName;
-            synchronized (this) {
-                trackedServiceName = m_trackedServiceName;
-            }
-            try {
-                m_nullObject = Proxy.newProxyInstance(trackedServiceName.getClassLoader(), new Class[] {trackedServiceName}, new DefaultNullObject()); 
-            }
-            catch (Exception e) {
-                m_logger.log(Logger.LOG_ERROR, "Could not create null object for " + trackedServiceName + ".", e);
-            }
-        }
-        return m_nullObject;
-    }
-    
-    private Object getDefaultImplementation() {
-        if (m_defaultImplementation != null) {
-            if (m_defaultImplementation instanceof Class) {
-                try {
-                    m_defaultImplementationInstance = ((Class) m_defaultImplementation).newInstance();
-                }
-                catch (Exception e) {
-                    m_logger.log(Logger.LOG_ERROR, "Could not create default implementation instance of class " + m_defaultImplementation + ".", e);
-                }
-            }
-            else {
-                m_defaultImplementationInstance = m_defaultImplementation;
-            }
-        }
-        return m_defaultImplementationInstance;
-    }
-    
-    public synchronized Class getInterface() {
-        return m_trackedServiceName;
-    }
-
-    public void start(DependencyService service) {
-        boolean needsStarting = false;
-        synchronized (this) {
-            m_services.add(service);
-            if (!m_isStarted) {
-                if (m_trackedServiceName != null) {
-                    if (m_trackedServiceFilter != null) {
-                        try {
-                            m_tracker = new ServiceTracker(m_context, m_context.createFilter(m_trackedServiceFilter), this);
-                        }
-                        catch (InvalidSyntaxException e) {
-                            throw new IllegalStateException("Invalid filter definition for dependency: " + m_trackedServiceFilter);
-                        }
-                    }
-                    else if (m_trackedServiceReference != null) {
-                        m_tracker = new ServiceTracker(m_context, m_trackedServiceReference, this);
-                    }
-                    else {
-                        m_tracker = new ServiceTracker(m_context, m_trackedServiceName.getName(), this);
-                    }
-                }
-                else {
-                    throw new IllegalStateException("Could not create tracker for dependency, no service name specified.");
-                }
-                m_isStarted = true;
-                needsStarting = true;
-            }
-        }
-        if (needsStarting) {
-        	// when the swapped callback is set, also track the aspects
-        	boolean trackAllServices = false;
-        	boolean trackAllAspects = false;
-        	if (m_callbackSwapped != null) {
-        		trackAllAspects = true;
-        	} 
-        	m_tracker.open(trackAllServices, trackAllAspects);
-        }
-    }
-
-    public void stop(DependencyService service) {
-        boolean needsStopping = false;
-        synchronized (this) {
-            if (m_services.size() == 1 && m_services.contains(service)) {
-                m_isStarted = false;
-                needsStopping = true;
-            }
-        }
-        if (needsStopping) {
-            m_tracker.close();
-            m_tracker = null;
-        }
-        //moved this down
-        synchronized (this) {
-            m_services.remove(service);
-        }
-    }
-
+    //@Override
     public Object addingService(ServiceReference ref) {
         Object service = m_context.getService(ref);
         // first check to make sure the service is actually an instance of our service
@@ -464,470 +303,133 @@
         return service;
     }
 
-    public void addedService(ServiceReference ref, Object service) {
-		debugLog("addedservice: " + ref);
-        boolean makeAvailable = makeAvailable();
-        
-        Object[] services;
-        synchronized (this) {
-            services = m_services.toArray();
+    //@Override
+    public void addedService(final ServiceReference ref, final Object service) {
+        _serial.execute(new Runnable() {
+            public void run() {
+                // this code is executed exclusively and without holding any locks
+                _addedService(ref, service);
+            }
+        });
+    }
+
+    //@Override
+    public void modifiedService(final ServiceReference ref, final Object service) {
+        _serial.execute(new Runnable() {
+            public void run() {
+                // this code is executed exclusively and without holding any locks
+                _modifiedService(ref, service);
+            }
+        });
+    }
+
+    //@Override
+    public void removedService(final ServiceReference ref, final Object service) {
+        _serial.execute(new Runnable() {
+            public void run() {
+                // this code is executed exclusively and without holding any locks
+                _removedService(ref, service);
+            }
+        });
+    }
+
+    //@Override
+    public void invokeAdded(final DependencyService service) {
+        _serial.execute(new Runnable() {
+            public void run() {
+                // this code is executed exclusively and without holding any locks
+                _invokeAdded(service);
+            }
+        });
+    }
+
+    //@Override
+    public void invokeRemoved(final DependencyService service) {
+        _serial.execute(new Runnable() {
+            public void run() {
+                // this code is executed exclusively and without holding any locks
+                _invokeRemoved(service);
+            }
+        });
+    }
+
+    //@Override
+    public synchronized String toString() {
+        return "ServiceDependency[" + m_trackedServiceName + " " + m_trackedServiceFilterUnmodified + "]";
+    }
+
+    //@Override
+    public String getAutoConfigName() {
+        return m_autoConfigInstance;
+    }
+
+    //@Override
+    public Object getAutoConfigInstance() {
+        return lookupService();
+    }
+
+    //@Override
+    public Class getAutoConfigType() {
+        return getInterface();
+    }
+
+    //@Override
+    public String getName() {
+        StringBuilder sb = new StringBuilder();
+        if (m_trackedServiceName != null) {
+            sb.append(m_trackedServiceName.getName());
+            if (m_trackedServiceFilterUnmodified != null) {
+                sb.append(' ');
+                sb.append(m_trackedServiceFilterUnmodified);
+            }
         }
-        for (int i = 0; i < services.length; i++) {
-            DependencyService ds = (DependencyService) services[i];
-            if (makeAvailable) {
-                if (ds.isInstantiated() && isInstanceBound() && isRequired()) {
-            		debugLog("invoke added: " + ref);
-                    invokeAdded(ds, ref, service); //**
+        if (m_trackedServiceReference != null) {
+            sb.append("{service.id=" + m_trackedServiceReference.getProperty(Constants.SERVICE_ID) + "}");
+        }
+        return sb.toString();
+    }
+
+    //@Override
+    public String getType() {
+        return "service";
+    }
+
+    //@Override
+    public Dictionary getProperties() {
+        ServiceReference reference = lookupServiceReference();
+        Object service = lookupService();
+        if (reference != null) {
+            if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
+                try {
+                    return (Dictionary) InvocationUtil.invokeCallbackMethod(m_propagateCallbackInstance, m_propagateCallbackMethod,
+                            new Class[][]{{ServiceReference.class, Object.class}, {ServiceReference.class}}, new Object[][]{
+                                    {reference, service}, {reference}});
+                } catch (InvocationTargetException e) {
+                    m_logger.log(LogService.LOG_WARNING, "Exception while invoking callback method", e.getCause());
+                } catch (Exception e) {
+                    m_logger.log(LogService.LOG_WARNING, "Exception while trying to invoke callback method", e);
                 }
-                // The dependency callback will be deferred until all required dependency are available.
-            	debugLog("dependency available: " + ref);
-                ds.dependencyAvailable(this); //**
-                if (!isRequired()) {
-                    // For optional dependency, we always invoke callback, because at this point, we know
-                    // that the service has been started, and the service start method has been called.
-                    // (See the ServiceImpl.bindService method, which will activate optional dependencies using 
-                    // startTrackingOptional() method).
-            		debugLog("invoke added: " + ref);
-                    invokeAdded(ds, ref, service); //**
+                throw new IllegalStateException("Could not invoke callback");
+            } else {
+                Properties props = new Properties();
+                String[] keys = reference.getPropertyKeys();
+                for (int i = 0; i < keys.length; i++) {
+                    if (!(keys[i].equals(Constants.SERVICE_ID) || keys[i].equals(Constants.SERVICE_PID))) {
+                        props.put(keys[i], reference.getProperty(keys[i]));
+                    }
                 }
+                return props;
             }
-            else {
-        		debugLog("dependency changed: " + ref);
-                ds.dependencyChanged(this); //**
-                // At this point, either the dependency is optional (meaning that the service has been started,
-                // 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.
-                
-                // we only try to invoke the method here if we are really already instantiated
-                if (ds.isInstantiated() && ds.getCompositionInstances().length > 0) {
-            		debugLog("invoke added: " + ref);
-                    invokeAdded(ds, ref, service); //**
-                }
-            }
+        } else {
+            throw new IllegalStateException("cannot find service reference");
         }
     }
 
-    public void modifiedService(ServiceReference ref, Object service) {
-        Object[] services;
-        synchronized (this) {
-            services = m_services.toArray();
-        }
-        for (int i = 0; i < services.length; i++) {
-            DependencyService ds = (DependencyService) services[i];
-            ds.dependencyChanged(this);
-            if (ds.isRegistered()) {
-                invokeChanged(ds, ref, service);
-            }
-        }
+    //@Override
+    public boolean isPropagated() {
+        return m_propagate;
     }
 
-    public void removedService(ServiceReference ref, Object service) {
-		debugLog("removedservice: " + ref + ", rank: " + ref.getProperty("service.ranking"));
-        boolean makeUnavailable = makeUnavailable();
-    	debugLog("make unavailable: " + makeUnavailable);
-        Object[] services;
-        synchronized (this) {
-            services = m_services.toArray();
-        }
-
-        for (int i = 0; i < services.length; i++) {
-            DependencyService ds = (DependencyService) services[i];
-            if (makeUnavailable) {
-                ds.dependencyUnavailable(this);
-                // when the dependency is optional or the dependency is instance bound and the component is instantiated (and the dependency is required)
-                // then remove is invoked. In other cases the removed has been when the component was unconfigured.
-                if (!isRequired() || (ds.isInstantiated() && isInstanceBound())) {
-                    invokeRemoved(ds, ref, service);
-                }
-            }
-            else {
-                ds.dependencyChanged(this);
-                invokeRemoved(ds, ref, service);
-            }
-        }
-        // unget what we got in addingService (see ServiceTracker 701.4.1)
-       	m_context.ungetService(ref);
-
-    }
-    
-    public void invokeAdded(DependencyService dependencyService, ServiceReference reference, Object service) {
-		debugLog("invoke added");
-        boolean added = false;
-        synchronized (m_sr) {
-            Set set = (Set) m_sr.get(dependencyService);
-            if (set == null) {
-                set = new HashSet();
-                m_sr.put(dependencyService, set);
-            }
-            added = set.add(new Tuple(reference, service));
-        }
-        if (added) { 
-        	// when a changed callback is specified we might not call the added callback just yet
-        	if (m_callbackSwapped != null) {
-        		handleAspectAwareAdded(dependencyService, reference, service);
-        	}
-        	else {
-        		invoke(dependencyService, reference, service, m_callbackAdded);
-        	}
-        }
-    }
-    
-    private synchronized void waitForCallbackLock(Runnable runnable) {
-    	while (m_injectionQueue.indexOf(runnable) != 0) {
-    		try {
-				wait();
-			} catch (InterruptedException e) {
-			}
-    	}
-    }
-    
-    private synchronized void enqueueCallback(Runnable runnable) {
-    	m_injectionQueue.addLast(runnable);
-    }
-    
-    private synchronized void releaseCallback(Runnable runnable) {
-    	m_injectionQueue.remove(runnable);
-    	notifyAll();
-    }
-    
-    private void handleAspectAwareAdded(final DependencyService dependencyService, final ServiceReference reference, final Object service) {
-		debugLog("aspectawareadded: " + reference.getProperty("service.ranking"));
-		if (componentIsDependencyManagerFactory(dependencyService)) {
-			// component is either aspect or adapter factory instance, these must be ignored.
-			return;
-		}
-		boolean invokeAdded = false;
-		boolean invokeSwapped = false;
-		Integer ranking = ServiceUtil.getRankingAsInteger(reference);
-		Tuple newHighestRankedService = null;
-		Tuple prevHighestRankedService = null;
-		Runnable callbackRunnable = null;
-		Map rankings = null;
-		synchronized (m_componentByRank) {
-			Long originalServiceId = ServiceUtil.getServiceIdAsLong(reference);
-			Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
-			if (componentMap == null) {
-				// create new componentMap
-				componentMap = new HashMap(); /* <Long, Map<Integer, Tuple>> */
-				m_componentByRank.put(dependencyService, componentMap);
-			}
-			rankings = (Map) componentMap.get(originalServiceId); /* <Integer, Tuple> */
-			if (rankings == null) {
-				// new component added
-				rankings = new HashMap(); /* <Integer, Tuple> */
-				componentMap.put(originalServiceId, rankings);
-				rankings.put(ranking, new Tuple(reference, service));
-				invokeAdded = true;
-			} 
-			
-			if (!invokeAdded) {
-				// current highest ranked
-				prevHighestRankedService = (Tuple)getHighestRankedService(dependencyService, originalServiceId).getValue();
-				newHighestRankedService = swapHighestRankedService(dependencyService, originalServiceId, reference, service, ranking);
-				debugLog("prevhigh: " + prevHighestRankedService.getServiceReference().getProperty("service.ranking") + ", new high: " + newHighestRankedService.getServiceReference().getProperty("service.ranking"));
-				if (!prevHighestRankedService.getServiceReference().equals(newHighestRankedService.getServiceReference())) {
-					// new highest ranked service
-					debugLog("New highest ranked to swap to");
-					invokeSwapped = true;
-				} else {
-					debugLog("Ignoring lower ranked or irrelevant swap");
-				}
-			}
-			debugLog(m_componentByRank.toString());
-			
-			// up until this point should be synchronized on m_componentsByRank to keep integrity of the administration and consequences
-			// then the do phase comes, here we want to guarantee the effects of this operation are done like they were synchronized, however
-			// synchronization on m_componentsByRank to too course grained here, so we'd like to switch to synchronization on the
-			// original service id, therefore we're using our own guarded block to ensure the correct order.
-			
-			if (invokeAdded) {
-				debugLog("invoke added: " + reference.getProperty("service.ranking"));
-				callbackRunnable = createCallbackRunnable(dependencyService, reference, service, m_callbackAdded);
-				enqueueCallback(callbackRunnable);
-			} else if (invokeSwapped) {
-				debugLog("invoke swapped: " + newHighestRankedService.getServiceReference().getProperty("service.ranking") + " replacing " + prevHighestRankedService.getServiceReference().getProperty("service.ranking"));
-				callbackRunnable = createSwapRunnable(dependencyService, prevHighestRankedService.getServiceReference(), prevHighestRankedService.getService(), newHighestRankedService.getServiceReference(), newHighestRankedService.getService());
-				enqueueCallback(callbackRunnable);
-			}    	
-		}
-		if (callbackRunnable != null) {
-			waitForCallbackLock(callbackRunnable);
-			synchronized (rankings) {
-				releaseCallback(callbackRunnable);
-				execute(callbackRunnable);
-			}
-		}
-    }
-    
-    private Runnable createCallbackRunnable(final DependencyService dependencyService, final ServiceReference reference, final Object service, final String callback) {
-    	return new Runnable() {
-			public void run() {
-				invoke(dependencyService, reference, service, callback);			
-			}
-			public String toString() {
-				return callback + " on " + dependencyService;
-			}
-		};
-    }
-    
-    private Runnable createSwapRunnable(final DependencyService dependencyService, final ServiceReference prevReference, final Object prevService, final ServiceReference newReference, final Object newService) {
-    	return new Runnable() {
-			public void run() {
-				invokeSwappedCallback(dependencyService, prevReference, prevService, newReference, newService);					
-			}
-			public String toString() {
-				return "swap on " + dependencyService;
-			}
-		};
-    }
-    
-    private void execute(Runnable runnable) {
-    	runnable.run();
-    }
-    
-    private void debugLog(String message) {
-    	if (m_debug) {
-    		m_logger.log(Logger.LOG_DEBUG, "[" + m_debugKey + "] " + message);
-    	}
-    }
-    
-    private boolean componentIsDependencyManagerFactory(DependencyService dependencyService) {
-        Object component = dependencyService.getService();
-        if (component != null) {
-            String className = component.getClass().getName();
-            return className.startsWith("org.apache.felix.dm")
-                && !className.startsWith("org.apache.felix.dm.impl.AdapterServiceImpl$AdapterImpl")
-                && !className.startsWith("org.apache.felix.dm.test");
-        }
-        return false;
-    }
-    
-	private Tuple swapHighestRankedService(DependencyService dependencyService, Long serviceId, ServiceReference newReference, Object newService, Integer newRanking) {
-		// does a component with a higher ranking exist
-		synchronized (m_componentByRank) {
-			Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
-			Map rankings = (Map) componentMap.get(serviceId); /* <Integer, Tuple> */
-			rankings.put(newRanking, new Tuple(newReference, newService));
-			Entry highestEntry = getHighestRankedService(dependencyService, serviceId); /* <Integer, Tuple> */
-			return (Tuple) highestEntry.getValue();
-		}
-	}
-	
-	private Entry getHighestRankedService(DependencyService dependencyService, Long serviceId) { /* <Integer, Tuple> */
-		Entry highestEntry = null; /* <Integer, Tuple> */
-		Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
-		Map rankings = (Map) componentMap.get(serviceId); /* <Integer, Tuple> */
-		if (rankings != null) {
-			for (Iterator entryIterator = rankings.entrySet().iterator(); entryIterator.hasNext(); ) { /* <Integer, Tuple> */
-				Entry mapEntry = (Entry) entryIterator.next();
-				if (highestEntry == null) {
-					highestEntry = mapEntry;
-				} else {
-					if (((Integer)mapEntry.getKey()).intValue() > ((Integer)highestEntry.getKey()).intValue()) {
-						highestEntry = mapEntry;
-					}
-				}
-			}
-		}
-		return highestEntry;
-	}
-
-
-
-	private boolean isLastService(DependencyService dependencyService, ServiceReference reference, Object object, Long serviceId) {
-		// get the collection of rankings
-		Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
-		
-		Map rankings = null; /* <Integer, Tuple> */
-		if (componentMap != null) {
-			rankings = (Map) componentMap.get(serviceId);
-		}
-		// if there is only one element left in the collection of rankings
-		// and this last element has the same ranking as the supplied service (in other words, it is the same)
-		// then this is the last service
-		// NOTE: it is possible that there is only one element, but that it's not equal to the supplied service,
-		// because an aspect on top of the original service is being removed (but the original service is still
-		// there). That in turn triggers:
-		// 1) a call to added(original-service)
-		// 2) that causes a swap
-		// 3) a call to removed(aspect-service) <-- that's what we're talking about
-		debugLog("last service: " + m_componentByRank.toString());
-		return (componentMap != null && rankings != null && rankings.size() == 1 && ((Entry)rankings.entrySet().iterator().next()).getKey()
-				.equals(ServiceUtil.getRankingAsInteger(reference)));
-	}
-	
-	
-    public void invokeChanged(DependencyService dependencyService, ServiceReference reference, Object service) {
-        invoke(dependencyService, reference, service, m_callbackChanged);
-    }
-
-    public void invokeRemoved(DependencyService dependencyService, ServiceReference reference, Object service) {
-		debugLog("invoke removed");
-        boolean removed = false;
-        synchronized (m_sr) {
-            Set set = (Set) m_sr.get(dependencyService);
-            removed = (set != null && set.remove(new Tuple(reference, service)));
-        }
-    	debugLog("removed: " + removed);
-        if (removed) {
-        	if (m_callbackSwapped != null) {
-        		handleAspectAwareRemoved(dependencyService, reference, service);
-        	}
-        	else {
-        		invoke(dependencyService, reference, service, m_callbackRemoved);
-        	}
-        }
-    }
-    
-	private void handleAspectAwareRemoved(DependencyService dependencyService, ServiceReference reference, Object service) {
-		debugLog("aspectawareremoved: " + reference.getProperty("service.ranking"));
-		if (componentIsDependencyManagerFactory(dependencyService)) {
-			// component is either aspect or adapter factory instance, these must be ignored.
-			return;
-		}
-		// we might need to swap here too!
-		boolean invokeRemoved = false;
-		Long serviceId = ServiceUtil.getServiceIdAsLong(reference);
-		Tuple prevHighestRankedService = null;
-		Tuple newHighestRankedService = null;
-		boolean invokeSwapped = false;
-		Map rankings = null;
-		Runnable callbackRunnable = null;
-		synchronized (m_componentByRank) {
-			Long originalServiceId = ServiceUtil.getServiceIdAsLong(reference);
-			if (isLastService(dependencyService, reference, service, serviceId)) {
-				invokeRemoved = true;
-			} else {
-				// not the last service, but should we swap?
-				prevHighestRankedService = (Tuple)getHighestRankedService(dependencyService, originalServiceId).getValue();
-				if (prevHighestRankedService.getServiceReference().equals(reference)) {
-					// swapping out
-					debugLog("Swap out on remove!");
-					invokeSwapped = true;
-				}
-			}
-			debugLog("is last service: " + invokeRemoved);
-			// cleanup
-			Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
-			if (componentMap != null) {
-				rankings = (Map) componentMap.get(originalServiceId); /* <Integer, Tuple> */
-				List rankingsToRemove = new ArrayList();
-				for (Iterator entryIterator = rankings.entrySet().iterator(); entryIterator.hasNext(); ) {
-					Entry mapEntry = (Entry) entryIterator.next();
-					if (((Tuple)mapEntry.getValue()).getServiceReference().equals(reference)) {
-						// remove the reference
-						// rankings.remove(mapEntry.getKey());
-						rankingsToRemove.add(mapEntry.getKey());
-					}
-				}
-				for (Iterator rankingIterator = rankingsToRemove.iterator(); rankingIterator.hasNext(); ) {
-					rankings.remove(rankingIterator.next());
-				}
-				if (rankings.size() == 0) {
-					componentMap.remove(originalServiceId);
-				}
-				if (componentMap.size() == 0) {
-					m_componentByRank.remove(dependencyService);
-				}
-			}
-			// determine current highest ranked service
-			if (invokeSwapped) {
-				newHighestRankedService = (Tuple)getHighestRankedService(dependencyService, originalServiceId).getValue();
-			}
-			if (invokeRemoved) {
-				// handle invoke outside the sync block since we won't know what will happen there
-				debugLog("invoke removed: " + reference.getProperty("service.ranking"));
-				callbackRunnable = createCallbackRunnable(dependencyService, reference, service, m_callbackRemoved);
-				enqueueCallback(callbackRunnable);
-			} else if (invokeSwapped) {
-				debugLog("invoke swapped: " + newHighestRankedService.getServiceReference().getProperty("service.ranking") + " replacing " + prevHighestRankedService.getServiceReference().getProperty("service.ranking"));
-				callbackRunnable = createSwapRunnable(dependencyService, prevHighestRankedService.getServiceReference(), prevHighestRankedService.getService(), newHighestRankedService.getServiceReference(), newHighestRankedService.getService());
-				enqueueCallback(callbackRunnable);
-			}
-		}
-		if (callbackRunnable != null) {
-			waitForCallbackLock(callbackRunnable);
-			synchronized (rankings) {
-				releaseCallback(callbackRunnable);
-				execute(callbackRunnable);
-			}
-		}
-	}    
-
-    public void invoke(DependencyService dependencyService, ServiceReference reference, Object service, String name) {
-		debugLog("invoke: " + name);
-        if (name != null) {
-            dependencyService.invokeCallbackMethod(getCallbackInstances(dependencyService), name, 
-                new Class[][] {
-                    {Component.class, ServiceReference.class, m_trackedServiceName}, {Component.class, ServiceReference.class, Object.class}, {Component.class, ServiceReference.class}, {Component.class, m_trackedServiceName}, {Component.class, Object.class}, {Component.class}, {Component.class, Map.class, m_trackedServiceName},
-                    {ServiceReference.class, m_trackedServiceName}, {ServiceReference.class, Object.class}, {ServiceReference.class}, {m_trackedServiceName}, {Object.class}, {}, {Map.class, m_trackedServiceName}
-                },
-                new Object[][] {
-                    {dependencyService, reference, service}, {dependencyService, reference, service}, {dependencyService, reference}, {dependencyService, service}, {dependencyService, service}, {dependencyService}, {dependencyService, new ServicePropertiesMap(reference), service},
-                    {reference, service}, {reference, service}, {reference}, {service}, {service}, {}, {new ServicePropertiesMap(reference), service}
-                }    
-            );
-        }
-    }
-    
-	private void invokeSwappedCallback(DependencyService component, ServiceReference previousReference, Object previous, ServiceReference currentServiceReference,
-			Object current) {
-		// sanity check on the service references
-		Integer oldRank = (Integer) previousReference.getProperty(Constants.SERVICE_RANKING);
-		Integer newRank = (Integer) currentServiceReference.getProperty(Constants.SERVICE_RANKING);
-		
-		if (oldRank != null && newRank != null && oldRank.equals(newRank)) {
-			throw new IllegalStateException("Attempt to swap a service for a service with the same rank! previousReference: " + previousReference + ", currentReference: " + currentServiceReference);
-		}
-		
-		component.invokeCallbackMethod(getCallbackInstances(component), m_callbackSwapped, new Class[][] { 
-			{ m_trackedServiceName, m_trackedServiceName },
-			{ Object.class, Object.class }, 
-			{ ServiceReference.class, m_trackedServiceName, ServiceReference.class, m_trackedServiceName },
-			{ ServiceReference.class, Object.class, ServiceReference.class, Object.class }, 
-			{ Component.class, m_trackedServiceName, m_trackedServiceName },
-			{ Component.class, Object.class, Object.class }, 
-			{ Component.class, ServiceReference.class, m_trackedServiceName, ServiceReference.class, m_trackedServiceName },
-			{ Component.class, ServiceReference.class, Object.class, ServiceReference.class, Object.class } 
-		}, 
-		new Object[][] { 
-			{ previous, current },
-			{ previous, current }, 
-			{ previousReference, previous, currentServiceReference, current },
-			{ previousReference, previous, currentServiceReference, current },
-			{ component, previous, current },
-			{ component, previous, current }, 
-			{ component, previousReference, previous, currentServiceReference, current },
-			{ component, previousReference, previous, currentServiceReference, current } 					
-		});
-	}    
-
-    protected synchronized boolean makeAvailable() {
-        if (!isAvailable()) {
-            m_isAvailable = true;
-            return true;
-        }
-        return false;
-    }
-    
-    private synchronized boolean makeUnavailable() {
-        if ((isAvailable()) && (!m_tracker.hasReference())) {
-            m_isAvailable = false;
-            return true;
-        }
-        return false;
-    }
-    
-    private synchronized Object[] getCallbackInstances(DependencyService dependencyService) {
-        if (m_callbackInstance == null) {
-            return dependencyService.getCompositionInstances();
-        }
-        else {
-            return new Object[] { m_callbackInstance };
-        }
-    }
-    
     // ----- CREATION
 
     /**
@@ -936,11 +438,12 @@
      * @param serviceName the name of the service
      * @return this service dependency
      */
+    //@Override
     public synchronized ServiceDependency setService(Class serviceName) {
         setService(serviceName, null, null);
         return this;
     }
-    
+
     /**
      * Sets the name of the service that should be tracked. You can either specify
      * only the name, only the filter, or the name and a filter.
@@ -958,11 +461,12 @@
      * @param serviceFilter the filter condition
      * @return this service dependency
      */
+    //@Override
     public synchronized ServiceDependency setService(Class serviceName, String serviceFilter) {
         setService(serviceName, null, serviceFilter);
         return this;
     }
-    
+
     /**
      * Sets the name of the service that should be tracked. The name is assumed to be 
      * a service of type <code>Object</code> which means that, when auto configuration 
@@ -972,6 +476,7 @@
      * @param serviceFilter the filter condition
      * @return this service dependency
      */
+    //@Override
     public synchronized ServiceDependency setService(String serviceFilter) {
         if (serviceFilter == null) {
             throw new IllegalArgumentException("Service filter cannot be null.");
@@ -990,44 +495,12 @@
      * @param serviceReference the service reference to track
      * @return this service dependency
      */
+    //@Override
     public synchronized ServiceDependency setService(Class serviceName, ServiceReference serviceReference) {
         setService(serviceName, serviceReference, null);
         return this;
     }
 
-    /** Internal method to set the name, service reference and/or filter. */
-    private void setService(Class serviceName, ServiceReference serviceReference, String serviceFilter) {
-        ensureNotActive();
-        if (serviceName == null) {
-            m_trackedServiceName = Object.class;
-        }
-        else {
-            m_trackedServiceName = serviceName;
-        }
-        if (serviceFilter != null) {
-            m_trackedServiceFilterUnmodified = serviceFilter;
-            if (serviceName == null) {
-                m_trackedServiceFilter = serviceFilter;
-            }
-            else {
-                m_trackedServiceFilter ="(&(" + Constants.OBJECTCLASS + "=" + serviceName.getName() + ")" + serviceFilter + ")";
-            }
-        }
-        else {
-            m_trackedServiceFilterUnmodified = null;
-            m_trackedServiceFilter = null;
-        }
-        if (serviceReference != null) {
-            m_trackedServiceReference = serviceReference;
-            if (serviceFilter != null) {
-                throw new IllegalArgumentException("Cannot specify both a filter and a service reference.");
-            }
-        }
-        else {
-            m_trackedServiceReference = null;
-        }
-    }
-    
     /**
      * Sets the default implementation for this service dependency. You can use this to supply
      * your own implementation that will be used instead of a Null Object when the dependency is
@@ -1038,6 +511,7 @@
      *     instantiate this implementation
      * @return this service dependency
      */
+    //@Override
     public synchronized ServiceDependency setDefaultImplementation(Object implementation) {
         ensureNotActive();
         m_defaultImplementation = implementation;
@@ -1050,12 +524,14 @@
      * @param required the required flag
      * @return this service dependency
      */
+    //@Override
     public synchronized ServiceDependency setRequired(boolean required) {
         ensureNotActive();
         setIsRequired(required);
         return this;
     }
-    
+
+    //@Override
     public ServiceDependency setInstanceBound(boolean isInstanceBound) {
         setIsInstanceBound(isInstanceBound);
         return this;
@@ -1069,13 +545,14 @@
      * @param autoConfig the value of auto config
      * @return this service dependency
      */
+    //@Override
     public synchronized ServiceDependency setAutoConfig(boolean autoConfig) {
         ensureNotActive();
         m_autoConfig = autoConfig;
         m_autoConfigInvoked = true;
         return this;
     }
-    
+
     /**
      * Sets auto configuration for this service. Auto configuration allows the
      * dependency to fill in the attribute in the service implementation that
@@ -1084,6 +561,7 @@
      * @param instanceName the name of attribute to auto config
      * @return this service dependency
      */
+    //@Override
     public synchronized ServiceDependency setAutoConfig(String instanceName) {
         ensureNotActive();
         m_autoConfig = (instanceName != null);
@@ -1091,7 +569,7 @@
         m_autoConfigInvoked = true;
         return this;
     }
-    
+
     /**
      * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
      * dependency is added or removed. When you specify callbacks, the auto configuration 
@@ -1102,6 +580,7 @@
      * @param removed the method to call when a service was removed
      * @return this service dependency
      */
+    //@Override
     public synchronized ServiceDependency setCallbacks(String added, String removed) {
         return setCallbacks((Object) null, added, null, removed);
     }
@@ -1117,10 +596,11 @@
      * @param removed the method to call when a service was removed
      * @return this service dependency
      */
+    //@Override
     public synchronized ServiceDependency setCallbacks(String added, String changed, String removed) {
         return setCallbacks((Object) null, added, changed, removed);
     }
-    
+
     /**
      * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
      * dependency is added, changed or removed. When you specify callbacks, the auto 
@@ -1133,8 +613,9 @@
      * removal of an aspect
      * @return this service dependency
      */
+    //@Override
     public synchronized ServiceDependency setCallbacks(String added, String changed, String removed, String swapped) {
-    	return setCallbacks((Object) null, added, changed, removed, swapped);
+        return setCallbacks((Object) null, added, changed, removed, swapped);
     }
 
     /**
@@ -1148,10 +629,11 @@
      * @param removed the method to call when a service was removed
      * @return this service dependency
      */
+    //@Override
     public synchronized ServiceDependency setCallbacks(Object instance, String added, String removed) {
         return setCallbacks(instance, added, (String) null, removed);
     }
-    
+
     /**
      * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
      * dependency is added, changed or removed. They are called on the instance you provide. When you
@@ -1164,10 +646,11 @@
      * @param removed the method to call when a service was removed
      * @return this service dependency
      */
+    //@Override
     public synchronized ServiceDependency setCallbacks(Object instance, String added, String changed, String removed) {
-    	return setCallbacks(instance, added, changed, removed, null);
+        return setCallbacks(instance, added, changed, removed, null);
     }
-    
+
     /**
      * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
      * dependency is added, changed or removed. When you specify callbacks, the auto 
@@ -1180,65 +663,204 @@
      * @param swapped the method to call when the service was swapped due to addition or 
      * removal of an aspect
      * @return this service dependency
-     */    
+     */
+    //@Override
     public synchronized ServiceDependency setCallbacks(Object instance, String added, String changed, String removed, String swapped) {
         ensureNotActive();
         // if at least one valid callback is specified, we turn off auto configuration, unless
         // someone already explicitly invoked autoConfig
-        if ((added != null || removed != null || changed != null || swapped != null) && ! m_autoConfigInvoked) {
+        if ((added != null || removed != null || changed != null || swapped != null) && !m_autoConfigInvoked) {
             setAutoConfig(false);
         }
-    	m_callbackInstance = instance;
+        m_callbackInstance = instance;
         m_callbackAdded = added;
         m_callbackChanged = changed;
-        m_callbackRemoved = removed;    
+        m_callbackRemoved = removed;
         m_callbackSwapped = swapped;
-    	return this;
+        return this;
     }
-    
-    private void ensureNotActive() {
-        if (m_tracker != null) {
-            throw new IllegalStateException("Cannot modify state while active.");
+
+    //@Override
+    public ServiceDependency setPropagate(boolean propagate) {
+        ensureNotActive();
+        m_propagate = propagate;
+        return this;
+    }
+
+    //@Override
+    public ServiceDependency setPropagate(Object instance, String method) {
+        setPropagate(instance != null && method != null);
+        m_propagateCallbackInstance = instance;
+        m_propagateCallbackMethod = method;
+        return this;
+    }
+
+    // --------------------------------------- Protected methods -------------------------------------------------------------------
+
+    protected synchronized boolean makeAvailable() {
+        if (!isAvailable()) {
+            m_isAvailable = true;
+            return true;
         }
-    }
-    
-    public synchronized String toString() {
-        return "ServiceDependency[" + m_trackedServiceName + " " + m_trackedServiceFilterUnmodified + "]";
+        return false;
     }
 
-    public String getAutoConfigName() {
-        return m_autoConfigInstance;
-    }
-    
-    public Object getAutoConfigInstance() {
-        return lookupService();
-    }
-    
-    public Class getAutoConfigType() {
-        return getInterface();
-    }
-
-    public String getName() {
-        StringBuilder sb = new StringBuilder();
-        if (m_trackedServiceName != null) {
-            sb.append(m_trackedServiceName.getName());
-            if (m_trackedServiceFilterUnmodified != null) {
-                sb.append(' ');
-                sb.append(m_trackedServiceFilterUnmodified);
+    protected synchronized Object getService() {
+        Object service = null;
+        if (m_isStarted) {
+            service = m_tracker.getService();
+        }
+        if (service == null && isAutoConfig()) {
+            service = getDefaultImplementation();
+            if (service == null) {
+                service = getNullObject();
             }
         }
-        if (m_trackedServiceReference != null) {
-            sb.append("{service.id=" + m_trackedServiceReference.getProperty(Constants.SERVICE_ID)+"}");
+        return service;
+    }
+
+    // --------------------------------------- Private methods --------------------------------------------
+
+    private void _start(DependencyService service) {
+        boolean needsStarting = false;
+        synchronized (this) {
+            m_services.add(service);
+            if (!m_isStarted) {
+                if (m_trackedServiceName != null) {
+                    if (m_trackedServiceFilter != null) {
+                        try {
+                            m_tracker = new ServiceTracker(m_context, m_context.createFilter(m_trackedServiceFilter), this);
+                        } catch (InvalidSyntaxException e) {
+                            throw new IllegalStateException("Invalid filter definition for dependency: " + m_trackedServiceFilter);
+                        }
+                    } else if (m_trackedServiceReference != null) {
+                        m_tracker = new ServiceTracker(m_context, m_trackedServiceReference, this);
+                    } else {
+                        m_tracker = new ServiceTracker(m_context, m_trackedServiceName.getName(), this);
+                    }
+                } else {
+                    throw new IllegalStateException("Could not create tracker for dependency, no service name specified.");
+                }
+                m_isStarted = true;
+                needsStarting = true;
+            }
         }
-        return sb.toString();
+        if (needsStarting) {
+            // when the swapped callback is set, also track the aspects
+            boolean trackAllServices = false;
+            boolean trackAllAspects = false;
+            if (m_callbackSwapped != null) {
+                trackAllAspects = true;
+            }
+            m_tracker.open(trackAllServices, trackAllAspects);
+        }
     }
 
-    public String getType() {
-        return "service";
+    private void _stop(DependencyService service) {
+        boolean needsStopping = false;
+        synchronized (this) {
+            if (m_services.size() == 1 && m_services.contains(service)) {
+                m_isStarted = false;
+                needsStopping = true;
+            }
+        }
+        if (needsStopping) {
+            m_tracker.close();
+            m_tracker = null;
+        }
+        //moved this down
+        synchronized (this) {
+            m_services.remove(service);
+        }
     }
 
-    public void invokeAdded(DependencyService service) {
-		debugLog("invoke added due to configure. (component is activated)");
+    private void _addedService(ServiceReference ref, Object service) {
+        debugLog("addedservice: " + ref);
+        boolean makeAvailable = makeAvailable();
+
+        Object[] services;
+        synchronized (this) {
+            services = m_services.toArray();
+        }
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = (DependencyService) services[i];
+            if (makeAvailable) {
+                if (ds.isInstantiated() && isInstanceBound() && isRequired()) {
+                    debugLog("invoke added: " + ref);              
+                    invokeAdded(ds, ref, service); //**
+                }
+                // The dependency callback will be deferred until all required dependency are available.
+                debugLog("dependency available: " + ref);
+                ds.dependencyAvailable(this); //**
+                if (!isRequired()) {
+                    // For optional dependency, we always invoke callback, because at this point, we know
+                    // that the service has been started, and the service start method has been called.
+                    // (See the ServiceImpl.bindService method, which will activate optional dependencies using 
+                    // startTrackingOptional() method).
+                    debugLog("invoke added: " + ref);
+                    invokeAdded(ds, ref, service); //**
+                }
+            } else {
+                debugLog("dependency changed: " + ref);
+                ds.dependencyChanged(this); //**
+                // At this point, either the dependency is optional (meaning that the service has been started,
+                // 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.
+
+                // we only try to invoke the method here if we are really already instantiated
+                if (ds.isInstantiated() && ds.getCompositionInstances().length > 0) {
+                    debugLog("invoke added: " + ref);
+                    invokeAdded(ds, ref, service); //**
+                }
+            }
+        }
+    }
+
+    private void _modifiedService(ServiceReference ref, Object service) {
+        Object[] services;
+        synchronized (this) {
+            services = m_services.toArray();
+        }
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = (DependencyService) services[i];
+            ds.dependencyChanged(this);
+            if (ds.isRegistered()) {
+                invokeChanged(ds, ref, service);
+            }
+        }
+    }
+
+    private void _removedService(ServiceReference ref, Object service) {
+        debugLog("removedservice: " + ref + ", rank: " + ref.getProperty("service.ranking"));
+        boolean makeUnavailable = makeUnavailable();
+        debugLog("make unavailable: " + makeUnavailable);
+        Object[] services;
+        synchronized (this) {
+            services = m_services.toArray();
+        }
+
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = (DependencyService) services[i];
+            if (makeUnavailable) {
+                ds.dependencyUnavailable(this);
+                // when the dependency is optional or the dependency is instance bound and the component is instantiated (and the dependency is required)
+                // then remove is invoked. In other cases the removed has been when the component was unconfigured.
+                if (!isRequired() || (ds.isInstantiated() && isInstanceBound())) {
+                    invokeRemoved(ds, ref, service);
+                }
+            } else {
+                ds.dependencyChanged(this);
+                invokeRemoved(ds, ref, service);
+            }
+        }
+        // unget what we got in addingService (see ServiceTracker 701.4.1)
+        m_context.ungetService(ref);
+
+    }
+
+    private void _invokeAdded(DependencyService service) {
+        debugLog("invoke added due to configure. (component is activated)");
         ServiceReference[] refs = m_tracker.getServiceReferences();
         if (refs != null) {
             for (int i = 0; i < refs.length; i++) {
@@ -1248,21 +870,21 @@
             }
         }
     }
-    
-    public void invokeRemoved(DependencyService service) {
-		debugLog("invoke removed due to unconfigure. (component is destroyed)");
+
+    private void _invokeRemoved(DependencyService service) {
+        debugLog("invoke removed due to unconfigure. (component is destroyed)");
         Set references = null;
         Object[] tupleArray = null;
         synchronized (m_sr) {
             references = (Set) m_sr.get(service);
             // is this null check necessary ??
             if (references != null) {
-	            tupleArray = references.toArray(new Tuple[references.size()]);
+                tupleArray = references.toArray(new Tuple[references.size()]);
             }
         }
 
-        Tuple[] refs = (Tuple[]) (tupleArray != null ?  tupleArray : new Tuple[0]);
-    
+        Tuple[] refs = (Tuple[]) (tupleArray != null ? tupleArray : new Tuple[0]);
+
         for (int i = 0; i < refs.length; i++) {
             ServiceReference sr = refs[i].getServiceReference();
             Object svc = refs[i].getService();
@@ -1270,53 +892,458 @@
         }
     }
 
-    public Dictionary getProperties() {
-        ServiceReference reference = lookupServiceReference();
-        Object service = lookupService();
-        if (reference != null) {
-            if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
-                try {
-                    return (Dictionary) InvocationUtil.invokeCallbackMethod(m_propagateCallbackInstance, m_propagateCallbackMethod, new Class[][] {{ ServiceReference.class, Object.class }, { ServiceReference.class }}, new Object[][] {{ reference, service }, { reference }});
-                }
-                catch (InvocationTargetException e) {
-                    m_logger.log(LogService.LOG_WARNING, "Exception while invoking callback method", e.getCause());
-                }
-                catch (Exception e) {
-                    m_logger.log(LogService.LOG_WARNING, "Exception while trying to invoke callback method", e);
-                }
-                throw new IllegalStateException("Could not invoke callback");
-            }
-            else {
-                Properties props = new Properties();
-                String[] keys = reference.getPropertyKeys();
-                for (int i = 0; i < keys.length; i++) {
-                    if (!(keys[i].equals(Constants.SERVICE_ID) || keys[i].equals(Constants.SERVICE_PID))) {
-                        props.put(keys[i], reference.getProperty(keys[i]));
+    private Object lookupService() {
+        Object service = null;
+        if (m_isStarted) {
+            service = getService();
+        } else {
+            ServiceReference[] refs = null;
+            ServiceReference ref = null;
+            if (m_trackedServiceName != null) {
+                if (m_trackedServiceFilter != null) {
+                    try {
+                        refs = m_context.getServiceReferences(m_trackedServiceName.getName(), m_trackedServiceFilter);
+                        if (refs != null) {
+                            Arrays.sort(refs, COMPARATOR);
+                            ref = refs[0];
+                        }
+                    } catch (InvalidSyntaxException e) {
+                        throw new IllegalStateException("Invalid filter definition for dependency.");
                     }
+                } else if (m_trackedServiceReference != null) {
+                    ref = m_trackedServiceReference;
+                } else {
+                    ref = m_context.getServiceReference(m_trackedServiceName.getName());
                 }
-                return props;
+                if (ref != null) {
+                    service = m_context.getService(ref);
+                }
+            } else {
+                throw new IllegalStateException("Could not lookup dependency, no service name specified.");
             }
         }
-        else {
-            throw new IllegalStateException("cannot find service reference");
+        if (service == null && isAutoConfig()) {
+            service = getDefaultImplementation();
+            if (service == null) {
+                service = getNullObject();
+            }
+        }
+        return service;
+    }
+
+    private ServiceReference lookupServiceReference() {
+        // TODO lots of duplication in lookupService()
+        ServiceReference service = null;
+        if (m_isStarted) {
+            service = m_tracker.getServiceReference();
+        } else {
+            ServiceReference[] refs = null;
+            ServiceReference ref = null;
+            if (m_trackedServiceName != null) {
+                if (m_trackedServiceFilter != null) {
+                    try {
+                        refs = m_context.getServiceReferences(m_trackedServiceName.getName(), m_trackedServiceFilter);
+                        if (refs != null) {
+                            Arrays.sort(refs, COMPARATOR);
+                            ref = refs[0];
+                        }
+                    } catch (InvalidSyntaxException e) {
+                        throw new IllegalStateException("Invalid filter definition for dependency.");
+                    }
+                } else if (m_trackedServiceReference != null) {
+                    ref = m_trackedServiceReference;
+                } else {
+                    ref = m_context.getServiceReference(m_trackedServiceName.getName());
+                }
+                if (ref != null) {
+                    service = ref;
+                }
+            } else {
+                throw new IllegalStateException("Could not lookup dependency, no service name specified.");
+            }
+        }
+        return service;
+    }
+
+    private synchronized Class getInterface() {
+        return m_trackedServiceName;
+    }
+
+    private Object getNullObject() {
+        if (m_nullObject == null) {
+            Class trackedServiceName;
+            synchronized (this) {
+                trackedServiceName = m_trackedServiceName;
+            }
+            try {
+                m_nullObject = Proxy.newProxyInstance(trackedServiceName.getClassLoader(), new Class[]{trackedServiceName},
+                        new DefaultNullObject());
+            } catch (Exception e) {
+                m_logger.log(Logger.LOG_ERROR, "Could not create null object for " + trackedServiceName + ".", e);
+            }
+        }
+        return m_nullObject;
+    }
+
+    private Object getDefaultImplementation() {
+        if (m_defaultImplementation != null) {
+            if (m_defaultImplementation instanceof Class) {
+                try {
+                    m_defaultImplementationInstance = ((Class) m_defaultImplementation).newInstance();
+                } catch (Exception e) {
+                    m_logger.log(Logger.LOG_ERROR, "Could not create default implementation instance of class " + m_defaultImplementation
+                            + ".", e);
+                }
+            } else {
+                m_defaultImplementationInstance = m_defaultImplementation;
+            }
+        }
+        return m_defaultImplementationInstance;
+    }
+
+    private void invokeAdded(DependencyService dependencyService, ServiceReference reference, Object service) {
+        // We are already serialized.
+        debugLog("invoke added");
+        boolean added = false;
+        synchronized (m_sr) {
+            Set set = (Set) m_sr.get(dependencyService);
+            if (set == null) {
+                set = new HashSet();
+                m_sr.put(dependencyService, set);
+            }
+            added = set.add(new Tuple(reference, service));
+        }
+        if (added) {
+            // when a changed callback is specified we might not call the added callback just yet
+            if (m_callbackSwapped != null) {
+                handleAspectAwareAdded(dependencyService, reference, service);
+            } else {
+                invoke(dependencyService, reference, service, m_callbackAdded);
+            }
         }
     }
 
-    public boolean isPropagated() {
-        return m_propagate;
+    private void invokeChanged(DependencyService dependencyService, ServiceReference reference, Object service) {
+        invoke(dependencyService, reference, service, m_callbackChanged);
+    }
+
+    private void invokeRemoved(DependencyService dependencyService, ServiceReference reference, Object service) {
+        debugLog("invoke removed");
+        boolean removed = false;
+        synchronized (m_sr) {
+            Set set = (Set) m_sr.get(dependencyService);
+            removed = (set != null && set.remove(new Tuple(reference, service)));
+        }
+        debugLog("removed: " + removed);
+        if (removed) {
+            if (m_callbackSwapped != null) {
+                handleAspectAwareRemoved(dependencyService, reference, service);
+            } else {
+                invoke(dependencyService, reference, service, m_callbackRemoved);
+            }
+        }
+    }
+
+    private void invoke(DependencyService dependencyService, ServiceReference reference, Object service, String name) {
+        debugLog("invoke: " + name);
+        if (name != null) {
+            dependencyService.invokeCallbackMethod(getCallbackInstances(dependencyService), name, new Class[][]{
+                    {Component.class, ServiceReference.class, m_trackedServiceName},
+                    {Component.class, ServiceReference.class, Object.class}, {Component.class, ServiceReference.class},
+                    {Component.class, m_trackedServiceName}, {Component.class, Object.class}, {Component.class},
+                    {Component.class, Map.class, m_trackedServiceName}, {ServiceReference.class, m_trackedServiceName},
+                    {ServiceReference.class, Object.class}, {ServiceReference.class}, {m_trackedServiceName}, {Object.class}, {},
+                    {Map.class, m_trackedServiceName}}, new Object[][]{{dependencyService, reference, service},
+                    {dependencyService, reference, service}, {dependencyService, reference}, {dependencyService, service},
+                    {dependencyService, service}, {dependencyService}, {dependencyService, new ServicePropertiesMap(reference), service},
+                    {reference, service}, {reference, service}, {reference}, {service}, {service}, {},
+                    {new ServicePropertiesMap(reference), service}});
+        }
+    }
+
+    private void handleAspectAwareAdded(final DependencyService dependencyService, final ServiceReference reference, final Object service) {
+        // At this point, we are already serialized: no need to synchronized.
+        debugLog("aspectawareadded: " + reference.getProperty("service.ranking"));
+        if (componentIsDependencyManagerFactory(dependencyService)) {
+            // component is either aspect or adapter factory instance, these must be ignored.
+            return;
+        }
+        boolean invokeAdded = false;
+        boolean invokeSwapped = false;
+        Integer ranking = ServiceUtil.getRankingAsInteger(reference);
+        Tuple newHighestRankedService = null;
+        Tuple prevHighestRankedService = null;
+        Map rankings = null;
+        //synchronized (m_componentByRank) { // don't synchronize: we are serialized and we can now invoke callbacks
+        Long originalServiceId = ServiceUtil.getServiceIdAsLong(reference);
+        Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
+        if (componentMap == null) {
+            // create new componentMap
+            componentMap = new HashMap(); /* <Long, Map<Integer, Tuple>> */
+            m_componentByRank.put(dependencyService, componentMap);
+        }
+        rankings = (Map) componentMap.get(originalServiceId); /* <Integer, Tuple> */
+        if (rankings == null) {
+            // new component added
+            rankings = new HashMap(); /* <Integer, Tuple> */
+            componentMap.put(originalServiceId, rankings);
+            rankings.put(ranking, new Tuple(reference, service));
+            invokeAdded = true;
+        }
+
+        if (!invokeAdded) {
+            // current highest ranked
+            prevHighestRankedService = (Tuple) getHighestRankedService(dependencyService, originalServiceId).getValue();
+            newHighestRankedService = swapHighestRankedService(dependencyService, originalServiceId, reference, service, ranking);
+            debugLog("prevhigh: " + prevHighestRankedService.getServiceReference().getProperty("service.ranking") + ", new high: " + 
+                     newHighestRankedService.getServiceReference().getProperty("service.ranking"));
+            if (!prevHighestRankedService.getServiceReference().equals(newHighestRankedService.getServiceReference())) {
+                // new highest ranked service
+                debugLog("New highest ranked to swap to");
+                invokeSwapped = true;
+            } else {
+                debugLog("Ignoring lower ranked or irrelevant swap");
+            }
+        }
+        debugLog(m_componentByRank.toString());
+        
+        // up until this point should be synchronized on m_componentsByRank to keep integrity of the administration and consequences
+        // then the do phase comes, here we want to guarantee the effects of this operation are done like they were synchronized, however
+        // synchronization on m_componentsByRank to too course grained here, so we'd like to switch to synchronization on the
+        // original service id, therefore we're using our own guarded block to ensure the correct order.
+
+        if (invokeAdded) {
+            debugLog("invoke added: " + reference.getProperty("service.ranking"));
+            // We can safely invoke callback since we are already serialized.
+            invoke(dependencyService, reference, service, m_callbackAdded);
+        } else if (invokeSwapped) {
+            debugLog("invoke swapped: " + newHighestRankedService.getServiceReference().getProperty("service.ranking") + " replacing " + 
+                     prevHighestRankedService.getServiceReference().getProperty("service.ranking"));            
+            // We can safely invoke callback since we are already serialized.
+            invokeSwappedCallback(dependencyService, prevHighestRankedService.getServiceReference(), prevHighestRankedService.getService(),
+                    newHighestRankedService.getServiceReference(), newHighestRankedService.getService());
+        }
+        //} 
+    }
+
+    private void log(String message) {
+        m_logger.log(Logger.LOG_DEBUG, message);
+    }
+
+    private void debugLog(String message) {
+        if (m_debug) {
+            m_logger.log(Logger.LOG_DEBUG, "[" + m_debugKey + "] " + message);
+        }
     }
     
-    public ServiceDependency setPropagate(boolean propagate) {
+    private boolean componentIsDependencyManagerFactory(DependencyService dependencyService) {
+        Object component = dependencyService.getService();
+        if (component != null) {
+            String className = component.getClass().getName();
+            return className.startsWith("org.apache.felix.dm")
+                    && !className.startsWith("org.apache.felix.dm.impl.AdapterServiceImpl$AdapterImpl")
+                    && !className.startsWith("org.apache.felix.dm.test");
+        }
+        return false;
+    }
+
+    private Tuple swapHighestRankedService(DependencyService dependencyService, Long serviceId, ServiceReference newReference,
+            Object newService, Integer newRanking) {
+        // does a component with a higher ranking exist
+        synchronized (m_componentByRank) {
+            Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
+            Map rankings = (Map) componentMap.get(serviceId); /* <Integer, Tuple> */
+            rankings.put(newRanking, new Tuple(newReference, newService));
+            Entry highestEntry = getHighestRankedService(dependencyService, serviceId); /* <Integer, Tuple> */
+            return (Tuple) highestEntry.getValue();
+        }
+    }
+
+    private Entry getHighestRankedService(DependencyService dependencyService, Long serviceId) { /* <Integer, Tuple> */
+        Entry highestEntry = null; /* <Integer, Tuple> */
+        Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
+        Map rankings = (Map) componentMap.get(serviceId); /* <Integer, Tuple> */
+        if (rankings != null) {
+            for (Iterator entryIterator = rankings.entrySet().iterator(); entryIterator.hasNext();) { /* <Integer, Tuple> */
+                Entry mapEntry = (Entry) entryIterator.next();
+                if (highestEntry == null) {
+                    highestEntry = mapEntry;
+                } else {
+                    if (((Integer) mapEntry.getKey()).intValue() > ((Integer) highestEntry.getKey()).intValue()) {
+                        highestEntry = mapEntry;
+                    }
+                }
+            }
+        }
+        return highestEntry;
+    }
+
+    private boolean isLastService(DependencyService dependencyService, ServiceReference reference, Object object, Long serviceId) {
+        // get the collection of rankings
+        Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
+
+        Map rankings = null; /* <Integer, Tuple> */
+        if (componentMap != null) {
+            rankings = (Map) componentMap.get(serviceId);
+        }
+        // if there is only one element left in the collection of rankings
+        // and this last element has the same ranking as the supplied service (in other words, it is the same)
+        // then this is the last service
+        // NOTE: it is possible that there is only one element, but that it's not equal to the supplied service,
+        // because an aspect on top of the original service is being removed (but the original service is still
+        // there). That in turn triggers:
+        // 1) a call to added(original-service)
+        // 2) that causes a swap
+        // 3) a call to removed(aspect-service) <-- that's what we're talking about
+        debugLog("last service: " + m_componentByRank.toString());
+        return (componentMap != null && rankings != null && rankings.size() == 1 && ((Entry) rankings.entrySet().iterator().next())
+                .getKey().equals(ServiceUtil.getRankingAsInteger(reference)));
+    }
+
+    private void handleAspectAwareRemoved(DependencyService dependencyService, ServiceReference reference, Object service) {
+        debugLog("aspectawareremoved: " + reference.getProperty("service.ranking"));
+        if (componentIsDependencyManagerFactory(dependencyService)) {
+            // component is either aspect or adapter factory instance, these must be ignored.
+            return;
+        }
+        // we might need to swap here too!
+        boolean invokeRemoved = false;
+        Long serviceId = ServiceUtil.getServiceIdAsLong(reference);
+        Tuple prevHighestRankedService = null;
+        Tuple newHighestRankedService = null;
+        boolean invokeSwapped = false;
+        Map rankings = null;
+        // synchronized (m_componentByRank) { // don't synchronize: we are serialized and we invoke callbacks
+        Long originalServiceId = ServiceUtil.getServiceIdAsLong(reference);
+        if (isLastService(dependencyService, reference, service, serviceId)) {
+            invokeRemoved = true;
+        } else {
+            // not the last service, but should we swap?
+            prevHighestRankedService = (Tuple) getHighestRankedService(dependencyService, originalServiceId).getValue();
+            if (prevHighestRankedService.getServiceReference().equals(reference)) {
+                // swapping out
+                debugLog("Swap out on remove!");
+                invokeSwapped = true;
+            }
+        }
+        debugLog("is last service: " + invokeRemoved);
+        // cleanup
+        Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
+        if (componentMap != null) {
+            rankings = (Map) componentMap.get(originalServiceId); /* <Integer, Tuple> */
+            List rankingsToRemove = new ArrayList();
+            for (Iterator entryIterator = rankings.entrySet().iterator(); entryIterator.hasNext();) {
+                Entry mapEntry = (Entry) entryIterator.next();
+                if (((Tuple) mapEntry.getValue()).getServiceReference().equals(reference)) {
+                    // remove the reference
+                    // rankings.remove(mapEntry.getKey());
+                    rankingsToRemove.add(mapEntry.getKey());
+                }
+            }
+            for (Iterator rankingIterator = rankingsToRemove.iterator(); rankingIterator.hasNext();) {
+                rankings.remove(rankingIterator.next());
+            }
+            if (rankings.size() == 0) {
+                componentMap.remove(originalServiceId);
+            }
+            if (componentMap.size() == 0) {
+                m_componentByRank.remove(dependencyService);
+            }
+        }
+        // determine current highest ranked service
+        if (invokeSwapped) {
+            newHighestRankedService = (Tuple) getHighestRankedService(dependencyService, originalServiceId).getValue();
+        }
+        if (invokeRemoved) {
+            // handle invoke outside the sync block since we won't know what will happen there
+            debugLog("invoke removed: " + reference.getProperty("service.ranking"));
+            // We can safely invoke callback, since we are already serialized
+            invoke(dependencyService, reference, service, m_callbackRemoved);
+        } else if (invokeSwapped) {
+            debugLog("invoke swapped: " + newHighestRankedService.getServiceReference().getProperty("service.ranking") + " replacing " + 
+                     prevHighestRankedService.getServiceReference().getProperty("service.ranking"));
+            // We can safely invoke callback, since we are already serialized
+            invokeSwappedCallback(dependencyService, prevHighestRankedService.getServiceReference(), prevHighestRankedService.getService(),
+                    newHighestRankedService.getServiceReference(), newHighestRankedService.getService());
+        }
+        //}
+    }
+
+    private void invokeSwappedCallback(DependencyService component, ServiceReference previousReference, Object previous,
+            ServiceReference currentServiceReference, Object current) {
+        // sanity check on the service references
+        Integer oldRank = (Integer) previousReference.getProperty(Constants.SERVICE_RANKING);
+        Integer newRank = (Integer) currentServiceReference.getProperty(Constants.SERVICE_RANKING);
+
+        if (oldRank != null && newRank != null && oldRank.equals(newRank)) {
+            throw new IllegalStateException("Attempt to swap a service for a service with the same rank! previousReference: "
+                    + previousReference + ", currentReference: " + currentServiceReference);
+        }
+
+        component.invokeCallbackMethod(getCallbackInstances(component), m_callbackSwapped, new Class[][]{
+                {m_trackedServiceName, m_trackedServiceName}, {Object.class, Object.class},
+                {ServiceReference.class, m_trackedServiceName, ServiceReference.class, m_trackedServiceName},
+                {ServiceReference.class, Object.class, ServiceReference.class, Object.class},
+                {Component.class, m_trackedServiceName, m_trackedServiceName}, {Component.class, Object.class, Object.class},
+                {Component.class, ServiceReference.class, m_trackedServiceName, ServiceReference.class, m_trackedServiceName},
+                {Component.class, ServiceReference.class, Object.class, ServiceReference.class, Object.class}}, new Object[][]{
+                {previous, current}, {previous, current}, {previousReference, previous, currentServiceReference, current},
+                {previousReference, previous, currentServiceReference, current}, {component, previous, current},
+                {component, previous, current}, {component, previousReference, previous, currentServiceReference, current},
+                {component, previousReference, previous, currentServiceReference, current}});
+    }
+
+    private synchronized boolean makeUnavailable() {
+        // TODO should we check also m_isStarted ?
+        if ((isAvailable()) && (m_isStarted == false || !m_tracker.hasReference())) {
+            m_isAvailable = false;
+            return true;
+        }
+        return false;
+    }
+
+    private synchronized Object[] getCallbackInstances(DependencyService dependencyService) {
+        if (m_callbackInstance == null) {
+            return dependencyService.getCompositionInstances();
+        } else {
+            return new Object[]{m_callbackInstance};
+        }
+    }
+
+    // ----- CREATION
+
+    /** Internal method to set the name, service reference and/or filter. */
+    private void setService(Class serviceName, ServiceReference serviceReference, String serviceFilter) {
         ensureNotActive();
-        m_propagate = propagate;
-        return this;
+        if (serviceName == null) {
+            m_trackedServiceName = Object.class;
+        } else {
+            m_trackedServiceName = serviceName;
+        }
+        if (serviceFilter != null) {
+            m_trackedServiceFilterUnmodified = serviceFilter;
+            if (serviceName == null) {
+                m_trackedServiceFilter = serviceFilter;
+            } else {
+                m_trackedServiceFilter = "(&(" + Constants.OBJECTCLASS + "=" + serviceName.getName() + ")" + serviceFilter + ")";
+            }
+        } else {
+            m_trackedServiceFilterUnmodified = null;
+            m_trackedServiceFilter = null;
+        }
+        if (serviceReference != null) {
+            m_trackedServiceReference = serviceReference;
+            if (serviceFilter != null) {
+                throw new IllegalArgumentException("Cannot specify both a filter and a service reference.");
+            }
+        } else {
+            m_trackedServiceReference = null;
+        }
     }
-    
-    public ServiceDependency setPropagate(Object instance, String method) {
-        setPropagate(instance != null && method != null);
-        m_propagateCallbackInstance = instance;
-        m_propagateCallbackMethod = method;
-        return this;
+
+    private void ensureNotActive() {
+        if (m_tracker != null) {
+            throw new IllegalStateException("Cannot modify state while active.");
+        }
     }
-   
 }
