FELIX-3729 initial implementation of customizers

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1424299 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
index 2c44b5c..3960e61 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
@@ -24,9 +24,7 @@
 import java.util.Collections;
 import java.util.Dictionary;
 import java.util.Enumeration;
-import java.util.HashMap;
 import java.util.Hashtable;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
@@ -35,7 +33,6 @@
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.ReentrantLock;
 
-import com.sun.xml.internal.rngom.binary.DataExceptPattern;
 import org.apache.felix.scr.Component;
 import org.apache.felix.scr.Reference;
 import org.apache.felix.scr.impl.BundleComponentActivator;
@@ -79,9 +76,9 @@
     // The dependency managers that manage every dependency
     private final List<DependencyManager> m_dependencyManagers;
 
-    private boolean m_dependencyManagersInitialized;
+    private volatile boolean m_dependencyManagersInitialized;
 
-    private final AtomicReference<Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>>> m_dependencies_map;
+    private volatile boolean m_dependenciesCollected;
 
     // A reference to the BundleComponentActivator
     private BundleComponentActivator m_activator;
@@ -121,7 +118,6 @@
         m_dependencyManagers = loadDependencyManagers( metadata );
 
         m_stateLock = new ReentrantLock( true );
-        m_dependencies_map = new AtomicReference<Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>>>();
         m_serviceRegistration = new AtomicReference<ServiceRegistration<S>>();
 
         // dump component details
@@ -511,6 +507,11 @@
                 && m_componentMetadata.getServiceMetadata().isServiceFactory();
     }
 
+    public boolean isFactory()
+    {
+        return false;
+    }
+
     public String[] getServices()
     {
         if ( m_componentMetadata.getServiceMetadata() != null )
@@ -734,73 +735,46 @@
      */
     protected boolean collectDependencies() throws IllegalStateException
     {
-        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> old = m_dependencies_map.get();
-        if ( old != null)
+        if ( m_dependenciesCollected)
         {
             log( LogService.LOG_DEBUG, "dependency map already present, do not collect dependencies", null );
             return false;
         }
         initDependencyManagers();
-        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> newDeps = new HashMap<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>>( );
-        for ( DependencyManager dependencyManager : m_dependencyManagers )
+        for ( DependencyManager<S, ?> dependencyManager : m_dependencyManagers )
         {
-            if ( !dependencyManager.prebind( newDeps ) )
+            if ( !dependencyManager.prebind() )
             {
                 //not actually satisfied any longer
-                returnServices( newDeps );
+                returnServices();
                 log( LogService.LOG_DEBUG, "Could not get required dependency for dependency manager: {0}",
                         new Object[] {dependencyManager}, null );
                 throw new IllegalStateException( "Missing dependencies, not satisfied" );
             }
         }
-        if ( !setDependencyMap( old, newDeps ) )
-        {
-            returnServices(newDeps);
-            log( LogService.LOG_DEBUG, "Another thread set the dependency map already present, do not keep collected dependencies", null );
-            return false;
-        }
+        m_dependenciesCollected = true;
         log( LogService.LOG_DEBUG, "This thread collected dependencies", null );
         return true;
     }
 
-    protected boolean setDependencyMap( Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> old, Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> newDeps )
-    {
-        return m_dependencies_map.compareAndSet( old, newDeps );
-    }
-
     protected void unsetDependencyMap()
     {
-        m_dependencies_map.set( null );
+        m_dependenciesCollected = false;
     }
 
-    private void returnServices( Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> deps )
+    private void returnServices()
     {
-        for ( Map<ServiceReference<?>, RefPair<?>> refs : deps.values() )
+        for ( DependencyManager<S, ?> dependencyManager : m_dependencyManagers )
         {
-            if ( refs != null )
-            {
-                for ( Map.Entry<ServiceReference<?>, RefPair<?>> serviceReferenceRefPairEntry : refs.entrySet() )
-                {
-                    RefPair<?> args = serviceReferenceRefPairEntry.getValue();
-                    if ( args.getServiceObject() != null )
-                    {
-                        getActivator().getBundleContext().ungetService( serviceReferenceRefPairEntry.getKey() );
-                    }
-                }
-            }
+            dependencyManager.deactivate();
         }
     }
 
-    abstract <T> void update( DependencyManager<S, T> dependencyManager, ServiceReference<T> ref );
+    abstract <T> void update( DependencyManager<S, T> dependencyManager, RefPair<T> refPair );
 
-    abstract <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, ServiceReference<T> reference );
+    abstract <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair );
 
-    abstract <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, ServiceReference<T> oldRef );
-
-    Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> getDependencyMap()
-    {
-        return m_dependencies_map.get();
-    }
+    abstract <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> oldRefPair );
 
     //**********************************************************************************************************
     public BundleComponentActivator getActivator()
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
index 27c3bb4..b3c27d8 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
@@ -21,10 +21,8 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Dictionary;
-import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.IdentityHashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -35,7 +33,6 @@
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
 import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.component.ComponentException;
 import org.osgi.service.component.ComponentFactory;
@@ -95,9 +92,15 @@
     }
 
 
+    @Override
+    public boolean isFactory()
+    {
+        return true;
+    }
+
     /* (non-Javadoc)
-     * @see org.osgi.service.component.ComponentFactory#newInstance(java.util.Dictionary)
-     */
+    * @see org.osgi.service.component.ComponentFactory#newInstance(java.util.Dictionary)
+    */
     public ComponentInstance newInstance( Dictionary dictionary )
     {
         final ImmediateComponentManager cm = createComponentManager();
@@ -267,28 +270,28 @@
 
     protected boolean collectDependencies()
     {
-        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> old = getDependencyMap();
-        if ( old == null )
-        {
-            Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependenciesMap = new HashMap<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>>();
-            for (DependencyManager dm: getDependencyManagers() )
-            {
-                dependenciesMap.put( dm, Collections.EMPTY_MAP );
-            }
-            setDependencyMap( old, dependenciesMap );
-        }
+//        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> old = getDependencyMap();
+//        if ( old == null )
+//        {
+//            Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependenciesMap = new HashMap<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>>();
+//            for (DependencyManager dm: getDependencyManagers() )
+//            {
+//                dependenciesMap.put( dm, Collections.EMPTY_MAP );
+//            }
+//            setDependencyMap( old, dependenciesMap );
+//        }
         return true;
     }
 
-    <T> void update( DependencyManager<S, T> dependencyManager, ServiceReference<T> ref )
+    <T> void update( DependencyManager<S, T> dependencyManager, RefPair<T> ref )
     {
     }
 
-    <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, ServiceReference<T> reference )
+    <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> reference )
     {
     }
 
-    <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, ServiceReference<T> oldRef )
+    <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> oldRef )
     {
     }
 
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
index d552f68..f273a36 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
@@ -21,14 +21,12 @@
 
 import java.security.Permission;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.SortedMap;
+import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.felix.scr.Component;
 import org.apache.felix.scr.Reference;
@@ -40,8 +38,6 @@
 import org.osgi.framework.Constants;
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServicePermission;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentConstants;
@@ -53,7 +49,7 @@
  * declared by a single <code>&lt;reference&gt;</code element in component
  * descriptor.
  */
-public class DependencyManager<S, T> implements ServiceListener, Reference
+public class DependencyManager<S, T> implements Reference
 {
     // mask of states ok to send events
     private static final int STATE_MASK = //Component.STATE_UNSATISFIED |
@@ -65,8 +61,9 @@
     // Reference to the metadata
     private final ReferenceMetadata m_dependencyMetadata;
 
-    // the number of matching services registered in the system
-    private final AtomicInteger m_size = new AtomicInteger();
+    private final AtomicReference<ServiceTracker<T, RefPair<T>>> trackerRef = new AtomicReference<ServiceTracker<T, RefPair<T>>>();
+
+    private final AtomicReference<Customizer<T>> customizerRef = new AtomicReference<Customizer<T>>();
 
     private BindMethods m_bindMethods;
 
@@ -76,10 +73,6 @@
     // the target service filter
     private volatile Filter m_targetFilter;
 
-    private final Object enableLock = new Object();
-    private final Collection<ServiceReference<T>> added = new ArrayList<ServiceReference<T>>();
-    private final Collection<ServiceReference<T>> removed = new ArrayList<ServiceReference<T>>();
-
     private boolean registered;
 
 
@@ -114,7 +107,544 @@
        m_bindMethods = bindMethods;
     }
 
+    private interface Customizer<T> extends ServiceTrackerCustomizer<T, RefPair<T>>
+    {
+        boolean open();
 
+        void close();
+
+        Collection<RefPair<T>> getRefs();
+        
+        void setTracker( ServiceTracker<T, RefPair<T>> tracker );
+    }
+
+    private abstract class AbstractCustomizer implements Customizer<T>
+    {
+        private ServiceTracker<T, RefPair<T>> tracker;
+
+        public void setTracker( ServiceTracker<T, RefPair<T>> tracker )
+        {
+            this.tracker = tracker;
+        }
+
+        protected ServiceTracker<T, RefPair<T>> getTracker()
+        {
+            return tracker;
+        }
+    }
+
+
+    private class FactoryCustomizer extends AbstractCustomizer {
+
+        public RefPair<T> addingService( ServiceReference<T> serviceReference )
+        {
+            RefPair<T> refPair = new RefPair<T>( serviceReference  );
+            return refPair;
+        }
+
+        public void addedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if ( !isOptional() )
+            {
+                m_componentManager.activateInternal();
+            }
+        }
+
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+        }
+
+        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if ( !isOptional() )
+            {
+                if (getTracker().isEmpty())
+                {
+                    m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
+                }
+            }
+        }
+
+        public boolean open()
+        {
+            boolean success = m_dependencyMetadata.isOptional() || !getTracker().isEmpty();
+            getTracker().getTracked( true );   //TODO activate method??
+            return success;
+        }
+
+        public void close()
+        {
+            getTracker().deactivate();
+        }
+
+        public Collection<RefPair<T>> getRefs()
+        {
+            return Collections.emptyList();
+        }
+    }
+
+    private class MultipleDynamicCustomizer extends AbstractCustomizer {
+
+        public RefPair<T> addingService( ServiceReference<T> serviceReference )
+        {
+            RefPair<T> refPair = new RefPair<T>( serviceReference  );
+            if (isActive())
+            {
+                 m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext());
+            }
+            return refPair;
+        }
+
+        public void addedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if (isActive())
+            {
+                m_componentManager.invokeBindMethod( DependencyManager.this, refPair );
+            }
+            else if ( !isOptional() )
+            {
+                m_componentManager.activateInternal();
+            }
+        }
+
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if (isActive())
+            {
+                m_componentManager.update( DependencyManager.this, refPair );
+            }
+        }
+
+        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if ( isActive() )
+            {
+                boolean unbind = true;
+                if ( !isOptional() )
+                {
+                    if (getTracker().isEmpty())
+                    {
+                        unbind = false;
+                    }
+                }
+                if ( unbind )
+                {
+                    m_componentManager.invokeUnbindMethod( DependencyManager.this, refPair );
+                }
+                else
+                {
+                    m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
+                }
+            }
+            if (refPair.getServiceObject() != null)
+            {
+                m_componentManager.getActivator().getBundleContext().ungetService( serviceReference );
+            }
+        }
+
+        public boolean open()
+        {
+            boolean success = m_dependencyMetadata.isOptional();
+            SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true );
+            for (RefPair<T> refPair: tracked.values())
+            {
+                synchronized (refPair)
+                {
+                    success |= m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext());
+                }
+            }
+            return success;
+        }
+
+        public void close()
+        {
+            for ( RefPair<T> ref : getRefs() )
+            {
+                if ( ref.getServiceObject() != null )
+                {
+                    ref.setServiceObject( null );
+                    m_componentManager.getActivator().getBundleContext().ungetService( ref.getRef() );
+                }
+            }
+            getTracker().deactivate();
+        }
+
+        public Collection<RefPair<T>> getRefs()
+        {
+            return getTracker().getTracked( true ).values();
+        }
+    }
+
+    private class MultipleStaticGreedyCustomizer extends AbstractCustomizer {
+
+
+        public RefPair<T> addingService( ServiceReference<T> serviceReference )
+        {
+            RefPair<T> refPair = new RefPair<T>( serviceReference  );
+            if (isActive())
+            {
+                 m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext());
+            }
+            return refPair;
+        }
+
+        public void addedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if (isActive())
+            {
+                m_componentManager.log( LogService.LOG_DEBUG,
+                    "Dependency Manager: Static dependency on {0}/{1} is broken", new Object[]
+                        { m_dependencyMetadata.getName(), m_dependencyMetadata.getInterface() }, null );
+                m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
+
+            }
+            m_componentManager.activateInternal();
+        }
+
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if (isActive())
+            {
+                m_componentManager.update( DependencyManager.this, refPair );
+            }
+        }
+
+        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if ( isActive() )
+            {
+                    m_componentManager.log( LogService.LOG_DEBUG,
+                        "Dependency Manager: Static dependency on {0}/{1} is broken", new Object[]
+                            { m_dependencyMetadata.getName(), m_dependencyMetadata.getInterface() }, null );
+                    m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
+                    m_componentManager.activateInternal();
+
+            }
+        }
+
+        public boolean open()
+        {
+            boolean success = m_dependencyMetadata.isOptional();
+            SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( success || !getTracker().isEmpty() );
+            for (RefPair<T> refPair: tracked.values())
+            {
+                synchronized (refPair)
+                {
+                    success |= m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext());
+                }
+            }
+            return success;
+        }
+
+        public void close()
+        {
+            for ( RefPair<T> ref: getRefs())
+            {
+                if ( ref.getServiceObject() != null)
+                {
+                    ref.setServiceObject( null );
+                    m_componentManager.getActivator().getBundleContext().ungetService( ref.getRef() );
+                }
+            }
+            getTracker().deactivate();
+        }
+
+        public Collection<RefPair<T>> getRefs()
+        {
+            return getTracker().getTracked( null ).values();
+        }
+    }
+
+    private class MultipleStaticReluctantCustomizer extends AbstractCustomizer {
+
+        private final Collection<RefPair<T>> refs = new ArrayList<RefPair<T>>();
+
+        public RefPair<T> addingService( ServiceReference<T> serviceReference )
+        {
+            RefPair<T> refPair = new RefPair<T>( serviceReference  );
+            return refPair;
+        }
+
+        public void addedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if (!isActive())
+            {
+                m_componentManager.activateInternal();
+            }
+        }
+
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if (isActive())
+            {
+                m_componentManager.update( DependencyManager.this, refPair );
+            }
+        }
+
+        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if ( isActive() )
+            {
+                if (refs.contains( refPair ))
+                {
+                    m_componentManager.log( LogService.LOG_DEBUG,
+                        "Dependency Manager: Static dependency on {0}/{1} is broken", new Object[]
+                            { m_dependencyMetadata.getName(), m_dependencyMetadata.getInterface() }, null );
+                    m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
+
+                    // FELIX-2368: immediately try to reactivate
+                    m_componentManager.activateInternal();
+
+                }
+            }
+            if (refPair.getServiceObject() != null)
+            {
+                m_componentManager.getActivator().getBundleContext().ungetService( serviceReference );
+            }
+        }
+
+        public boolean open()
+        {
+            boolean success = m_dependencyMetadata.isOptional();
+            SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true );
+            for (RefPair<T> refPair: tracked.values())
+            {
+                synchronized (refPair)
+                {
+                    success |= m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext());
+                }
+                refs.add(refPair) ;
+            }
+            return success;
+        }
+
+        public void close()
+        {
+            for ( RefPair<T> ref: getRefs())
+            {
+                if ( ref.getServiceObject() != null)
+                {
+                    ref.setServiceObject( null );
+                    m_componentManager.getActivator().getBundleContext().ungetService( ref.getRef() );
+                }
+            }
+            refs.clear();
+            getTracker().deactivate();
+        }
+
+        public Collection<RefPair<T>> getRefs()
+        {
+            return refs;
+        }
+    }
+
+    private class SingleDynamicCustomizer extends AbstractCustomizer {
+
+        private RefPair<T> refPair;
+
+        public RefPair<T> addingService( ServiceReference<T> serviceReference )
+        {
+            RefPair<T> refPair = new RefPair<T>( serviceReference  );
+            return refPair;
+        }
+
+        public void addedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if (isActive() )
+            {
+                if ( this.refPair == null || ( !isReluctant() && refPair.getRef().compareTo( this.refPair.getRef() ) > 0 ) )
+                {
+                    synchronized ( refPair )
+                    {
+                        if (!m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext() ))
+                        {
+                            //TODO error???
+                        }
+                    }
+                    m_componentManager.invokeBindMethod( DependencyManager.this, refPair );
+                    if ( this.refPair != null )
+                    {
+                        m_componentManager.invokeUnbindMethod( DependencyManager.this, this.refPair );
+                        closeRefPair();
+                    }
+                    this.refPair = refPair;
+                }
+            }
+            else if ( !isOptional() )
+            {
+                m_componentManager.activateInternal();
+            }
+        }
+
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if (isActive())
+            {
+                m_componentManager.update( DependencyManager.this, refPair );
+            }
+        }
+
+        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if (refPair == this.refPair)
+            {
+                if ( isActive() )
+                {
+                    RefPair<T> nextRefPair = null;
+                    if ( !getTracker().isEmpty() )
+                    {
+                        SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true );
+                        nextRefPair = tracked.values().iterator().next();
+                        synchronized ( nextRefPair )
+                        {
+                            if (!m_bindMethods.getBind().getServiceObject( nextRefPair, m_componentManager.getActivator().getBundleContext() ))
+                            {
+                                //TODO error???
+                            }
+                        }
+                        m_componentManager.invokeBindMethod( DependencyManager.this, nextRefPair );
+                    }
+
+                    if ( isOptional() || nextRefPair != null)
+                    {
+                        m_componentManager.invokeUnbindMethod( DependencyManager.this, refPair );
+                        closeRefPair();
+                        this.refPair = nextRefPair;
+                    }
+                    else //required and no replacement service, deactivate
+                    {
+                        m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
+                    }
+                }
+            }
+        }
+
+        public boolean open()
+        {
+            boolean success = m_dependencyMetadata.isOptional();
+            if ( success || !getTracker().isEmpty() )
+            {
+                SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true );
+                if ( !tracked.isEmpty() )
+                {
+                    RefPair<T> refPair = tracked.values().iterator().next();
+                    synchronized ( refPair )
+                    {
+                        success |= m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext() );
+                    }
+                    this.refPair = refPair;
+                }
+            }
+            return success;
+        }
+
+        public void close()
+        {
+            closeRefPair();
+            getTracker().deactivate();
+        }
+
+        private void closeRefPair()
+        {
+            if ( refPair != null && refPair.getServiceObject() != null )
+            {
+                refPair.setServiceObject( null );
+                m_componentManager.getActivator().getBundleContext().ungetService( refPair.getRef() );
+            }
+            refPair = null;
+        }
+
+        public Collection<RefPair<T>> getRefs()
+        {
+            return refPair == null? Collections.<RefPair<T>>emptyList(): Collections.singleton( refPair );
+        }
+    }
+
+    private class SingleStaticCustomizer extends AbstractCustomizer
+    {
+
+        private RefPair<T> refPair;
+
+        public RefPair<T> addingService( ServiceReference<T> serviceReference )
+        {
+            RefPair<T> refPair = new RefPair<T>( serviceReference );
+            return refPair;
+        }
+
+        public void addedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if ( isActive() )
+            {
+                if ( !isReluctant() && ( this.refPair == null || refPair.getRef().compareTo( this.refPair.getRef() ) > 0 ) )
+                {
+                    m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
+                    m_componentManager.activateInternal();
+                }
+            }
+            else
+            {
+                m_componentManager.activateInternal();
+            }
+        }
+
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if ( isActive() )
+            {
+                m_componentManager.update( DependencyManager.this, refPair );
+            }
+        }
+
+        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair )
+        {
+            if ( isActive() && refPair == this.refPair )
+            {
+                m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
+                m_componentManager.activateInternal();
+            }
+        }
+
+        public boolean open()
+        {
+            boolean success = m_dependencyMetadata.isOptional();
+            if ( success || !getTracker().isEmpty() )
+            {
+                SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true );
+                if ( !tracked.isEmpty() )
+                {
+                    RefPair<T> refPair = tracked.values().iterator().next();
+                    synchronized ( refPair )
+                    {
+                        success |= m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext() );
+                    }
+                    this.refPair = refPair;
+                }
+            }
+            return success;
+        }
+
+        public void close()
+        {
+            if ( refPair != null && refPair.getServiceObject() != null )
+            {
+                refPair.setServiceObject( null );
+                m_componentManager.getActivator().getBundleContext().ungetService( refPair.getRef() );
+            }
+            refPair = null;
+            getTracker().deactivate();
+        }
+
+        public Collection<RefPair<T>> getRefs()
+        {
+            return refPair == null ? Collections.<RefPair<T>>emptyList() : Collections.singleton( refPair );
+        }
+    }
+
+    private boolean isActive()
+    {
+        ServiceTracker<T, RefPair<T>> tracker = trackerRef.get();
+        return tracker != null && tracker.isActive();
+    }
 
     //---------- ServiceListener interface ------------------------------------
 
@@ -122,6 +652,7 @@
      * Called when a registered service changes state. In the case of service
      * modification the service is assumed to be removed and added again.
      */
+    /*
     public void serviceChanged( ServiceEvent event )
     {
         final ServiceReference<T> ref = ( ServiceReference<T> ) event.getServiceReference();
@@ -303,7 +834,7 @@
             }
         }
     }
-
+ *?
 
     /**
      * Called by the {@link #serviceChanged(ServiceEvent)} method if a new
@@ -318,6 +849,7 @@
      * @param reference The reference to the service newly registered or
      *      modified.
      */
+    /*
     private void serviceAdded( ServiceReference<T> reference )
     {
         // if the component is currently unsatisfied, it may become satisfied
@@ -431,7 +963,7 @@
         }
     }
 
-
+   *?
     /**
      * Called by the {@link #serviceChanged(ServiceEvent)} method if an existing
      * service is unregistered from the system or if a registered service has
@@ -444,6 +976,7 @@
      * @param reference The reference to the service unregistering or being
      *      modified.
      */
+    /*
     private void serviceRemoved( ServiceReference<T> reference )
     {
         // if the dependency is not satisfied anymore, we have to
@@ -555,7 +1088,7 @@
                     { m_componentManager.state() }, null );
         }
     }
-
+   */
 
     private boolean handleServiceEvent()
     {
@@ -633,13 +1166,11 @@
 
             m_componentManager.log( LogService.LOG_DEBUG,
                     "Registered for service events, currently {0} service(s) match the filter", new Object[]
-                    {new Integer( m_size.get() )}, null );
+                    {new Integer( size() )}, null );
         }
         else
         {
             // no services available
-            m_size.set( 0 );
-
             m_componentManager.log( LogService.LOG_DEBUG,
                     "Not registered for service events since the bundle has no permission to get service {0}", new Object[]
                     {m_dependencyMetadata.getInterface()}, null );
@@ -649,18 +1180,7 @@
 
     void deactivate()
     {
-        // unget all services we once got
-        if ( m_componentManager.getDependencyMap() != null )
-        {
-            ServiceReference<T>[] boundRefs = getBoundServiceReferences();
-            if ( boundRefs != null )
-            {
-                for ( ServiceReference<T> ref: boundRefs )
-                {
-                    ungetService( ref );
-                }
-            }
-        }
+        customizerRef.get().close();
     }
 
 
@@ -676,7 +1196,7 @@
      */
     int size()
     {
-        return m_size.get();
+        return trackerRef.get().getTracked( null ).size();
     }
 
 
@@ -837,18 +1357,18 @@
      */
     public ServiceReference<T>[] getBoundServiceReferences()
     {
-        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependencyMap = m_componentManager.getDependencyMap();
-        if ( dependencyMap == null )
-        {
-            return null;
-        }
-        Map<ServiceReference<T>, RefPair<T>> bound = (Map)dependencyMap.get( this );
+        Collection<RefPair<T>> bound = customizerRef.get().getRefs();
         if ( bound.isEmpty() )
         {
             return null;
         }
-
-        return bound.keySet().toArray( new ServiceReference[bound.size()] );
+        ServiceReference<T>[] result = new ServiceReference[bound.size()];
+        int i = 0;
+        for (RefPair<T> ref: bound)
+        {
+            result[i++] = ref.getRef();
+        }
+        return result;
     }
 
 
@@ -857,13 +1377,7 @@
      */
     private boolean isBound()
     {
-        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependencyMap = m_componentManager.getDependencyMap();
-        if (dependencyMap  == null )
-        {
-            return false;
-        }
-        Map<ServiceReference<T>, RefPair<T>> bound = (Map)dependencyMap.get( this );
-        return !bound.isEmpty();
+        return !customizerRef.get().getRefs().isEmpty();
     }
 
 
@@ -878,14 +1392,9 @@
      *      if the service is bound or <code>null</code> if the service is not
      *      bound.
      */
-    private RefPair getBoundService( ServiceReference<T> serviceReference )
+    private RefPair<T> getBoundService( ServiceReference<T> serviceReference )
     {
-        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependencyMap = m_componentManager.getDependencyMap();
-        if (dependencyMap == null)
-        {
-            return null;
-        }
-        return dependencyMap.get( this ).get( serviceReference );
+        return trackerRef.get().getTracked( null ).get( serviceReference );
     }
 
 
@@ -904,11 +1413,16 @@
     {
         // check whether we already have the service and return that one
         RefPair refPair = getBoundService( serviceReference );
-        if ( refPair != null && refPair.getServiceObject() != null )
+        if (refPair == null)
+        {
+            //we don't know about this reference
+            return null;
+        }
+        if ( refPair.getServiceObject() != null )
         {
             return (T)refPair.getServiceObject();
         }
-        T serviceObject = null;
+        T serviceObject;
         // otherwise acquire the service
         try
         {
@@ -928,16 +1442,7 @@
         // keep the service for later ungetting
         if ( serviceObject != null )
         {
-            if (refPair != null)
-            {
-                refPair.setServiceObject( serviceObject );
-            }
-            else
-            {
-                refPair = new RefPair( serviceReference );
-                refPair.setServiceObject( serviceObject );
-                m_componentManager.getDependencyMap().get( this ).put( serviceReference, refPair );
-            }
+            refPair.setServiceObject( serviceObject );
         }
 
         // return the acquired service (may be null of course)
@@ -949,38 +1454,38 @@
      * Ungets the service described by the ServiceReference and removes it from
      * the list of bound services.
      */
-    void ungetService( ServiceReference<T> serviceReference )
-    {
-        // check we really have this service, do nothing if not
-        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependencyMap = m_componentManager.getDependencyMap();
-        if ( dependencyMap != null )
-        {
-            RefPair refPair  = dependencyMap.get( this ).get( serviceReference );
-            if ( refPair != null && refPair.getServiceObject() != null )
-            {
-                BundleComponentActivator activator = m_componentManager.getActivator();
-                if ( activator != null )
-                {
-                    BundleContext bundleContext = activator.getBundleContext();
-                    if ( bundleContext != null )
-                    {
-                        try
-                        {
-                            bundleContext.ungetService( serviceReference );
-                        }
-                        catch ( IllegalStateException e )
-                        {
-                            m_componentManager.log( LogService.LOG_INFO,
-                                "For dependency {0}, trying to unget ServiceReference {1} on invalid bundle context {2}",
-                                new Object[]
-                                    { m_dependencyMetadata.getName(), serviceReference.getProperty( Constants.SERVICE_ID ),
-                                        serviceReference }, null );
-                        }
-                    }
-                }
-            }
-        }
-    }
+//    void ungetService( ServiceReference<T> serviceReference )
+//    {
+//        // check we really have this service, do nothing if not
+//        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependencyMap = m_componentManager.getDependencyMap();
+//        if ( dependencyMap != null )
+//        {
+//            RefPair refPair  = dependencyMap.get( this ).get( serviceReference );
+//            if ( refPair != null && refPair.getServiceObject() != null )
+//            {
+//                BundleComponentActivator activator = m_componentManager.getActivator();
+//                if ( activator != null )
+//                {
+//                    BundleContext bundleContext = activator.getBundleContext();
+//                    if ( bundleContext != null )
+//                    {
+//                        try
+//                        {
+//                            bundleContext.ungetService( serviceReference );
+//                        }
+//                        catch ( IllegalStateException e )
+//                        {
+//                            m_componentManager.log( LogService.LOG_INFO,
+//                                "For dependency {0}, trying to unget ServiceReference {1} on invalid bundle context {2}",
+//                                new Object[]
+//                                    { m_dependencyMetadata.getName(), serviceReference.getProperty( Constants.SERVICE_ID ),
+//                                        serviceReference }, null );
+//                        }
+//                    }
+//                }
+//            }
+//        }
+//    }
 
 
     //---------- DependencyManager core ---------------------------------------
@@ -1023,9 +1528,9 @@
     }
 
 
-    boolean open( S componentInstance, Map<ServiceReference<?>, RefPair<?>> parameters )
+    boolean open( S componentInstance )
     {
-        return bind( componentInstance, (Map)parameters);
+        return bind( componentInstance );
     }
 
 
@@ -1036,83 +1541,85 @@
      */
     void close( S componentInstance )
     {
-        unbind( componentInstance, getBoundServiceReferences() );
+        unbind( componentInstance );
     }
 
-    boolean prebind( Map<DependencyManager<S, T>, Map<ServiceReference<T>, RefPair<T>>> dependencyMap)
+    boolean prebind()
     {
-        // If no references were received, we have to check if the dependency
-        // is optional, if it is not then the dependency is invalid
-        if ( !isSatisfied() )
-        {
-            return false;
-        }
 
-        // if no bind method is configured or if this is a delayed component,
-        // we have nothing to do and just signal success
-        if ( m_dependencyMetadata.getBind() == null )
-        {
-            dependencyMap.put( this, new HashMap<ServiceReference<T>, RefPair<T>>( ) );
-            return true;
-        }
-
-        Map<ServiceReference<T>, RefPair<T>> result = new HashMap<ServiceReference<T>, RefPair<T>>();
-        // assume success to begin with: if the dependency is optional,
-        // we don't care, whether we can bind a service. Otherwise, we
-        // require at least one service to be bound, thus we require
-        // flag being set in the loop below
-        boolean success = m_dependencyMetadata.isOptional();
-
-        // Get service reference(s)
-        if ( m_dependencyMetadata.isMultiple() )
-        {
-            // bind all registered services
-            ServiceReference<T>[] refs = getFrameworkServiceReferences();
-            if ( refs != null )
-            {
-                for ( ServiceReference<T> ref : refs )
-                {
-                    RefPair refPair = new RefPair( ref );
-                    // success is if we have the minimal required number of services bound
-                    if ( m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext() ) )
-                    {
-                        result.put( ref, refPair );
-                        // of course, we have success if the service is bound
-                        success = true;
-                    }
-                    else
-                    {
-                        m_componentManager.getActivator().registerMissingDependency( this, ref );
-                    }
-                }
-            }
-        }
-        else
-        {
-            // bind best matching service
-            ServiceReference ref = getFrameworkServiceReference();
-            if ( ref != null )
-            {
-                RefPair refPair = new RefPair( ref );
-                // success is if we have the minimal required number of services bound
-                if ( m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext() ) )
-                {
-                    result.put( ref, refPair );
-                    // of course, we have success if the service is bound
-                    success = true;
-                }
-                else if ( isOptional() )
-                {
-                    m_componentManager.getActivator().registerMissingDependency( this, ref );
-                }
-            }
-        }
-
-        // success will be true, if the service is optional or if at least
-        // one service was available to be bound (regardless of whether the
-        // bind method succeeded or not)
-        dependencyMap.put( this, result );
-        return success;
+        return customizerRef.get().open();
+//        // If no references were received, we have to check if the dependency
+//        // is optional, if it is not then the dependency is invalid
+//        if ( !isSatisfied() )
+//        {
+//            return false;
+//        }
+//
+//        // if no bind method is configured or if this is a delayed component,
+//        // we have nothing to do and just signal success
+//        if ( m_dependencyMetadata.getBind() == null )
+//        {
+//            dependencyMap.put( this, new HashMap<ServiceReference<T>, RefPair<T>>( ) );
+//            return true;
+//        }
+//
+//        Map<ServiceReference<T>, RefPair<T>> result = new HashMap<ServiceReference<T>, RefPair<T>>();
+//        // assume success to begin with: if the dependency is optional,
+//        // we don't care, whether we can bind a service. Otherwise, we
+//        // require at least one service to be bound, thus we require
+//        // flag being set in the loop below
+//        boolean success = m_dependencyMetadata.isOptional();
+//
+//        // Get service reference(s)
+//        if ( m_dependencyMetadata.isMultiple() )
+//        {
+//            // bind all registered services
+//            ServiceReference<T>[] refs = getFrameworkServiceReferences();
+//            if ( refs != null )
+//            {
+//                for ( ServiceReference<T> ref : refs )
+//                {
+//                    RefPair refPair = new RefPair( ref );
+//                    // success is if we have the minimal required number of services bound
+//                    if ( m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext() ) )
+//                    {
+//                        result.put( ref, refPair );
+//                        // of course, we have success if the service is bound
+//                        success = true;
+//                    }
+//                    else
+//                    {
+//                        m_componentManager.getActivator().registerMissingDependency( this, ref );
+//                    }
+//                }
+//            }
+//        }
+//        else
+//        {
+//            // bind best matching service
+//            ServiceReference ref = getFrameworkServiceReference();
+//            if ( ref != null )
+//            {
+//                RefPair refPair = new RefPair( ref );
+//                // success is if we have the minimal required number of services bound
+//                if ( m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext() ) )
+//                {
+//                    result.put( ref, refPair );
+//                    // of course, we have success if the service is bound
+//                    success = true;
+//                }
+//                else if ( isOptional() )
+//                {
+//                    m_componentManager.getActivator().registerMissingDependency( this, ref );
+//                }
+//            }
+//        }
+//
+//        // success will be true, if the service is optional or if at least
+//        // one service was available to be bound (regardless of whether the
+//        // bind method succeeded or not)
+//        dependencyMap.put( this, result );
+//        return success;
     }
 
     /**
@@ -1122,7 +1629,7 @@
      * @return true if the dependency is satisfied and at least the minimum
      *      number of services could be bound. Otherwise false is returned.
      */
-    private boolean bind( S componentInstance, Map<ServiceReference<T>, RefPair<T>> parameters )
+    private boolean bind( S componentInstance )
     {
         // If no references were received, we have to check if the dependency
         // is optional, if it is not then the dependency is invalid
@@ -1147,16 +1654,17 @@
         // flag being set in the loop below
         boolean success = m_dependencyMetadata.isOptional();
 
+        Collection<RefPair<T>> refs = customizerRef.get().getRefs();
         m_componentManager.log( LogService.LOG_DEBUG,
             "For dependency {0}, optional: {1}; to bind: {2}",
-            new Object[]{ m_dependencyMetadata.getName(), success, parameters }, null );
-        for ( Map.Entry<ServiceReference<T>, RefPair<T>> entry : parameters.entrySet() )
+            new Object[]{ m_dependencyMetadata.getName(), success, refs }, null );
+        for ( RefPair<T> refPair : refs )
         {
-            if ( !invokeBindMethod( componentInstance, entry.getValue() ) )
+            if ( !invokeBindMethod( componentInstance, refPair ) )
             {
                 m_componentManager.log( LogService.LOG_DEBUG,
                         "For dependency {0}, failed to invoke bind method on object {1}",
-                        new Object[] {m_dependencyMetadata.getName(), entry.getValue()}, null );
+                        new Object[] {m_dependencyMetadata.getName(), refPair}, null );
 
             }
             success = true;
@@ -1168,18 +1676,18 @@
     /**
      * Handles an update in the service reference properties of a bound service.
      * <p>
-     * This just calls the {@link #invokeUpdatedMethod(Object, org.osgi.framework.ServiceReference)}
+     * This just calls the {@link #invokeUpdatedMethod(S, RefPair<T>)}
      * method if the method has been configured in the component metadata. If
      * the method is not configured, this method does nothing.
      *
      * @param componentInstance
-     * @param ref The <code>ServiceReference</code> representing the updated
+     * @param refPair The <code>ServiceReference</code> representing the updated
      */
-    void update( S componentInstance, final ServiceReference<T> ref )
+    void update( S componentInstance, final RefPair<T> refPair )
     {
         if ( m_dependencyMetadata.getUpdated() != null )
         {
-            invokeUpdatedMethod( componentInstance, ref );
+            invokeUpdatedMethod( componentInstance, refPair );
         }
     }
 
@@ -1188,15 +1696,13 @@
      * Revoke the given bindings. This method cannot throw an exception since
      * it must try to complete all that it can
      */
-    private void unbind( S componentInstance, ServiceReference<T>[] boundRefs )
+    private void unbind( S componentInstance )
     {
-        if ( boundRefs != null )
-        {
             // only invoke the unbind method if there is an instance (might be null
             // in the delayed component situation) and the unbind method is declared.
             boolean doUnbind = componentInstance != null && m_dependencyMetadata.getUnbind() != null;
 
-            for ( ServiceReference<T> boundRef : boundRefs )
+            for ( RefPair<T> boundRef : customizerRef.get().getRefs() )
             {
                 if ( doUnbind )
                 {
@@ -1207,40 +1713,39 @@
                 // bind method (or the locateService method might have been
                 // called) but there is no unbind method to actually unbind
                 // the service (see FELIX-832)
-                ungetService( boundRef );
+//                ungetService( boundRef );
             }
-        }
     }
 
-    boolean invokeBindMethod( S componentInstance, ServiceReference<T> ref )
-    {
-        //event driven, and we already checked this ref is not yet handled.
-        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependencyMap = m_componentManager.getDependencyMap();
-        if ( dependencyMap != null )
-        {
-            if ( m_bindMethods == null )
-            {
-                m_componentManager.log( LogService.LOG_ERROR,
-                        "For dependency {0}, bind method not set: component state {1}",
-                        new Object[]
-                                {m_dependencyMetadata.getName(), new Integer( m_componentManager.getState() )}, null );
-
-            }
-            Map<ServiceReference<T>, RefPair<T>> deps = (Map)dependencyMap.get( this );
-            RefPair<T> refPair = new RefPair<T>( ref );
-            if ( !m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext() ) )
-            {
-                //reference deactivated while we are processing.
-                return false;
-            }
-            synchronized ( deps )
-            {
-                deps.put( ref, refPair );
-            }
-            return invokeBindMethod( componentInstance, refPair );
-        }
-        return false;
-    }
+//    boolean invokeBindMethod( S componentInstance, ServiceReference<T> ref )
+//    {
+//        //event driven, and we already checked this ref is not yet handled.
+//        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependencyMap = m_componentManager.getDependencyMap();
+//        if ( dependencyMap != null )
+//        {
+//            if ( m_bindMethods == null )
+//            {
+//                m_componentManager.log( LogService.LOG_ERROR,
+//                        "For dependency {0}, bind method not set: component state {1}",
+//                        new Object[]
+//                                {m_dependencyMetadata.getName(), new Integer( m_componentManager.getState() )}, null );
+//
+//            }
+//            Map<ServiceReference<T>, RefPair<T>> deps = (Map)dependencyMap.get( this );
+//            RefPair<T> refPair = new RefPair<T>( ref );
+//            if ( !m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext() ) )
+//            {
+//                //reference deactivated while we are processing.
+//                return false;
+//            }
+//            synchronized ( deps )
+//            {
+//                deps.put( ref, refPair );
+//            }
+//            return invokeBindMethod( componentInstance, refPair );
+//        }
+//        return false;
+//    }
 
     public void invokeBindMethodLate( final ServiceReference<T> ref )
     {
@@ -1266,7 +1771,8 @@
             }
         }
         //TODO static and dynamic reluctant
-        m_componentManager.invokeBindMethod( this, ref );
+        RefPair<T> refPair = trackerRef.get().getService( ref );
+        m_componentManager.invokeBindMethod( this, refPair );
     }
 
     /**
@@ -1287,35 +1793,32 @@
      *      be handed over to the bind method but the service cannot be
      *      retrieved using the service reference.
      */
-    private boolean invokeBindMethod( S componentInstance, RefPair refPair )
+    boolean invokeBindMethod( S componentInstance, RefPair refPair )
     {
         // The bind method is only invoked if the implementation object is not
         // null. This is valid for both immediate and delayed components
-        if( componentInstance != null )
+        if ( componentInstance != null )
         {
-            if ( m_bindMethods != null )
+            MethodResult result = m_bindMethods.getBind().invoke( componentInstance, refPair, MethodResult.VOID );
+            if ( result == null )
             {
-                MethodResult result = m_bindMethods.getBind().invoke( componentInstance, refPair, MethodResult.VOID );
-                if ( result == null )
-                {
-                    return false;
-                }
-                m_componentManager.setServiceProperties( result );
-                return true;
+                return false;
             }
+            m_componentManager.setServiceProperties( result );
+            return true;
 
             // Concurrency Issue: The component instance still exists but
             // but the defined bind method field is null, fail binding
-            m_componentManager.log( LogService.LOG_INFO,
-                "DependencyManager : Component instance present, but DependencyManager shut down (no bind method)",
-                null );
-            return false;
+//            m_componentManager.log( LogService.LOG_INFO,
+//                    "DependencyManager : Component instance present, but DependencyManager shut down (no bind method)",
+//                    null );
+//            return false;
         }
         else
         {
             m_componentManager.log( LogService.LOG_DEBUG,
-                "DependencyManager : component not yet created, assuming bind method call succeeded",
-                null );
+                    "DependencyManager : component not yet created, assuming bind method call succeeded",
+                    null );
 
             return true;
         }
@@ -1326,15 +1829,14 @@
      * Calls the updated method.
      *
      * @param componentInstance
-     * @param ref A service reference corresponding to the service whose service
+     * @param refPair A service reference corresponding to the service whose service
      */
-    private void invokeUpdatedMethod( S componentInstance, final ServiceReference<T> ref )
+    private void invokeUpdatedMethod( S componentInstance, final RefPair<T> refPair )
     {
         // The updated method is only invoked if the implementation object is not
         // null. This is valid for both immediate and delayed components
         if ( componentInstance != null )
         {
-            RefPair refPair = m_componentManager.getDependencyMap().get( this ).get( ref );
             if (refPair == null)
             {
 
@@ -1347,7 +1849,7 @@
             {
                 m_componentManager.log( LogService.LOG_WARNING,
                         "DependencyManager : invokeUpdatedMethod : Service not available from service registry for ServiceReference {0} for reference {1}",
-                        new Object[] {ref, getName()}, null );
+                        new Object[] {refPair.getRef(), getName()}, null );
                 return;
 
             }
@@ -1376,15 +1878,14 @@
      * <code>true</code>.
      *
      * @param componentInstance
-     * @param ref A service reference corresponding to the service that will be
+     * @param refPair A service reference corresponding to the service that will be
      */
-    void invokeUnbindMethod( S componentInstance, final ServiceReference<T> ref )
+    void invokeUnbindMethod( S componentInstance, final RefPair<T> refPair )
     {
         // The unbind method is only invoked if the implementation object is not
         // null. This is valid for both immediate and delayed components
         if ( componentInstance != null )
         {
-            RefPair refPair = m_componentManager.getDependencyMap().get( this ).get( ref );
             if (refPair == null)
             {
                 //TODO should this be possible? If so, reduce or eliminate logging
@@ -1396,7 +1897,7 @@
             {
                 m_componentManager.log( LogService.LOG_WARNING,
                         "DependencyManager : invokeUnbindMethod : Service not available from service registry for ServiceReference {0} for reference {1}",
-                        new Object[] {ref, getName()}, null );
+                        new Object[] {refPair.getRef(), getName()}, null );
                 return;
 
             }
@@ -1536,141 +2037,188 @@
             }
         }
         m_target = target;
+        String filterString = "(" + Constants.OBJECTCLASS + "=" + m_dependencyMetadata.getInterface() + ")";
+        if (m_target != null)
+        {
+            filterString = "(&" + filterString + m_target + ")";
+        }
 
         if ( registered )
         {
             unregisterServiceListener();
         }
-        //compute the new target filter while we wait for other threads to complete.
-        if ( target != null )
+        m_componentManager.log( LogService.LOG_DEBUG, "Setting target property for dependency {0} to {1}", new Object[]
+                {m_dependencyMetadata.getName(), target}, null );
+        try
         {
-            m_componentManager.log( LogService.LOG_DEBUG, "Setting target property for dependency {0} to {1}", new Object[]
-                    {m_dependencyMetadata.getName(), target}, null );
-            try
-            {
-                m_targetFilter = m_componentManager.getActivator().getBundleContext().createFilter( target );
-            }
-            catch ( InvalidSyntaxException ise )
-            {
-                m_componentManager.log( LogService.LOG_ERROR, "Invalid syntax in target property for dependency {0} to {1}", new Object[]
-                        {m_dependencyMetadata.getName(), target}, null );
-                // log
-                m_targetFilter = null;
-            }
+            m_targetFilter = m_componentManager.getActivator().getBundleContext().createFilter( filterString );
         }
-        else
+        catch ( InvalidSyntaxException ise )
         {
-            m_componentManager.log( LogService.LOG_DEBUG, "Clearing target property for dependency {0}", new Object[]
-                    {m_dependencyMetadata.getName()}, null );
+            m_componentManager.log( LogService.LOG_ERROR, "Invalid syntax in target property for dependency {0} to {1}", new Object[]
+                    {m_dependencyMetadata.getName(), target}, null );
+            // TODO this is an error, how do we recover?
             m_targetFilter = null;
         }
-        //wait for events to finish processing
-        synchronized ( added )
-        {
-            while ( !added.isEmpty() )
-            {
-                try
-                {
-                    added.wait();
-                }
-                catch ( InterruptedException e )
-                {
-                    //??
-                }
-            }
-        }
-        synchronized ( removed )
-        {
-            while ( !removed.isEmpty() )
-            {
-                try
-                {
-                    removed.wait();
-                }
-                catch ( InterruptedException e )
-                {
-                    //??
-                }
-            }
-        }
 
-        //we are now done processing all the events received before we removed the listener.
-        ServiceReference[] boundRefs = getBoundServiceReferences();
-        if ( boundRefs != null && m_targetFilter != null )
-        {
-            for ( ServiceReference boundRef : boundRefs )
-            {
-                if ( !m_targetFilter.match( boundRef ) )
-                {
-                    serviceRemoved( boundRef );
-                }
-            }
-        }
-        boolean active = m_componentManager.getDependencyMap() != null;
-        // register the service listener
         registerServiceListener();
-        Collection<ServiceReference> toAdd = new ArrayList<ServiceReference>();
 
-        synchronized ( enableLock )
-        {
-            // get the current number of registered services available
-            ServiceReference[] refArray = getFrameworkServiceReferences();
-            if ( refArray != null )
-            {
-                List<ServiceReference> refs = Arrays.asList( refArray );
-                m_componentManager.log( LogService.LOG_DEBUG, "Component: {0} dependency: {1} refs: {2}", new Object[]
-                        {m_componentManager.getName(), getName(), refs}, null );
-                synchronized ( added )
-                {
-                    m_componentManager.log( LogService.LOG_DEBUG, "Component: {0} dependency: {1} added: {2}", new Object[]
-                            {m_componentManager.getName(), getName(), added}, null );
-                    added.removeAll( refs );
-                }
-                synchronized ( removed )
-                {
-                    m_componentManager.log( LogService.LOG_DEBUG, "Component: {0} dependency: {1} removed: {2}", new Object[]
-                            {m_componentManager.getName(), getName(), removed}, null );
-                    removed.retainAll( refs );
-                }
-                if ( active )
-                {
-                    for ( ServiceReference ref : refs )
-                    {
-                        if ( getBoundService( ref ) == null )
-                        {
-                            toAdd.add( ref );
-                        }
-                    }
-                }
-            }
-            else
-            {
-                m_componentManager.log( LogService.LOG_DEBUG, "Component: {0} dependency: {1} no services", new Object[]
-                        {m_componentManager.getName(), getName()}, null );
-                removed.clear();//retainAll of empty set.
-            }
-            m_size.set( ( refArray == null ) ? 0 : refArray.length );
-        }
+        //TODO deal with changes in what matches filter.
 
-        for ( ServiceReference ref : toAdd )
-        {
-            serviceAdded( ref );
-        }
+
+//
+//        //wait for events to finish processing
+//        synchronized ( added )
+//        {
+//            while ( !added.isEmpty() )
+//            {
+//                try
+//                {
+//                    added.wait();
+//                }
+//                catch ( InterruptedException e )
+//                {
+//                    //??
+//                }
+//            }
+//        }
+//        synchronized ( removed )
+//        {
+//            while ( !removed.isEmpty() )
+//            {
+//                try
+//                {
+//                    removed.wait();
+//                }
+//                catch ( InterruptedException e )
+//                {
+//                    //??
+//                }
+//            }
+//        }
+//
+//        //we are now done processing all the events received before we removed the listener.
+//        ServiceReference[] boundRefs = getBoundServiceReferences();
+//        if ( boundRefs != null && m_targetFilter != null )
+//        {
+//            for ( ServiceReference boundRef : boundRefs )
+//            {
+//                if ( !m_targetFilter.match( boundRef ) )
+//                {
+//                    serviceRemoved( boundRef );
+//                }
+//            }
+//        }
+//        boolean active = m_componentManager.getDependencyMap() != null;
+//        // register the service listener
+//        registerServiceListener();
+//        Collection<ServiceReference> toAdd = new ArrayList<ServiceReference>();
+//
+//        synchronized ( enableLock )
+//        {
+//            // get the current number of registered services available
+//            ServiceReference[] refArray = getFrameworkServiceReferences();
+//            if ( refArray != null )
+//            {
+//                List<ServiceReference> refs = Arrays.asList( refArray );
+//                m_componentManager.log( LogService.LOG_DEBUG, "Component: {0} dependency: {1} refs: {2}", new Object[]
+//                        {m_componentManager.getName(), getName(), refs}, null );
+//                synchronized ( added )
+//                {
+//                    m_componentManager.log( LogService.LOG_DEBUG, "Component: {0} dependency: {1} added: {2}", new Object[]
+//                            {m_componentManager.getName(), getName(), added}, null );
+//                    added.removeAll( refs );
+//                }
+//                synchronized ( removed )
+//                {
+//                    m_componentManager.log( LogService.LOG_DEBUG, "Component: {0} dependency: {1} removed: {2}", new Object[]
+//                            {m_componentManager.getName(), getName(), removed}, null );
+//                    removed.retainAll( refs );
+//                }
+//                if ( active )
+//                {
+//                    for ( ServiceReference ref : refs )
+//                    {
+//                        if ( getBoundService( ref ) == null )
+//                        {
+//                            toAdd.add( ref );
+//                        }
+//                    }
+//                }
+//            }
+//            else
+//            {
+//                m_componentManager.log( LogService.LOG_DEBUG, "Component: {0} dependency: {1} no services", new Object[]
+//                        {m_componentManager.getName(), getName()}, null );
+//                removed.clear();//retainAll of empty set.
+//            }
+//            m_size.set( ( refArray == null ) ? 0 : refArray.length );
+//        }
+//
+//        for ( ServiceReference ref : toAdd )
+//        {
+//            serviceAdded( ref );
+//        }
 
     }
 
     private void registerServiceListener() throws InvalidSyntaxException
     {
-        String filterString = "(" + Constants.OBJECTCLASS + "=" + m_dependencyMetadata.getInterface() + ")";
-        m_componentManager.getActivator().getBundleContext().addServiceListener( this, filterString );
+        Customizer<T> customizer = newCustomizer();
+        ServiceTracker<T, RefPair<T>> tracker = new ServiceTracker<T, RefPair<T>>( m_componentManager.getActivator().getBundleContext(), m_targetFilter, customizer );
+        customizer.setTracker( tracker );
+        tracker.open();
+        trackerRef.set( tracker );
         registered = true;
         m_componentManager.log( LogService.LOG_DEBUG, "registering service listener for dependency {0}", new Object[]
                 {m_dependencyMetadata.getName()}, null );
     }
 
+    private Customizer<T> newCustomizer()
+    {
+        Customizer<T> customizer;
+        if (m_componentManager.isFactory())
+        {
+            customizer = new FactoryCustomizer();
+        }
+        else if ( isMultiple() )
+        {
+            if ( isStatic() )
+            {
+                if ( isReluctant() )
+                {
+                    customizer = new MultipleStaticReluctantCustomizer();
+                }
+                else
+                {
+                    customizer = new MultipleStaticGreedyCustomizer();
+                }
+            }
+            else
+            {
+                customizer = new MultipleDynamicCustomizer();
+            }
+        }
+        else
+        {
+            if ( isStatic() )
+            {
+                customizer = new SingleStaticCustomizer();
+            }
+            else
+            {
+                customizer = new SingleDynamicCustomizer();
+            }
+        }
+        customizerRef.set( customizer );
+        return customizer;
+    }
+
     void unregisterServiceListener()
     {
-        m_componentManager.getActivator().getBundleContext().removeServiceListener( this );
+        ServiceTracker<T, RefPair<T>> tracker = trackerRef.get();
+        trackerRef.set( null ); //???
+        tracker.close();
         registered = false;
         m_componentManager.log( LogService.LOG_DEBUG, "unregistering service listener for dependency {0}", new Object[]
                 {m_dependencyMetadata.getName()}, null );
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
index 4e6de52..9748f0d 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
@@ -21,8 +21,6 @@
 
 import java.util.Dictionary;
 import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.felix.scr.impl.BundleComponentActivator;
@@ -263,19 +261,13 @@
         setter.presetImplementationObject( implementationObject );
 
         // 4. Bind the target services
-        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> parameters = getDependencyMap();
 
         for ( DependencyManager<S, ?> dm: getDependencyManagers())
         {
             // if a dependency turned unresolved since the validation check,
             // creating the instance fails here, so we deactivate and return
             // null.
-            Map<ServiceReference<?>, RefPair<?>> params = parameters.get( dm );
-            boolean open;
-            synchronized ( params )
-            {
-                open = dm.open( implementationObject, params );
-            }
+            boolean open = dm.open( implementationObject );
             if ( !open )
             {
                 log( LogService.LOG_ERROR, "Cannot create component instance due to failure to bind reference {0}",
@@ -354,22 +346,22 @@
         return Active.getInstance();
     }
 
-    <T> void update( DependencyManager<S, T> dependencyManager, ServiceReference<T> ref )
+    <T> void update( DependencyManager<S, T> dependencyManager, RefPair<T> refPair )
     {
         final S impl = ( m_tmpImplementationObject != null ) ? m_tmpImplementationObject : m_implementationObject;
-        dependencyManager.update( impl, ref );
+        dependencyManager.update( impl, refPair );
     }
 
-    <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, ServiceReference<T> reference )
+    <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair )
     {
         final S impl = ( m_tmpImplementationObject != null ) ? m_tmpImplementationObject : m_implementationObject;
-        dependencyManager.invokeBindMethod( impl, reference);
+        dependencyManager.invokeBindMethod( impl, refPair);
     }
 
-    <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, ServiceReference<T> oldRef )
+    <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> oldRefPair )
     {
         final S impl = ( m_tmpImplementationObject != null ) ? m_tmpImplementationObject : m_implementationObject;
-        dependencyManager.invokeUnbindMethod( impl, oldRef);
+        dependencyManager.invokeUnbindMethod( impl, oldRefPair);
     }
 
     protected void setFactoryProperties( Dictionary<String, Object> dictionary )
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
index 06a60fd..49633d4 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
@@ -208,35 +208,35 @@
         }
     }
 
-    <T> void update( DependencyManager<S, T> dependencyManager, ServiceReference<T> ref )
+    <T> void update( DependencyManager<S, T> dependencyManager, RefPair<T> refPair )
     {
         for ( S implementationObject : serviceContexts.keySet() )
         {
-            dependencyManager.update( implementationObject, ref );
+            dependencyManager.update( implementationObject, refPair );
         }
     }
 
-    <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, ServiceReference<T> reference )
+    <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair )
     {
         for ( S implementationObject : serviceContexts.keySet() )
         {
-            dependencyManager.invokeBindMethod( implementationObject, reference );
+            dependencyManager.invokeBindMethod( implementationObject, refPair );
         }
         for ( S implementationObject : tmpImplementationObjects.keySet() )
         {
-            dependencyManager.invokeBindMethod( implementationObject, reference );
+            dependencyManager.invokeBindMethod( implementationObject, refPair );
         }
     }
 
-    <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, ServiceReference<T> oldRef )
+    <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> oldRefPair )
     {
         for ( S implementationObject : serviceContexts.keySet() )
         {
-            dependencyManager.invokeUnbindMethod( implementationObject, oldRef );
+            dependencyManager.invokeUnbindMethod( implementationObject, oldRefPair );
         }
         for ( S implementationObject : tmpImplementationObjects.keySet() )
         {
-            dependencyManager.invokeUnbindMethod( implementationObject, oldRef );
+            dependencyManager.invokeUnbindMethod( implementationObject, oldRefPair );
         }
     }
 
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java
index 6de70df..178f2c5 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java
@@ -65,6 +65,8 @@
  *
  * - included AbstractTracked as an inner class.
  * - addedService method on customizer called after the object is tracked.
+ * - we always track all matching services.
+ *
  * @param <S>
  * @param <T>
  */
@@ -108,6 +110,12 @@
 	 */
 	private volatile Tracked				tracked;
 
+
+    /**
+     * whether the DependencyManager is getting the service immediately.
+     */
+    private boolean active;
+
 	/**
 	 * Accessor method for the current Tracked object. This method is only
 	 * intended to be used by the unsynchronized methods which do not modify the
@@ -789,18 +797,33 @@
 	 *         {@code ServiceTracker}. If no services are being tracked, then
 	 *         the returned map is empty.
 	 * @since 1.5
+     * @param activate
 	 */
-	public SortedMap<ServiceReference<S>, T> getTracked() {
+	public SortedMap<ServiceReference<S>, T> getTracked( Boolean activate ) {
 		SortedMap<ServiceReference<S>, T> map = new TreeMap<ServiceReference<S>, T>(Collections.reverseOrder());
 		final Tracked t = tracked();
 		if (t == null) { /* if ServiceTracker is not open */
 			return map;
 		}
 		synchronized (t) {
-			return t.copyEntries(map);
+            if ( activate != null )
+            {
+                active = activate;
+            }
+            return t.copyEntries(map);
 		}
 	}
 
+    void deactivate() {
+        final Tracked t = tracked();
+        if (t == null) { /* if ServiceTracker is not open */
+            return;
+        }
+        synchronized (t) {
+                active = false;
+        }
+    }
+
 	/**
 	 * Return if this {@code ServiceTracker} is empty.
 	 * 
@@ -818,6 +841,17 @@
 		}
 	}
 
+    public boolean isActive() {
+        final Tracked t = tracked();
+        if (t == null) { /* if ServiceTracker is not open */
+            return false;
+        }
+        synchronized (t) {
+            return active;
+        }
+
+    }
+
 	/**
 	 * Return an array of service objects for all services being tracked by this
 	 * {@code ServiceTracker}. The runtime type of the returned array is that of
@@ -1049,13 +1083,15 @@
          * @param related Action related object.
          */
         void track(final S item, final R related) {
+            boolean tracking;
             final T object;
             synchronized (this) {
                 if (closed) {
                     return;
                 }
+                tracking = tracked.containsKey( item );
                 object = tracked.get(item);
-                if (object == null) { /* we are not tracking the item */
+                if (!tracking) { /* we are not tracking the item */
                     if (adding.contains(item)) {
                         /* if this item is already in the process of being added. */
                         if (DEBUG) {
@@ -1072,7 +1108,7 @@
                 }
             }
 
-            if (object == null) { /* we are not tracking the item */
+            if (!tracking) { /* we are not tracking the item */
                 trackAdding(item, related);
             } else {
                 /* Call customizer outside of synchronized region */
@@ -1112,11 +1148,9 @@
                          * if the item was not untracked during the customizer
                          * callback
                          */
-                        if (object != null) {
-                            tracked.put(item, object);
-                            modified(); /* increment modification count */
-                            notifyAll(); /* notify any waiters */
-                        }
+                        tracked.put( item, object );
+                        modified(); /* increment modification count */
+                        notifyAll(); /* notify any waiters */
                     } else {
                         becameUntracked = true;
                     }
@@ -1125,7 +1159,7 @@
             /*
              * The item became untracked during the customizer callback.
              */
-            if (becameUntracked && (object != null)) {
+            if (becameUntracked) {
                 if (DEBUG) {
                     System.out.println("AbstractTracked.trackAdding[removed]: " + item); //$NON-NLS-1$
                 }
@@ -1178,9 +1212,6 @@
                                                  * must remove from tracker before
                                                  * calling customizer callback
                                                  */
-                if (object == null) { /* are we actually tracking the item */
-                    return;
-                }
                 modified(); /* increment modification count */
             }
             if (DEBUG) {