FELIX-4505 Implement prototype scope for references, using ComponentContextImpl as object key in RefPairs. LocateService now uses appropriate strategy. New event method signatures not yet implemented.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1615440 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
index 6687a61..77bc2fa 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
@@ -22,11 +22,10 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
-import org.osgi.service.component.ComponentContext;
 import org.osgi.service.log.LogService;
 
 
-public class ActivateMethod extends BaseMethod
+public class ActivateMethod extends BaseMethod<ActivatorParameter>
 {
 
     private static final Class[] ACTIVATE_TYPES_DS11 =
@@ -107,7 +106,7 @@
     }
 
 
-    protected Object[] getParameters( Method method, Object rawParameter )
+    protected Object[] getParameters( Method method, ActivatorParameter rawParameter )
     {
         final Class[] parameterTypes = method.getParameterTypes();
         final ActivatorParameter ap = ( ActivatorParameter ) rawParameter;
@@ -142,7 +141,7 @@
         return "activate";
     }
 
-    public MethodResult invoke( Object componentInstance, Object rawParameter, final MethodResult methodCallFailureResult, SimpleLogger logger )
+    public MethodResult invoke( Object componentInstance, ActivatorParameter rawParameter, final MethodResult methodCallFailureResult, SimpleLogger logger )
     {
         if (methodExists( logger ))
         {
@@ -246,29 +245,4 @@
         return isDS11();
     }
 
-    //---------- Helper class for method call parameters
-
-    public static final class ActivatorParameter
-    {
-        private final ComponentContext m_componentContext;
-        private final int m_reason;
-
-        public ActivatorParameter( ComponentContext componentContext, int reason )
-        {
-            this.m_componentContext = componentContext;
-            this.m_reason = reason;
-        }
-
-
-        public ComponentContext getComponentContext()
-        {
-            return m_componentContext;
-        }
-
-
-        public int getReason()
-        {
-            return m_reason;
-        }
-    }
 }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivatorParameter.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivatorParameter.java
new file mode 100644
index 0000000..f4f32a4
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivatorParameter.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scr.impl.helper;
+
+import org.osgi.service.component.ComponentContext;
+
+public final class ActivatorParameter
+{
+    private final ComponentContext m_componentContext;
+    private final int m_reason;
+
+    public ActivatorParameter( ComponentContext componentContext, int reason )
+    {
+        this.m_componentContext = componentContext;
+        this.m_reason = reason;
+    }
+
+
+    public ComponentContext getComponentContext()
+    {
+        return m_componentContext;
+    }
+
+
+    public int getReason()
+    {
+        return m_reason;
+    }
+}
\ No newline at end of file
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
index 43f72a4..a3b2565 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
@@ -36,7 +36,7 @@
 /**
  * Component method to be invoked on service (un)binding.
  */
-abstract class BaseMethod
+abstract class BaseMethod<P>
 {
 
     // class references to simplify parameter checking
@@ -218,7 +218,7 @@
             final boolean acceptPackage, SimpleLogger logger ) throws SuitableMethodNotAccessibleException, InvocationTargetException;
 
 
-    private MethodResult invokeMethod( final Object componentInstance, final Object rawParameter, SimpleLogger logger )
+    private MethodResult invokeMethod( final Object componentInstance, final P rawParameter, SimpleLogger logger )
         throws InvocationTargetException
     {
         try
@@ -281,7 +281,7 @@
      * @throws IllegalStateException If the required parameters cannot be
      *      extracted from the <code>rawParameter</code>
      */
-    protected abstract Object[] getParameters( Method method, Object rawParameter );
+    protected abstract Object[] getParameters( Method method, P rawParameter );
 
 
     protected String getMethodNamePrefix()
@@ -500,7 +500,7 @@
      *      <code>methodCallFailureResult</code> is returned if the method was
      *      found and called, but the method threw an exception.
      */
-    public MethodResult invoke( final Object componentInstance, final Object rawParameter,
+    public MethodResult invoke( final Object componentInstance, final P rawParameter,
             final MethodResult methodCallFailureResult, SimpleLogger logger )
     {
         try
@@ -525,11 +525,11 @@
     private static interface State
     {
 
-        MethodResult invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter, SimpleLogger logger )
+        <P> MethodResult invoke( final BaseMethod<P> baseMethod, final Object componentInstance, final P rawParameter, SimpleLogger logger )
             throws InvocationTargetException;
 
 
-        boolean methodExists( final BaseMethod baseMethod, SimpleLogger logger );
+        <P> boolean methodExists( final BaseMethod<P> baseMethod, SimpleLogger logger );
     }
 
     private static class NotApplicable implements State
@@ -538,13 +538,13 @@
         private static final State INSTANCE = new NotApplicable();
 
 
-        public MethodResult invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter, SimpleLogger logger )
+        public <P> MethodResult invoke( final BaseMethod<P> baseMethod, final Object componentInstance, final P rawParameter, SimpleLogger logger )
         {
             return MethodResult.VOID;
         }
 
 
-        public boolean methodExists( final BaseMethod baseMethod, SimpleLogger logger )
+        public <P> boolean methodExists( final BaseMethod<P> baseMethod, SimpleLogger logger )
         {
             return true;
         }
@@ -555,7 +555,7 @@
         private static final State INSTANCE = new NotResolved();
 
 
-        private synchronized void resolve( final BaseMethod baseMethod, SimpleLogger logger )
+        private synchronized <P> void resolve( final BaseMethod<P> baseMethod, SimpleLogger logger )
         {
             logger.log( LogService.LOG_DEBUG, "getting {0}: {1}", new Object[]
                     {baseMethod.getMethodNamePrefix(), baseMethod.getMethodName()}, null );
@@ -576,7 +576,7 @@
         }
 
 
-        public MethodResult invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter, SimpleLogger logger )
+        public <P> MethodResult invoke( final BaseMethod<P> baseMethod, final Object componentInstance, final P rawParameter, SimpleLogger logger )
             throws InvocationTargetException
         {
             resolve( baseMethod, logger );
@@ -584,7 +584,7 @@
         }
 
 
-        public boolean methodExists( final BaseMethod baseMethod, SimpleLogger logger )
+        public <P> boolean methodExists( final BaseMethod<P> baseMethod, SimpleLogger logger )
         {
             resolve( baseMethod, logger );
             return baseMethod.getState().methodExists( baseMethod, logger );
@@ -596,7 +596,7 @@
         private static final State INSTANCE = new NotFound();
 
 
-        public MethodResult invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter, SimpleLogger logger )
+        public <P> MethodResult invoke( final BaseMethod<P> baseMethod, final Object componentInstance, final P rawParameter, SimpleLogger logger )
         {
             // 112.3.1 If the method is not found , SCR must log an error
             // message with the log service, if present, and ignore the
@@ -607,7 +607,7 @@
         }
 
 
-        public boolean methodExists( final BaseMethod baseMethod, SimpleLogger logger )
+        public <P> boolean methodExists( final BaseMethod<P> baseMethod, SimpleLogger logger )
         {
             return false;
         }
@@ -618,14 +618,14 @@
         private static final State INSTANCE = new Resolved();
 
 
-        public MethodResult invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter, SimpleLogger logger )
+        public <P> MethodResult invoke( final BaseMethod<P> baseMethod, final Object componentInstance, final P rawParameter, SimpleLogger logger )
             throws InvocationTargetException
         {
             return baseMethod.invokeMethod( componentInstance, rawParameter, logger );
         }
 
 
-        public boolean methodExists( final BaseMethod baseMethod, SimpleLogger logger )
+        public <P> boolean methodExists( final BaseMethod<P> baseMethod, SimpleLogger logger )
         {
             return true;
         }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
index c799db6..cb2de3c 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
@@ -23,6 +23,7 @@
 import java.lang.reflect.Method;
 
 import org.apache.felix.scr.impl.Activator;
+import org.apache.felix.scr.impl.manager.ComponentContextImpl;
 import org.apache.felix.scr.impl.manager.RefPair;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
@@ -34,7 +35,7 @@
 /**
  * Component method to be invoked on service (un)binding.
  */
-public class BindMethod extends BaseMethod
+public class BindMethod extends BaseMethod<BindParameters>
 {
 
     private static final Class<?> OBJECT_CLASS = Object.class;
@@ -563,46 +564,33 @@
         return null;
     }
 
-    public <T> boolean getServiceObject( RefPair<T> refPair, BundleContext context, SimpleLogger logger )
+    public <S, T> boolean getServiceObject( ComponentContextImpl<S> key, RefPair<S, T> refPair, BundleContext context, SimpleLogger logger )
     {
         //??? this resolves which we need.... better way?
-        if ( refPair.getServiceObject() == null && methodExists( logger ) )
+        if ( refPair.getServiceObject(key) == null && methodExists( logger ) )
         {
             if (m_paramStyle == SERVICE_OBJECT || m_paramStyle == SERVICE_OBJECT_AND_MAP) {
-                T service = context.getService( refPair.getRef() );
-                if ( service == null )
-                {
-                    refPair.setFailed();
-                    logger.log(
-                         LogService.LOG_WARNING,
-                         "Could not get service from ref {0}", new Object[] {refPair.getRef()}, null );
-                    return false;
-                }
-                if (!refPair.setServiceObject(service))
-                {
-                    // Another thread got the service before, so unget our
-                    context.ungetService( refPair.getRef() );
-                }
-                return true;
+                return refPair.getServiceObject(key, context, logger);
             }
         }
         return true;
     }
 
-    protected Object[] getParameters( Method method, Object rawParameter )
+    protected Object[] getParameters( Method method, BindParameters bp )
     {
-        RefPair<?> refPair = ( RefPair<?> ) rawParameter;
+        ComponentContextImpl key = bp.getComponentContext();
+        RefPair<?, ?> refPair = bp.getRefPair();
         if (m_paramStyle == SERVICE_REFERENCE )
         {
             return new Object[] {refPair.getRef()};
         }
         if (m_paramStyle == SERVICE_OBJECT)
         {
-            return new Object[] {refPair.getServiceObject()};
+            return new Object[] {refPair.getServiceObject(key)};
         }
         if (m_paramStyle == SERVICE_OBJECT_AND_MAP  )
         {
-            return new Object[] {refPair.getServiceObject(), new ReadOnlyDictionary<String, Object>( refPair.getRef() )};
+            return new Object[] {refPair.getServiceObject(key), new ReadOnlyDictionary<String, Object>( refPair.getRef() )};
         }
         throw new IllegalStateException( "Unexpected m_paramStyle of " + m_paramStyle );
     }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/BindParameters.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/BindParameters.java
new file mode 100644
index 0000000..fc9185a
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/BindParameters.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.scr.impl.helper;
+
+import org.apache.felix.scr.impl.manager.ComponentContextImpl;
+import org.apache.felix.scr.impl.manager.RefPair;
+
+public class BindParameters
+{
+    
+    private final ComponentContextImpl<?> componentContext;
+    private final RefPair<?, ?> refPair;
+    public BindParameters(ComponentContextImpl<?> componentContext, RefPair<?, ?> refPair)
+    {
+        this.componentContext = componentContext;
+        this.refPair = refPair;
+    }
+    
+    public ComponentContextImpl<?> getComponentContext()
+    {
+        return componentContext;
+    }
+    
+    public RefPair<?, ?> getRefPair()
+    {
+        return refPair;
+    }
+    
+}
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 57414ae..6419b3f 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
@@ -96,8 +96,6 @@
 
     private volatile boolean m_dependencyManagersInitialized;
 
-    private volatile boolean m_dependenciesCollected;
-
     private final AtomicInteger m_trackingCount = new AtomicInteger( );
 
     // The ServiceRegistration is now tracked in the RegistrationManager
@@ -783,7 +781,6 @@
                 {
                     disableDependencyManagers();
                 }
-                unsetDependenciesCollected();
             }
             finally
             {
@@ -968,47 +965,34 @@
 
     /**
      * Collect and store in m_dependencies_map all the services for dependencies, outside of any locks.
-     * Throwing IllegalStateException on failure to collect all the dependencies is needed so getService can
-     * know to return null.
+     * @param componentContext possible instance key for prototype scope references
      *
-     * @return true if this thread collected the dependencies;
-     *   false if some other thread successfully collected the dependencies;
-     * @throws IllegalStateException if some dependency is no longer available.
+     * @return true if all references can be collected,
+     *   false if some dependency is no longer available.
      */
-    protected boolean collectDependencies() throws IllegalStateException
+    protected boolean collectDependencies(ComponentContextImpl<S> componentContext)
     {
-        if ( m_dependenciesCollected)
-        {
-            log( LogService.LOG_DEBUG, "dependencies already collected, do not collect dependencies", null );
-            return false;
-        }
         initDependencyManagers();
         for ( DependencyManager<S, ?> dependencyManager : m_dependencyManagers )
         {
-            if ( !dependencyManager.prebind() )
+            if ( !dependencyManager.prebind(componentContext) )
             {
                 //not actually satisfied any longer
                 deactivateDependencyManagers();
                 log( LogService.LOG_DEBUG, "Could not get required dependency for dependency manager: {0}",
                         new Object[] {dependencyManager.getName()}, null );
-                throw new IllegalStateException( "Missing dependencies, not satisfied" );
+                return false;
             }
         }
-        m_dependenciesCollected = true;
         log( LogService.LOG_DEBUG, "This thread collected dependencies", null );
         return true;
     }
 
-    protected void unsetDependenciesCollected()
-    {
-        m_dependenciesCollected = false;
-    }
+    abstract <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> refPair, int trackingCount );
 
-    abstract <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount );
+    abstract <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> refPair, int trackingCount );
 
-    abstract <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount );
-
-    abstract <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> oldRefPair, int trackingCount );
+    abstract <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> oldRefPair, int trackingCount );
 
     //**********************************************************************************************************
     public BundleComponentActivator getActivator()
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
index 459c854..0c49101 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
@@ -47,17 +47,16 @@
     
     private final Bundle m_usingBundle;
     
-    private final S m_implementationObject;
+    private S m_implementationObject;
     
     private volatile boolean m_implementationAccessible;
     
     private final CountDownLatch accessibleLatch = new CountDownLatch(1);
 
-    ComponentContextImpl( SingleComponentManager<S> componentManager, Bundle usingBundle, S implementationObject )
+    public ComponentContextImpl( SingleComponentManager<S> componentManager, Bundle usingBundle )
     {
         m_componentManager = componentManager;
         m_usingBundle = usingBundle;
-        m_implementationObject = implementationObject;
         edgeInfos = new EdgeInfo[componentManager.getComponentMetadata().getDependencies().size()];
         for (int i = 0; i< edgeInfos.length; i++)
         {
@@ -65,6 +64,13 @@
         }
     }
     
+    
+    public void setImplementationObject(S implementationObject)
+    {
+        this.m_implementationObject = implementationObject;
+    }
+
+
     void setImplementationAccessible(boolean implementationAccessible)
     {
         this.m_implementationAccessible = implementationAccessible;
@@ -98,7 +104,7 @@
         try
         {
             DependencyManager<S, ?> dm = m_componentManager.getDependencyManager( name );
-            return ( dm != null ) ? dm.getService() : null;
+            return ( dm != null ) ? dm.getService(this) : null;
         }
         finally
         {
@@ -113,7 +119,7 @@
         try
         {
             DependencyManager<S, ?> dm = m_componentManager.getDependencyManager( name );
-            return ( dm != null ) ? dm.getService( ref ) : null;
+            return ( dm != null ) ? dm.getService( this, ref ) : null;
         }
         finally
         {
@@ -128,7 +134,7 @@
         try
         {
             DependencyManager<S, ?> dm = m_componentManager.getDependencyManager( name );
-            return ( dm != null ) ? dm.getServices() : null;
+            return ( dm != null ) ? dm.getServices(this) : null;
         }
         finally
         {
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 b1368b5..3ba0c57 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
@@ -295,20 +295,20 @@
         return false;
     }
 
-    protected boolean collectDependencies()
+    protected boolean collectDependencies(ComponentContextImpl<S> componentContext)
     {
         return true;
     }
 
-    <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<T> ref, int trackingCount )
+    <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> ref, int trackingCount )
     {
     }
 
-    <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> reference, int trackingCount )
+    <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> reference, int trackingCount )
     {
     }
 
-    <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> oldRef, int trackingCount )
+    <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> oldRef, int trackingCount )
     {
     }
 
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
index 64ad529..0fd5224 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
@@ -35,9 +35,12 @@
 import org.apache.felix.scr.impl.config.ReferenceManager;
 import org.apache.felix.scr.impl.helper.BindMethod;
 import org.apache.felix.scr.impl.helper.BindMethods;
+import org.apache.felix.scr.impl.helper.BindParameters;
 import org.apache.felix.scr.impl.helper.Coercions;
 import org.apache.felix.scr.impl.helper.MethodResult;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
+import org.apache.felix.scr.impl.metadata.ReferenceMetadata.ReferenceScope;
+import org.apache.felix.scr.impl.metadata.ServiceMetadata.Scope;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Filter;
@@ -65,13 +68,13 @@
     
     private final int m_index;
 
-    private final Customizer<T> m_customizer;
+    private final Customizer<S, T> m_customizer;
 
     //only set once, but it's not clear there is enough other synchronization to get the correct object before it's used.
     private volatile BindMethods m_bindMethods;
 
     //reset on filter change
-    private volatile ServiceTracker<T, RefPair<T>> m_tracker;
+    private volatile ServiceTracker<T, RefPair<S, T>> m_tracker;
 
     // the target service filter string
     private volatile String m_target;
@@ -126,37 +129,38 @@
        m_bindMethods = bindMethods;
     }
 
-    private interface Customizer<T> extends ServiceTrackerCustomizer<T, RefPair<T>>
+    private interface Customizer<S, T> extends ServiceTrackerCustomizer<T, RefPair<S, T>>
     {
         /**
          * attempt to obtain the services from the tracked service references that will be used in inital bind calls
          * before activation.
+         * @param key TODO
          * @return true if there are enough services for activation.
          */
-        boolean prebind();
+        boolean prebind(ComponentContextImpl<S> key);
 
         void close();
 
-        Collection<RefPair<T>> getRefs( AtomicInteger trackingCount );
+        Collection<RefPair<S, T>> getRefs( AtomicInteger trackingCount );
 
         boolean isSatisfied();
         
-        void setTracker( ServiceTracker<T, RefPair<T>> tracker );
+        void setTracker( ServiceTracker<T, RefPair<S, T>> tracker );
 
         void setTrackerOpened();
 
-        void setPreviousRefMap( Map<ServiceReference<T>, RefPair<T>> previousRefMap );
+        void setPreviousRefMap( Map<ServiceReference<T>, RefPair<S, T>> previousRefMap );
     }
 
-    private abstract class AbstractCustomizer implements Customizer<T>
+    private abstract class AbstractCustomizer implements Customizer<S, T>
     {
-        private final Map<ServiceReference<T>, RefPair<T>> EMPTY_REF_MAP = Collections.emptyMap();
+        private final Map<ServiceReference<T>, RefPair<S, T>> EMPTY_REF_MAP = Collections.emptyMap();
 
         private volatile boolean trackerOpened;
 
-        private volatile Map<ServiceReference<T>, RefPair<T>> previousRefMap = EMPTY_REF_MAP;
+        private volatile Map<ServiceReference<T>, RefPair<S, T>> previousRefMap = EMPTY_REF_MAP;
 
-        public void setTracker( ServiceTracker<T, RefPair<T>> tracker )
+        public void setTracker( ServiceTracker<T, RefPair<S, T>> tracker )
         {
             m_tracker = tracker;
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracker reset (closed)", new Object[] {getName()}, null );
@@ -165,7 +169,7 @@
 
         public boolean isSatisfied()
         {
-            ServiceTracker<T, RefPair<T>> tracker = getTracker();
+            ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
             if ( tracker == null)
             {
                 return false;
@@ -173,7 +177,7 @@
             return cardinalitySatisfied( tracker.getServiceCount() );
         }
 
-        protected ServiceTracker<T, RefPair<T>> getTracker()
+        protected ServiceTracker<T, RefPair<S, T>> getTracker()
         {
             return m_tracker;
         }
@@ -200,19 +204,19 @@
 
         protected void deactivateTracker()
         {
-            ServiceTracker<T, RefPair<T>> tracker = getTracker();
+            ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
             if ( tracker != null )
             {
                 tracker.deactivate();
             }
         }
 
-        protected Map<ServiceReference<T>, RefPair<T>> getPreviousRefMap()
+        protected Map<ServiceReference<T>, RefPair<S, T>> getPreviousRefMap()
         {
             return previousRefMap;
         }
 
-        public void setPreviousRefMap( Map<ServiceReference<T>, RefPair<T>> previousRefMap )
+        public void setPreviousRefMap( Map<ServiceReference<T>, RefPair<S, T>> previousRefMap )
         {
             if ( previousRefMap != null )
             {
@@ -225,9 +229,9 @@
 
         }
 
-        protected void ungetService( RefPair<T> ref )
+        protected void ungetService( RefPair<S, T> ref )
         {
-            Object service = ref.unsetServiceObject();
+            Object service = ref.unsetServiceObject(null);
             if ( service != null )
             {
                 BundleContext bundleContext = m_componentManager.getBundleContext();
@@ -248,13 +252,13 @@
 
     private class FactoryCustomizer extends AbstractCustomizer {
 
-        public RefPair<T> addingService( ServiceReference<T> serviceReference )
+        public RefPair<S, T> addingService( ServiceReference<T> serviceReference )
         {
-            RefPair<T> refPair = new RefPair<T>( serviceReference  );
+            RefPair<S, T> refPair = newRefPair(serviceReference);
             return refPair;
         }
 
-        public void addedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
         {
             if ( cardinalityJustSatisfied( serviceCount ) )
             {
@@ -262,11 +266,11 @@
             }
         }
 
-        public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
         {
         }
 
-        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
         {
             refPair.setDeleted( true );
             if ( !cardinalitySatisfied( getTracker().getServiceCount() ) )
@@ -275,7 +279,7 @@
             }
         }
 
-        public boolean prebind()
+        public boolean prebind(ComponentContextImpl<S> key)
         {
             AtomicInteger trackingCount = new AtomicInteger( );
             int serviceCount = getTracker().getTracked( true, trackingCount ).size();
@@ -287,7 +291,7 @@
             deactivateTracker();
         }
 
-        public Collection<RefPair<T>> getRefs( AtomicInteger trackingCount )
+        public Collection<RefPair<S, T>> getRefs( AtomicInteger trackingCount )
         {
             return Collections.emptyList();
         }
@@ -295,20 +299,20 @@
 
     private class MultipleDynamicCustomizer extends AbstractCustomizer {
 
-        private RefPair<T> lastRefPair;
+        private RefPair<S, T> lastRefPair;
         private int lastRefPairTrackingCount;
 
-        public RefPair<T> addingService( ServiceReference<T> serviceReference )
+        public RefPair<S, T> addingService( ServiceReference<T> serviceReference )
         {
-            RefPair<T> refPair = getPreviousRefMap().get( serviceReference );
+            RefPair<S, T> refPair = getPreviousRefMap().get( serviceReference );
             if ( refPair == null )
             {
-                refPair = new RefPair<T>( serviceReference  );
+                refPair = newRefPair(serviceReference);
             }
             return refPair;
         }
 
-        public void addedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleDynamic added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
         	boolean tracked = false;
@@ -317,12 +321,9 @@
                 if (isActive())
                 {
                     m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleDynamic already active, binding {2}", new Object[] {getName(), trackingCount, serviceReference}, null );
-                    getServiceObject( m_bindMethods.getBind(), refPair );
-                    if ( !refPair.isFailed() )
+                    m_componentManager.invokeBindMethod( DependencyManager.this, refPair, trackingCount );
+                    if ( refPair.isFailed() )
                     {
-                        m_componentManager.invokeBindMethod( DependencyManager.this, refPair, trackingCount );
-                    }
-                    else {
                         m_componentManager.registerMissingDependency( DependencyManager.this, serviceReference, trackingCount );
                     }
                 }
@@ -345,7 +346,7 @@
 			}
         }
 
-        public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleDynamic modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             if (isActive())
@@ -356,7 +357,7 @@
             tracked( trackingCount );
         }
 
-        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleDynamic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             refPair.setDeleted( true );
@@ -382,14 +383,14 @@
             ungetService( refPair );
         }
 
-        public boolean prebind()
+        public boolean prebind(ComponentContextImpl<S> key)
         {
             int serviceCount = 0;
             AtomicInteger trackingCount = new AtomicInteger( );
-            SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true, trackingCount );
-            for (RefPair<T> refPair: tracked.values())
+            SortedMap<ServiceReference<T>, RefPair<S, T>> tracked = getTracker().getTracked( true, trackingCount );
+            for (RefPair<S, T> refPair: tracked.values())
             {
-                if (getServiceObject( m_bindMethods.getBind(), refPair ))
+                if (getServiceObject( key, m_bindMethods.getBind(), refPair ))
                 {
                      serviceCount++;
                 }
@@ -404,7 +405,7 @@
         public void close()
         {
             AtomicInteger trackingCount = new AtomicInteger( );
-            for ( RefPair<T> ref : getRefs( trackingCount ) )
+            for ( RefPair<S, T> ref : getRefs( trackingCount ) )
             {
                 ungetService( ref );
             }
@@ -412,11 +413,11 @@
         }
 
 
-        public Collection<RefPair<T>> getRefs( AtomicInteger trackingCount )
+        public Collection<RefPair<S, T>> getRefs( AtomicInteger trackingCount )
         {
             if ( lastRefPair == null )
             {
-                ServiceTracker<T, RefPair<T>> tracker = getTracker();
+                ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
                 if (tracker == null) {
                     trackingCount.set( lastRefPairTrackingCount );
                     return Collections.emptyList();                    
@@ -434,17 +435,13 @@
     private class MultipleStaticGreedyCustomizer extends AbstractCustomizer {
 
 
-        public RefPair<T> addingService( ServiceReference<T> serviceReference )
+        public RefPair<S, T> addingService( ServiceReference<T> serviceReference )
         {
-            RefPair<T> refPair = new RefPair<T>( serviceReference  );
-            if (isActive())
-            {
-                 getServiceObject( m_bindMethods.getBind(), refPair );
-            }
+            RefPair<S, T> refPair = newRefPair(serviceReference);
             return refPair;
         }
 
-        public void addedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             tracked( trackingCount );
@@ -464,7 +461,7 @@
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy added {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             if (isActive())
@@ -475,7 +472,7 @@
             tracked( trackingCount );
         }
 
-        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             refPair.setDeleted( true );
@@ -502,15 +499,15 @@
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy removed {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public boolean prebind()
+        public boolean prebind(ComponentContextImpl<S> key)
         {
             int serviceCount = 0;
             AtomicInteger trackingCount = new AtomicInteger( );
-            final ServiceTracker<T, RefPair<T>> tracker = getTracker();
-            SortedMap<ServiceReference<T>, RefPair<T>> tracked = tracker.getTracked( cardinalitySatisfied( tracker.getServiceCount() ), trackingCount );
-            for (RefPair<T> refPair: tracked.values())
+            final ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
+            SortedMap<ServiceReference<T>, RefPair<S, T>> tracked = tracker.getTracked( cardinalitySatisfied( tracker.getServiceCount() ), trackingCount );
+            for (RefPair<S, T> refPair: tracked.values())
             {
-                if ( getServiceObject( m_bindMethods.getBind(), refPair ) )
+                if ( getServiceObject( key, m_bindMethods.getBind(), refPair ) )
                 {
                     serviceCount++;
                 }
@@ -526,16 +523,16 @@
         public void close()
         {
             AtomicInteger trackingCount = new AtomicInteger( );
-            for ( RefPair<T> ref: getRefs( trackingCount ))
+            for ( RefPair<S, T> ref: getRefs( trackingCount ))
             {
                 ungetService( ref );
             }
             deactivateTracker();
         }
 
-        public Collection<RefPair<T>> getRefs( AtomicInteger trackingCount )
+        public Collection<RefPair<S, T>> getRefs( AtomicInteger trackingCount )
         {
-            ServiceTracker<T, RefPair<T>> tracker = getTracker();
+            ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
             if (tracker == null) {
                 return Collections.emptyList();                    
             }            
@@ -545,16 +542,16 @@
 
     private class MultipleStaticReluctantCustomizer extends AbstractCustomizer {
 
-        private final AtomicReference<Collection<RefPair<T>>> refs = new AtomicReference<Collection<RefPair<T>>>();
+        private final AtomicReference<Collection<RefPair<S, T>>> refs = new AtomicReference<Collection<RefPair<S, T>>>();
         private int trackingCount;
 
-        public RefPair<T> addingService( ServiceReference<T> serviceReference )
+        public RefPair<S, T> addingService( ServiceReference<T> serviceReference )
         {
-            RefPair<T> refPair = new RefPair<T>( serviceReference  );
+            RefPair<S, T> refPair = newRefPair(serviceReference);
             return refPair;
         }
 
-        public void addedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             tracked( trackingCount );
@@ -565,10 +562,10 @@
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant added {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
-            Collection<RefPair<T>> refs = this.refs.get();
+            Collection<RefPair<S, T>> refs = this.refs.get();
             if (isActive() && refs.contains( refPair ))
             {                
                 m_componentManager.invokeUpdatedMethod( DependencyManager.this, refPair, trackingCount );
@@ -577,12 +574,12 @@
             tracked( trackingCount );
         }
 
-        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             refPair.setDeleted( true );
             tracked( trackingCount );
-            Collection<RefPair<T>> refs = this.refs.get();
+            Collection<RefPair<S, T>> refs = this.refs.get();
             if ( isActive() && refs != null )
             {
                 if (refs.contains( refPair ))
@@ -609,27 +606,27 @@
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant removed {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public boolean prebind()
+        public boolean prebind(ComponentContextImpl<S> key)
         {
             int serviceCount = 0;
-            Collection<RefPair<T>> refs = this.refs.get();
+            Collection<RefPair<S, T>> refs = this.refs.get();
             if (refs != null) {
                 //another thread is concurrently opening, and it got done already
-                for (RefPair<T> refPair: refs)
+                for (RefPair<S, T> refPair: refs)
                 {
-                    if (getServiceObject( m_bindMethods.getBind(), refPair ))
+                    if (getServiceObject( key, m_bindMethods.getBind(), refPair ))
                     {
                         serviceCount++;
                     }
                 }
                 return cardinalitySatisfied( serviceCount );
             }
-            refs = new ArrayList<RefPair<T>>();
+            refs = new ArrayList<RefPair<S, T>>();
             AtomicInteger trackingCount = new AtomicInteger( );
-            SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true, trackingCount );
-            for (RefPair<T> refPair: tracked.values())
+            SortedMap<ServiceReference<T>, RefPair<S, T>> tracked = getTracker().getTracked( true, trackingCount );
+            for (RefPair<S, T> refPair: tracked.values())
             {
-                if (getServiceObject( m_bindMethods.getBind(), refPair ))
+                if (getServiceObject( key, m_bindMethods.getBind(), refPair ))
                 {
                     serviceCount++;
                 }
@@ -642,9 +639,9 @@
             else 
             {
                 //some other thread got done first.  If we have more refPairs, we might need to unget some services.
-                Collection<RefPair<T>> actualRefs = this.refs.get();
+                Collection<RefPair<S, T>> actualRefs = this.refs.get();
                 refs.removeAll( actualRefs );
-                for (RefPair<T> ref: refs) 
+                for (RefPair<S, T> ref: refs) 
                 {
                     ungetService( ref );
                 }
@@ -654,10 +651,10 @@
 
         public void close()
         {
-            Collection<RefPair<T>> refs = this.refs.getAndSet( null );
+            Collection<RefPair<S, T>> refs = this.refs.getAndSet( null );
             if ( refs != null )
             {
-                for ( RefPair<T> ref: refs )
+                for ( RefPair<S, T> ref: refs )
                 {
                     ungetService( ref );
                 }
@@ -665,30 +662,30 @@
             deactivateTracker();
         }
 
-        public Collection<RefPair<T>> getRefs( AtomicInteger trackingCount )
+        public Collection<RefPair<S, T>> getRefs( AtomicInteger trackingCount )
         {
             trackingCount.set( this.trackingCount );
-            Collection<RefPair<T>> refs = this.refs.get();
-            return refs == null? Collections.<RefPair<T>>emptyList(): refs;
+            Collection<RefPair<S, T>> refs = this.refs.get();
+            return refs == null? Collections.<RefPair<S, T>>emptyList(): refs;
         }
     }
 
     private class SingleDynamicCustomizer extends AbstractCustomizer {
 
-        private RefPair<T> refPair;
+        private RefPair<S, T> refPair;
         private int trackingCount;
 
-        public RefPair<T> addingService( ServiceReference<T> serviceReference )
+        public RefPair<S, T> addingService( ServiceReference<T> serviceReference )
         {
-            RefPair<T> refPair = getPreviousRefMap().get( serviceReference );
+            RefPair<S, T> refPair = getPreviousRefMap().get( serviceReference );
             if ( refPair == null )
             {
-                refPair = new RefPair<T>( serviceReference  );
+                refPair = newRefPair(serviceReference);
             }
             return refPair;
         }
 
-        public void addedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             boolean tracked = false;
@@ -704,10 +701,9 @@
                     }
                     if ( invokeBind )
                     {
-                        getServiceObject( m_bindMethods.getBind(), refPair );
+                        m_componentManager.invokeBindMethod( DependencyManager.this, refPair, trackingCount );
                         if ( !refPair.isFailed() )
                         {
-                            m_componentManager.invokeBindMethod( DependencyManager.this, refPair, trackingCount );
                             if ( this.refPair != null )
                             {
                                 m_componentManager.invokeUnbindMethod( DependencyManager.this, this.refPair,
@@ -738,7 +734,7 @@
             }
         }
 
-        public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             boolean invokeUpdated;
@@ -755,14 +751,14 @@
             tracked( trackingCount );
         }
 
-        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             refPair.setDeleted( true );
             boolean deactivate = false;
             boolean untracked = true;
-            RefPair<T> oldRefPair = null;
-            RefPair<T> nextRefPair = null;
+            RefPair<S, T> oldRefPair = null;
+            RefPair<S, T> nextRefPair = null;
             synchronized ( getTracker().tracked() )
             {
                 if ( refPair == this.refPair && isActive() )
@@ -770,7 +766,7 @@
                     if ( !getTracker().isEmpty() )
                     {
                         AtomicInteger trackingCount2 = new AtomicInteger();
-                        SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true, //TODO true here looks odd.
+                        SortedMap<ServiceReference<T>, RefPair<S, T>> tracked = getTracker().getTracked( true, //TODO true here looks odd.
                                 trackingCount2 );
                         nextRefPair = tracked.values().iterator().next();
                     }
@@ -793,15 +789,8 @@
             }
             if ( nextRefPair != null )
             {
-                if ( !getServiceObject( m_bindMethods.getBind(), nextRefPair ) )
-                {
-                    //TODO error???
-                }
-                if ( !nextRefPair.isFailed() )
-                {
-                    m_componentManager.invokeBindMethod( DependencyManager.this, nextRefPair,
+                m_componentManager.invokeBindMethod( DependencyManager.this, nextRefPair,
                             trackingCount );
-                }
             }
 
             if ( oldRefPair != null )
@@ -834,16 +823,16 @@
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic removed {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public boolean prebind()
+        public boolean prebind(ComponentContextImpl<S> key)
         {
-            RefPair<T> refPair = null;
+            RefPair<S, T> refPair = null;
             boolean success = cardinalitySatisfied( 0 );
             AtomicInteger trackingCount = new AtomicInteger();
             synchronized ( getTracker().tracked() )
             {
                 if ( success || !getTracker().isEmpty() )
                 {
-                    SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true, trackingCount );
+                    SortedMap<ServiceReference<T>, RefPair<S, T>> tracked = getTracker().getTracked( true, trackingCount );
                     if ( !tracked.isEmpty() )
                     {
                         refPair = tracked.values().iterator().next();
@@ -853,7 +842,7 @@
             }
             if (refPair != null) 
             {
-                success |= getServiceObject( m_bindMethods.getBind(), refPair );
+                success |= getServiceObject( key, m_bindMethods.getBind(), refPair );
                 if ( refPair.isFailed() )
                 {
                     m_componentManager.registerMissingDependency( DependencyManager.this, refPair.getRef(),
@@ -878,7 +867,7 @@
             refPair = null;
         }
 
-        public Collection<RefPair<T>> getRefs( AtomicInteger trackingCount )
+        public Collection<RefPair<S, T>> getRefs( AtomicInteger trackingCount )
         {
             Object monitor = getTracker() == null? null: getTracker().tracked();
             if ( monitor != null )
@@ -886,12 +875,12 @@
                 synchronized ( monitor )
                 {
                     trackingCount.set( this.trackingCount );
-                    return refPair == null? Collections.<RefPair<T>> emptyList(): Collections.singleton( refPair );
+                    return refPair == null? Collections.<RefPair<S, T>> emptyList(): Collections.singleton( refPair );
                 }
             }
             else
             {
-                return Collections.<RefPair<T>> emptyList();
+                return Collections.<RefPair<S, T>> emptyList();
             }
         }
     }
@@ -899,16 +888,16 @@
     private class SingleStaticCustomizer extends AbstractCustomizer
     {
 
-        private RefPair<T> refPair;
+        private RefPair<S, T> refPair;
         private int trackingCount;
 
-        public RefPair<T> addingService( ServiceReference<T> serviceReference )
+        public RefPair<S, T> addingService( ServiceReference<T> serviceReference )
         {
-            RefPair<T> refPair = new RefPair<T>( serviceReference );
+            RefPair<S, T> refPair = newRefPair(serviceReference);
             return refPair;
         }
 
-        public void addedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             this.trackingCount = trackingCount;
@@ -941,7 +930,7 @@
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic added {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             boolean invokeUpdated;
@@ -958,7 +947,7 @@
             tracked( trackingCount );
         }
 
-        public void removedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             refPair.setDeleted( true );
@@ -988,16 +977,16 @@
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic removed {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public boolean prebind()
+        public boolean prebind(ComponentContextImpl<S> key)
         {
             boolean success = cardinalitySatisfied( 0 );
             if ( success || !getTracker().isEmpty() )
             {
-                RefPair<T> refPair = null;
+                RefPair<S, T> refPair = null;
                 AtomicInteger trackingCount = new AtomicInteger();
                 synchronized ( getTracker().tracked() )
                 {
-                    SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true, trackingCount );
+                    SortedMap<ServiceReference<T>, RefPair<S, T>> tracked = getTracker().getTracked( true, trackingCount );
                     if ( !tracked.isEmpty() )
                     {
                         refPair = tracked.values().iterator().next();
@@ -1006,7 +995,7 @@
                 }
                 if ( refPair != null )
                 {
-                    success |= getServiceObject( m_bindMethods.getBind(), refPair );
+                    success |= getServiceObject( key, m_bindMethods.getBind(), refPair );
                     if ( refPair.isFailed() )
                     {
                         m_componentManager.registerMissingDependency( DependencyManager.this, refPair.getRef(),
@@ -1019,10 +1008,10 @@
 
         public void close()
         {
-            ServiceTracker<T, RefPair<T>> tracker = getTracker();
+            ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
             if ( tracker != null )
             {
-                RefPair<T> ref;
+                RefPair<S, T> ref;
                 synchronized ( tracker.tracked() )
                 {
                     ref = refPair;
@@ -1036,7 +1025,7 @@
             }
         }
 
-        public Collection<RefPair<T>> getRefs( AtomicInteger trackingCount )
+        public Collection<RefPair<S, T>> getRefs( AtomicInteger trackingCount )
         {
             Object monitor = getTracker() == null? null: getTracker().tracked();
             if ( monitor != null )
@@ -1044,20 +1033,20 @@
                 synchronized ( monitor )
                 {
                     trackingCount.set( this.trackingCount );
-                    return refPair == null? Collections.<RefPair<T>> emptyList(): Collections.singleton( refPair );
+                    return refPair == null? Collections.<RefPair<S, T>> emptyList(): Collections.singleton( refPair );
                 }
             }
             else
             {
-                return Collections.<RefPair<T>> emptyList();
+                return Collections.<RefPair<S, T>> emptyList();
             }
         }
     }
 
-    private class NoPermissionsCustomizer implements Customizer<T>
+    private class NoPermissionsCustomizer implements Customizer<S, T>
     {
 
-        public boolean prebind()
+        public boolean prebind(ComponentContextImpl<S> key)
         {
             return false;
         }
@@ -1066,7 +1055,7 @@
         {
         }
 
-        public Collection<RefPair<T>> getRefs( AtomicInteger trackingCount )
+        public Collection<RefPair<S, T>> getRefs( AtomicInteger trackingCount )
         {
             return Collections.emptyList();
         }
@@ -1076,7 +1065,7 @@
             return isOptional();
         }
 
-        public void setTracker( ServiceTracker<T, RefPair<T>> tRefPairServiceTracker )
+        public void setTracker( ServiceTracker<T, RefPair<S, T>> tRefPairServiceTracker )
         {
         }
 
@@ -1084,24 +1073,24 @@
         {
         }
 
-        public void setPreviousRefMap( Map<ServiceReference<T>, RefPair<T>> previousRefMap )
+        public void setPreviousRefMap( Map<ServiceReference<T>, RefPair<S, T>> previousRefMap )
         {
         }
 
-        public RefPair<T> addingService( ServiceReference<T> tServiceReference )
+        public RefPair<S, T> addingService( ServiceReference<T> tServiceReference )
         {
             return null;
         }
 
-        public void addedService( ServiceReference<T> tServiceReference, RefPair<T> service, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount, int serviceCount )
         {
         }
 
-        public void modifiedService( ServiceReference<T> tServiceReference, RefPair<T> service, int trackingCount )
+        public void modifiedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount )
         {
         }
 
-        public void removedService( ServiceReference<T> tServiceReference, RefPair<T> service, int trackingCount )
+        public void removedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount )
         {
         }
     }
@@ -1225,9 +1214,9 @@
      * value, the service with the lowest service.id is returned.
      * <p>
      */
-    private RefPair<T> getBestRefPair()
+    private RefPair<S, T> getBestRefPair()
     {
-        Collection<RefPair<T>> refs = m_customizer.getRefs( new AtomicInteger( ) );
+        Collection<RefPair<S, T>> refs = m_customizer.getRefs( new AtomicInteger( ) );
         if (refs.isEmpty())
         {
             return null;
@@ -1241,11 +1230,12 @@
      * {@link #getBestRefPair()} method. If this returns a
      * non-<code>null</code> service instance the service is then considered
      * bound to this instance.
+     * @param key TODO
      */
-    T getService()
+    T getService(ComponentContextImpl<S> key)
     {
-        RefPair<T> sr = getBestRefPair();
-        return getService( sr );
+        RefPair<S, T> sr = getBestRefPair();
+        return getService( key, sr );
     }
 
 
@@ -1255,14 +1245,15 @@
      * match the criteria configured for this dependency <code>null</code> is
      * returned. All services returned by this method will be considered bound
      * after this method returns.
+     * @param key TODO
      */
-    T[] getServices()
+    T[] getServices(ComponentContextImpl<S> key)
     {
-        Collection<RefPair<T>> refs = m_customizer.getRefs(  new AtomicInteger( ) );
+        Collection<RefPair<S, T>> refs = m_customizer.getRefs(  new AtomicInteger( ) );
         List<T> services = new ArrayList<T>( refs.size() );
-        for ( RefPair<T> ref: refs)
+        for ( RefPair<S, T> ref: refs)
         {
-            T service = getService(ref);
+            T service = getService(key, ref);
             if (service != null)
             {
                 services.add( service );
@@ -1279,9 +1270,9 @@
 	 */
     public List<ServiceReference<?>> getServiceReferences()
     {
-        Collection<RefPair<T>> bound = m_customizer.getRefs(  new AtomicInteger( ) );
+        Collection<RefPair<S, T>> bound = m_customizer.getRefs(  new AtomicInteger( ) );
         List<ServiceReference<?>> result = new ArrayList<ServiceReference<?>>(bound.size());
-        for (RefPair<T> ref: bound)
+        for (RefPair<S, T> ref: bound)
         {
             result.add(ref.getRef());
         }
@@ -1299,9 +1290,9 @@
      *      if the service is bound or <code>null</code> if the service is not
      *      bound.
      */
-    private RefPair<T> getRefPair( ServiceReference<T> serviceReference )
+    private RefPair<S, T> getRefPair( ServiceReference<T> serviceReference )
     {
-        final ServiceTracker<T, RefPair<T>> tracker = m_tracker;
+        final ServiceTracker<T, RefPair<S, T>> tracker = m_tracker;
         if ( tracker != null )
         {
             AtomicInteger trackingCount = new AtomicInteger( );
@@ -1316,20 +1307,20 @@
      * is already bound the given service, that bound service instance is
      * returned. Otherwise the service retrieved from the service registry
      * and kept as a bound service for future use.
-     *
+     * @param key TODO
      * @param serviceReference The reference to the service to be returned
      *
      * @return The requested service or <code>null</code> if no service is
      *      registered for the service reference (any more).
      */
-    T getService( ServiceReference<T> serviceReference )
+    T getService( ComponentContextImpl<S> key, ServiceReference<T> serviceReference )
     {
         // check whether we already have the service and return that one
-        RefPair<T> refPair = getRefPair( serviceReference );
-        return getService( refPair );
+        RefPair<S, T> refPair = getRefPair( serviceReference );
+        return getService( key, refPair );
     }
 
-    private T getService( RefPair<T> refPair )
+    private T getService( ComponentContextImpl<S> key, RefPair<S, T> refPair )
     {
         if (refPair == null)
         {
@@ -1337,7 +1328,7 @@
             return null;
         }
         T serviceObject;
-        if ( (serviceObject = refPair.getServiceObject()) != null )
+        if ( (serviceObject = refPair.getServiceObject(key)) != null )
         {
             return serviceObject;
         }
@@ -1352,7 +1343,8 @@
         }
         try
         {
-            serviceObject = bundleContext.getService( refPair.getRef() );
+            refPair.getServiceObject(key, bundleContext, m_componentManager);
+            serviceObject = refPair.getServiceObject( key );
         }
         catch ( Exception e )
         {
@@ -1365,12 +1357,6 @@
             return null;
         }
 
-        // keep the service for later ungetting
-        if ( !refPair.setServiceObject( serviceObject ) )
-        {
-            //another thread got the service first
-            bundleContext.ungetService( refPair.getRef() );
-        }
 
         // return the acquired service (may be null of course)
         //even if we did not set the service object, all the getService are for the same bundle so will have the same object.
@@ -1416,9 +1402,9 @@
         return true;
     }
 
-    boolean prebind()
+    boolean prebind(ComponentContextImpl<S> key)
     {
-        return m_customizer.prebind();
+        return m_customizer.prebind(key);
     }
 
     /**
@@ -1429,15 +1415,11 @@
      * @return true if the dependency is satisfied and at least the minimum
      *      number of services could be bound. Otherwise false is returned.
      */
-    boolean open( S componentInstance, EdgeInfo edgeInfo )
+    boolean open( ComponentContextImpl<S> componentContext, EdgeInfo edgeInfo )
     {
-        // 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();
+        int serviceCount = 0;
         AtomicInteger trackingCount =  new AtomicInteger( );
-        Collection<RefPair<T>> refs;
+        Collection<RefPair<S, T>> refs;
         CountDownLatch openLatch;
         synchronized ( m_tracker.tracked() )
         {
@@ -1447,39 +1429,39 @@
         }
         m_componentManager.log( LogService.LOG_DEBUG,
             "For dependency {0}, optional: {1}; to bind: {2}",
-            new Object[]{ getName(), success, refs }, null );
-        for ( RefPair<T> refPair : refs )
+            new Object[]{ getName(), isOptional(), refs }, null );
+        for ( RefPair<S, T> refPair : refs )
         {
             if ( !refPair.isDeleted() && !refPair.isFailed() )
             {
-                if ( !doInvokeBindMethod( componentInstance, refPair ) )
+                if ( !doInvokeBindMethod( componentContext, refPair ) )
                 {
                     m_componentManager.log( LogService.LOG_DEBUG,
                             "For dependency {0}, failed to invoke bind method on object {1}",
                             new Object[] {getName(), refPair}, null );
 
                 }
-                success = true;
+                serviceCount++;
             }
         }
         openLatch.countDown();
-        return success;
+        return cardinalitySatisfied(serviceCount);
     }
 
     /**
      * Revoke the given bindings. This method cannot throw an exception since
      * it must try to complete all that it can
-     * @param componentInstance instance we are unbinding from.
+     * @param componentContext instance we are unbinding from.
      * @param edgeInfo EdgeInfo for the combination of this component instance and this dependency manager.
      */
-    void close( S componentInstance, EdgeInfo edgeInfo )
+    void close( ComponentContextImpl<S> componentContext, EdgeInfo edgeInfo )
     {
         // only invoke the unbind method if there is an instance (might be null
         // in the delayed component situation) and the unbind method is declared.
-        boolean doUnbind = componentInstance != null && m_dependencyMetadata.getUnbind() != null;
+        boolean doUnbind = componentContext != null && m_dependencyMetadata.getUnbind() != null;
 
         AtomicInteger trackingCount = new AtomicInteger();
-        Collection<RefPair<T>> refPairs;
+        Collection<RefPair<S, T>> refPairs;
         CountDownLatch latch;
         synchronized ( m_tracker.tracked() )
         {
@@ -1490,13 +1472,13 @@
 
         m_componentManager.log( LogService.LOG_DEBUG,
                 "DependencyManager: {0} close component unbinding from {1} at tracking count {2} refpairs: {3}",
-                new Object[] {getName(), componentInstance, trackingCount.get(), refPairs}, null );
+                new Object[] {getName(), componentContext, trackingCount.get(), refPairs}, null );
         m_componentManager.waitForTracked( trackingCount.get() );
-        for ( RefPair<T> boundRef : refPairs )
+        for ( RefPair<S, T> boundRef : refPairs )
         {
             if ( doUnbind && !boundRef.isFailed() )
             {
-                invokeUnbindMethod( componentInstance, boundRef, trackingCount.get(), edgeInfo );
+                invokeUnbindMethod( componentContext, boundRef, trackingCount.get(), edgeInfo );
             }
 
         }
@@ -1511,12 +1493,12 @@
         }
         if ( !isMultiple() )
         {
-            Collection<RefPair<T>> refs = m_customizer.getRefs( new AtomicInteger( ) );
+            Collection<RefPair<S, T>> refs = m_customizer.getRefs( new AtomicInteger( ) );
             if (refs.isEmpty())
             {
                 return;
             }
-            RefPair<T> test = refs.iterator().next();
+            RefPair<S, T> test = refs.iterator().next();
             if ( ref != test.getRef())
             {
                 //another ref is now better
@@ -1524,16 +1506,16 @@
             }
         }
         //TODO dynamic reluctant
-        RefPair<T> refPair = m_tracker.getService( ref );
-        if (refPair.getServiceObject() != null)
-        {
-            m_componentManager.log( LogService.LOG_DEBUG,
-                    "DependencyManager : late binding of service reference {1} skipped as service has already been located",
-                    new Object[] {ref}, null );
-            //something else got the reference and may be binding it.
-            return;
-        }
-        getServiceObject( m_bindMethods.getBind(), refPair );
+        RefPair<S, T> refPair = m_tracker.getService( ref );
+        //TODO this check is no longer correct, fix it!
+//        if (refPair.getServiceObject(key) != null)
+//        {
+//            m_componentManager.log( LogService.LOG_DEBUG,
+//                    "DependencyManager : late binding of service reference {1} skipped as service has already been located",
+//                    new Object[] {ref}, null );
+//            //something else got the reference and may be binding it.
+//            return;
+//        }
         m_componentManager.invokeBindMethod( this, refPair, trackingCount );
     }
 
@@ -1547,7 +1529,7 @@
      *
      *
      *
-     * @param componentInstance instance we are binding to
+     * @param componentContext instance we are binding to
      * @param refPair the service reference, service object tuple.
      * @param trackingCount service event counter for this service.
      * @param edgeInfo EdgeInfo for the combination of this instance and this dependency manager.
@@ -1557,11 +1539,11 @@
      *      be handed over to the bind method but the service cannot be
      *      retrieved using the service reference.
      */
-    boolean invokeBindMethod( S componentInstance, RefPair<T> refPair, int trackingCount, EdgeInfo info )
+    boolean invokeBindMethod( ComponentContextImpl<S> componentContext, RefPair<S, T> refPair, int trackingCount, EdgeInfo info )
     {
         // The bind method is only invoked if the implementation object is not
         // null. This is valid for both immediate and delayed components
-        if ( componentInstance != null )
+        if ( componentContext.getImplementationObject( false ) != null )
         {
             synchronized ( m_tracker.tracked() )
             {
@@ -1572,7 +1554,7 @@
                 }
             }
             //edgeInfo open has been set, so binding has started.
-            return doInvokeBindMethod( componentInstance, refPair );
+            return doInvokeBindMethod( componentContext, refPair );
 
         }
         else
@@ -1585,9 +1567,18 @@
         }
     }
 
-    private boolean doInvokeBindMethod(S componentInstance, RefPair<T> refPair)
+    private boolean doInvokeBindMethod(ComponentContextImpl<S> componentContext, RefPair<S, T> refPair)
     {
-        MethodResult result = m_bindMethods.getBind().invoke( componentInstance, refPair, MethodResult.VOID, m_componentManager );
+        if ( !getServiceObject( componentContext, m_bindMethods.getBind(), refPair ))
+        {
+            m_componentManager.log( LogService.LOG_WARNING,
+                    "DependencyManager : invokeUpdatedMethod : Service not available from service registry for ServiceReference {0} for reference {1}",
+                    new Object[] {refPair.getRef(), getName()}, null );
+            return false;
+
+        }
+        BindParameters bp = new BindParameters(componentContext, refPair);
+        MethodResult result = m_bindMethods.getBind().invoke( componentContext.getImplementationObject( false ), bp, MethodResult.VOID, m_componentManager );
         if ( result == null )
         {
             return false;
@@ -1600,11 +1591,11 @@
     /**
      * Calls the updated method.
      *
-     * @param componentInstance instance we are calling updated on.
+     * @param componentContext instance we are calling updated on.
      * @param refPair A service reference corresponding to the service whose service
      * @param edgeInfo EdgeInfo for the comibination of this instance and this dependency manager.
      */
-    void invokeUpdatedMethod( S componentInstance, final RefPair<T> refPair, int trackingCount, EdgeInfo info )
+    void invokeUpdatedMethod( ComponentContextImpl<S> componentContext, final RefPair<S, T> refPair, int trackingCount, EdgeInfo info )
     {
         if ( m_dependencyMetadata.getUpdated() == null )
         {
@@ -1612,7 +1603,7 @@
         }
         // 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 )
+        if ( componentContext != null )
         {
             synchronized ( m_tracker.tracked() )
             {
@@ -1623,7 +1614,7 @@
                 }
             }
             info.waitForOpen( m_componentManager, getName(), "invokeUpdatedMethod" );
-            if ( !getServiceObject( m_bindMethods.getUpdated(), refPair ))
+            if ( !getServiceObject( componentContext, m_bindMethods.getUpdated(), refPair ))
             {
                 m_componentManager.log( LogService.LOG_WARNING,
                         "DependencyManager : invokeUpdatedMethod : Service not available from service registry for ServiceReference {0} for reference {1}",
@@ -1631,7 +1622,8 @@
                 return;
 
             }
-            MethodResult methodResult = m_bindMethods.getUpdated().invoke( componentInstance, refPair, MethodResult.VOID, m_componentManager );
+            BindParameters bp = new BindParameters(componentContext, refPair);
+            MethodResult methodResult = m_bindMethods.getUpdated().invoke( componentContext.getImplementationObject( false ), bp, MethodResult.VOID, m_componentManager );
             if ( methodResult != null)
             {
                 m_componentManager.setServiceProperties( methodResult );
@@ -1655,16 +1647,16 @@
      * to the component this method has no effect and just returns
      * <code>true</code>.
      *
-     * @param componentInstance instance we are unbinding from
+     * @param componentContext instance we are unbinding from
      * @param refPair A service reference, service pair that will be unbound
      * @param trackingCount service event count for this reference
      * @param info EdgeInfo for the combination of this instance and this dependency manager
      */
-    void invokeUnbindMethod( S componentInstance, final RefPair<T> refPair, int trackingCount, EdgeInfo info )
+    void invokeUnbindMethod( ComponentContextImpl<S> componentContext, final RefPair<S, T> refPair, int trackingCount, EdgeInfo info )
     {
         // The unbind method is only invoked if the implementation object is not
         // null. This is valid for both immediate and delayed components
-        if ( componentInstance != null )
+        if ( componentContext != null )
         {
             synchronized ( m_tracker.tracked() )
             {
@@ -1688,7 +1680,7 @@
                 return;
             }
 
-            if ( !getServiceObject( m_bindMethods.getUnbind(), refPair ))
+            if ( !getServiceObject( componentContext, m_bindMethods.getUnbind(), refPair ))
             {
                 m_componentManager.log( LogService.LOG_WARNING,
                         "DependencyManager : invokeUnbindMethod : Service not available from service registry for ServiceReference {0} for reference {1}",
@@ -1696,7 +1688,8 @@
                 return;
 
             }
-            MethodResult methodResult = m_bindMethods.getUnbind().invoke( componentInstance, refPair, MethodResult.VOID, m_componentManager );
+            BindParameters bp = new BindParameters(componentContext, refPair);
+            MethodResult methodResult = m_bindMethods.getUnbind().invoke( componentContext.getImplementationObject( false ), bp, MethodResult.VOID, m_componentManager );
             if ( methodResult != null )
             {
                 m_componentManager.setServiceProperties( methodResult );
@@ -1862,9 +1855,9 @@
             filterString = "(&" + filterString + m_target + ")";
         }
 
-        final ServiceTracker<T, RefPair<T>> oldTracker = m_tracker;
+        final ServiceTracker<T, RefPair<S, T>> oldTracker = m_tracker;
         AtomicInteger trackingCount = new AtomicInteger();
-        SortedMap<ServiceReference<T>, RefPair<T>> refMap = unregisterServiceListener( trackingCount );
+        SortedMap<ServiceReference<T>, RefPair<S, T>> refMap = unregisterServiceListener( trackingCount );
         if ( trackingCount.get() != -1 )
         {
             //wait for service events to complete before processing initial set from new tracker.
@@ -1909,7 +1902,7 @@
         boolean initialActive = oldTracker != null && oldTracker.isActive();
         m_componentManager.log( LogService.LOG_DEBUG, "New service tracker for {0}, initial active: {1}, previous references: {2}", new Object[]
                 {getName(), initialActive, refMap}, null );
-        ServiceTracker<T, RefPair<T>> tracker = new ServiceTracker<T, RefPair<T>>( bundleContext, m_targetFilter, m_customizer, initialActive );
+        ServiceTracker<T, RefPair<S, T>> tracker = new ServiceTracker<T, RefPair<S, T>>( bundleContext, m_targetFilter, m_customizer, initialActive );
         m_customizer.setTracker( tracker );
         //set minimum cardinality
         m_minCardinality = minimumCardinality;
@@ -1924,9 +1917,9 @@
                 {getName()}, null );
     }
 
-    private Customizer<T> newCustomizer()
+    private Customizer<S, T> newCustomizer()
     {
-        Customizer<T> customizer;
+        Customizer<S, T> customizer;
         if (!hasGetPermission())
         {
             customizer = new NoPermissionsCustomizer();
@@ -1969,10 +1962,10 @@
         return customizer;
     }
 
-    SortedMap<ServiceReference<T>, RefPair<T>> unregisterServiceListener( AtomicInteger trackingCount )
+    SortedMap<ServiceReference<T>, RefPair<S, T>> unregisterServiceListener( AtomicInteger trackingCount )
     {
-        SortedMap<ServiceReference<T>, RefPair<T>> refMap;
-        ServiceTracker<T, RefPair<T>> tracker = m_tracker;
+        SortedMap<ServiceReference<T>, RefPair<S, T>> refMap;
+        ServiceTracker<T, RefPair<S, T>> tracker = m_tracker;
         if ( tracker != null )
         {
             refMap = tracker.close( trackingCount );
@@ -1982,7 +1975,7 @@
         }
         else
         {
-            refMap = new TreeMap<ServiceReference<T>, RefPair<T>>(Collections.reverseOrder());
+            refMap = new TreeMap<ServiceReference<T>, RefPair<S, T>>(Collections.reverseOrder());
             m_componentManager.log( LogService.LOG_DEBUG, " No existing service listener to unregister for dependency {0}", new Object[]
                     {getName()}, null );
             trackingCount.set( -1 );
@@ -2006,12 +1999,12 @@
         return "DependencyManager: Component [" + m_componentManager + "] reference [" + getName() + "]";
     }
 
-    boolean getServiceObject(BindMethod bindMethod, RefPair<T> refPair)
+    boolean getServiceObject(ComponentContextImpl<S> key, BindMethod bindMethod, RefPair<S, T> refPair)
     {
         BundleContext bundleContext = m_componentManager.getBundleContext();
         if ( bundleContext != null )
         {
-            return bindMethod.getServiceObject( refPair, bundleContext, m_componentManager );
+            return bindMethod.getServiceObject( key, refPair, bundleContext, m_componentManager );
         }
         else 
         {
@@ -2020,4 +2013,17 @@
         }
     }
 
+    RefPair<S, T> newRefPair(ServiceReference<T> serviceReference)
+    {
+        if ( m_dependencyMetadata.getScope() == ReferenceScope.bundle )
+        {
+            return new SingleRefPair<S, T>( serviceReference  );
+        }
+        if ( m_componentManager.getComponentMetadata().getServiceScope() == Scope.singleton )
+        {
+            return new SinglePrototypeRefPair<S, T>(m_componentManager.getBundleContext(), serviceReference);
+        }
+        return new MultiplePrototypeRefPair<S, T>(m_componentManager.getBundleContext(), serviceReference);
+    }
+
 }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java
new file mode 100644
index 0000000..5454cf1
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package org.apache.felix.scr.impl.manager;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.felix.scr.impl.helper.SimpleLogger;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceObjects;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+/**
+ * @version $Rev:$ $Date:$
+ */
+public class MultiplePrototypeRefPair<S, T> extends RefPair<S, T>
+{
+    private final ServiceObjects<T> serviceObjects;
+    private final ConcurrentMap<ComponentContextImpl<S>, T> instances = new ConcurrentHashMap<ComponentContextImpl<S>, T>();
+    
+    public MultiplePrototypeRefPair( BundleContext context, ServiceReference<T> ref )
+    {
+        super(ref);
+        this.serviceObjects = context.getServiceObjects(ref);
+    }
+
+    @Override
+    public T getServiceObject(ComponentContextImpl<S> key)
+    {
+        return instances.get( key );
+    }
+
+    @Override
+    public boolean setServiceObject(ComponentContextImpl<S> key, T serviceObject)
+    {
+        return instances.putIfAbsent(key, serviceObject) == null;
+    }
+
+    @Override
+    public T unsetServiceObject(ComponentContextImpl<S> key)
+    {
+        return instances.get(key);
+    }
+
+    @Override
+    public String toString()
+    {
+        return "[MultiplePrototypeRefPair: ref: [" + getRef() + "] has service: [" + !instances.isEmpty() + "]]";
+    }
+
+    @Override
+    public boolean getServiceObject(ComponentContextImpl<S> key, BundleContext context,
+        SimpleLogger logger)
+    {
+        T service = serviceObjects.getService();
+        if ( service == null )
+        {
+            setFailed();
+            logger.log(
+                 LogService.LOG_WARNING,
+                 "Could not get service from serviceobjects for ref {0}", new Object[] {getRef()}, null );
+            return false;
+        }
+        if (!setServiceObject(key, service))
+        {
+            // Another thread got the service before, so unget our
+            serviceObjects.ungetService( service );
+        }
+        return true;
+    }
+
+
+}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java
index 3f9a04a..ba57204 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java
@@ -20,20 +20,19 @@
 
 package org.apache.felix.scr.impl.manager;
 
-import java.util.concurrent.atomic.AtomicReference;
-
+import org.apache.felix.scr.impl.helper.SimpleLogger;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 
 /**
  * @version $Rev:$ $Date:$
  */
-public class RefPair<T>
+public abstract class RefPair<S, T>
 {
     private final ServiceReference<T> ref;
-    private AtomicReference<T> serviceObjectRef = new AtomicReference<T>();
 
-    private boolean failed;
-    private volatile boolean deleted;
+    boolean failed;
+    volatile boolean deleted;
 
     public RefPair( ServiceReference<T> ref )
     {
@@ -45,25 +44,13 @@
         return ref;
     }
 
-    public T getServiceObject()
-    {
-        return serviceObjectRef.get();
-    }
+    public abstract boolean getServiceObject( ComponentContextImpl<S> key, BundleContext context, SimpleLogger logger );
+ 
+    public abstract T getServiceObject(ComponentContextImpl<S> key);
 
-    public boolean setServiceObject( T serviceObject )
-    {
-        boolean set = serviceObjectRef.compareAndSet( null, serviceObject );
-        if ( serviceObject != null)
-        {
-            failed = false;
-        }
-        return set;
-    }
+    public abstract boolean setServiceObject( ComponentContextImpl<S> key, T serviceObject );
     
-    public T unsetServiceObject()
-    {
-        return serviceObjectRef.getAndSet( null );
-    }
+    public abstract T unsetServiceObject(ComponentContextImpl<S> key);
 
     public void setFailed( )
     {
@@ -85,9 +72,4 @@
         this.deleted = deleted;
     }
 
-    @Override
-    public String toString()
-    {
-        return "[RefPair: ref: [" + ref + "] service: [" + serviceObjectRef.get() + "]]";
-    }
 }
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 e55b64d..f2d7d04 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
@@ -24,7 +24,7 @@
 import java.util.IdentityHashMap;
 
 import org.apache.felix.scr.impl.config.ComponentContainer;
-import org.apache.felix.scr.impl.helper.ActivateMethod;
+import org.apache.felix.scr.impl.helper.ActivatorParameter;
 import org.apache.felix.scr.impl.helper.ComponentMethods;
 import org.apache.felix.scr.impl.helper.MethodResult;
 import org.apache.felix.scr.impl.helper.ModifiedMethod;
@@ -84,24 +84,15 @@
 
         // When the getServiceMethod is called, the implementation object must be created
 
-        try
+        ComponentContextImpl<S> componentContext = new ComponentContextImpl<S>(this, bundle);
+        if (collectDependencies(componentContext) )
         {
-            if ( !collectDependencies() )
-            {
-                log( LogService.LOG_DEBUG,
-                        "getService (ServiceFactory) did not win collecting dependencies, try creating object anyway.",
-                        null );
+            log( LogService.LOG_DEBUG,
+                "getService (ServiceFactory) dependencies collected.",
+                null );
 
-            }
-            else
-            {
-                log( LogService.LOG_DEBUG,
-                        "getService (ServiceFactory) won collecting dependencies, proceed to creating object.",
-                        null );
-
-            }
         }
-        catch ( IllegalStateException e )
+        else
         {
             //cannot obtain service from a required reference
             return null;
@@ -125,14 +116,18 @@
                 }
             }
 
-        } );
+        }, componentContext );
 
-        // register the components component context if successfull
+        // register the components component context if successful
         if ( service == null )
         {
             // log that the service factory component cannot be created (we don't
             // know why at this moment; this should already have been logged)
             log( LogService.LOG_ERROR, "Failed creating the component instance; see log for reason", null );
+        } 
+        else 
+        {
+            m_activated = true;
         }
 
         return service;
@@ -160,7 +155,7 @@
             // if this was the last use of the component, go back to REGISTERED state
             if ( serviceContexts.isEmpty() && getState() == STATE_ACTIVE )
             {
-                unsetDependenciesCollected();
+                m_activated = false;
             }
         }
     }
@@ -173,27 +168,27 @@
         }
     }
 
-    <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount )
+    <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> refPair, int trackingCount )
     {
         for ( ComponentContextImpl<S> cc : getComponentContexts() )
         {
-            dependencyManager.invokeBindMethod( cc.getImplementationObject( false ), refPair, trackingCount, cc.getEdgeInfo( dependencyManager ) );
+            dependencyManager.invokeBindMethod( cc, refPair, trackingCount, cc.getEdgeInfo( dependencyManager ) );
         }
     }
 
-    <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount )
+    <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> refPair, int trackingCount )
     {
         for ( ComponentContextImpl<S> cc : getComponentContexts() )
         {
-            dependencyManager.invokeUpdatedMethod( cc.getImplementationObject( false ), refPair, trackingCount, cc.getEdgeInfo( dependencyManager ) );
+            dependencyManager.invokeUpdatedMethod( cc, refPair, trackingCount, cc.getEdgeInfo( dependencyManager ) );
         }
     }
 
-    <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> oldRefPair, int trackingCount )
+    <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> oldRefPair, int trackingCount )
     {
         for ( ComponentContextImpl<S> cc : getComponentContexts() )
         {
-            dependencyManager.invokeUnbindMethod( cc.getImplementationObject( false ), oldRefPair, trackingCount, cc.getEdgeInfo( dependencyManager ) );
+            dependencyManager.invokeUnbindMethod( cc, oldRefPair, trackingCount, cc.getEdgeInfo( dependencyManager ) );
         }
     }
 
@@ -205,7 +200,7 @@
         {
             S instance = componentContext.getImplementationObject(true);
             result = modifiedMethod.invoke( instance,
-                    new ActivateMethod.ActivatorParameter( componentContext, -1 ), MethodResult.VOID, this );
+                    new ActivatorParameter( componentContext, -1 ), MethodResult.VOID, this );
 
         }
         return result;
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
index cc8c2d9..23254a5 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
@@ -31,7 +31,7 @@
 import org.apache.felix.scr.impl.BundleComponentActivator;
 import org.apache.felix.scr.impl.config.ComponentContainer;
 import org.apache.felix.scr.impl.config.ReferenceManager;
-import org.apache.felix.scr.impl.helper.ActivateMethod.ActivatorParameter;
+import org.apache.felix.scr.impl.helper.ActivatorParameter;
 import org.apache.felix.scr.impl.helper.ComponentMethods;
 import org.apache.felix.scr.impl.helper.MethodResult;
 import org.apache.felix.scr.impl.helper.ModifiedMethod;
@@ -103,7 +103,7 @@
     // 4. Call the activate method, if present
     // if this method is overwritten, the deleteComponent method should
     // also be overwritten
-    private boolean createComponent()
+    private boolean createComponent(ComponentContextImpl<S> componentContext)
     {
         if ( !isStateLocked() )
         {
@@ -123,7 +123,7 @@
                 {
                     m_componentContext = null;
                 }
-            } );
+            }, componentContext );
 
             // if something failed creating the component instance, return false
             if ( tmpComponent == null )
@@ -215,7 +215,7 @@
     }
 
 
-    protected S createImplementationObject( Bundle usingBundle, SetImplementationObject<S> setter )
+    protected S createImplementationObject( Bundle usingBundle, SetImplementationObject<S> setter, ComponentContextImpl<S> componentContext )
     {
         final Class<S> implementationObjectClass;
         final S implementationObject;
@@ -246,7 +246,7 @@
             return null;
         }
         
-        ComponentContextImpl<S> componentContext = new ComponentContextImpl<S>(this, usingBundle, implementationObject);
+        componentContext.setImplementationObject(implementationObject);
 
         // 3. set the implementation object prematurely
         setter.presetComponentContext( componentContext );
@@ -261,7 +261,7 @@
                 // if a dependency turned unresolved since the validation check,
                 // creating the instance fails here, so we deactivate and return
                 // null.
-                boolean open = dm.open( implementationObject, componentContext.getEdgeInfo( dm ) );
+                boolean open = dm.open( componentContext, componentContext.getEdgeInfo( dm ) );
                 if ( !open )
                 {
                     log( LogService.LOG_ERROR, "Cannot create component instance due to failure to bind reference {0}",
@@ -288,12 +288,11 @@
                 }
                 if ( !skip )
                 {
-                    md.close( implementationObject, componentContext.getEdgeInfo( md ) );
+                    md.close( componentContext, componentContext.getEdgeInfo( md ) );
                 }
                 md.deactivate();
             }
             setter.resetImplementationObject( implementationObject );
-            unsetDependenciesCollected();
             return null;
 
         }
@@ -307,7 +306,7 @@
             // containing the exception with the Log Service and activation fails
             for ( DependencyManager<S, ?> md: getReversedDependencyManagers() )
             {
-                md.close( implementationObject, componentContext.getEdgeInfo( md ) );
+                md.close( componentContext, componentContext.getEdgeInfo( md ) );
             }
 
             // make sure the implementation object is not available
@@ -348,7 +347,7 @@
             // 2. Unbind any bound services
             for ( DependencyManager<S, ?> md: getReversedDependencyManagers() )
             {
-                md.close( implementationObject, componentContext.getEdgeInfo( md ) );
+                md.close( componentContext, componentContext.getEdgeInfo( md ) );
             }
         }
 
@@ -359,36 +358,33 @@
         return m_componentContext != null;
     }
 
-    <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount )
+    <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> refPair, int trackingCount )
     {
         ComponentContextImpl<S> componentContext = m_componentContext;
         if ( componentContext != null )
         {
-            final S impl = componentContext.getImplementationObject( false );
             EdgeInfo info = componentContext.getEdgeInfo( dependencyManager );
-            dependencyManager.invokeBindMethod( impl, refPair, trackingCount, info );
+            dependencyManager.invokeBindMethod( componentContext, refPair, trackingCount, info );
         }
     }
 
-    <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<T> refPair, int trackingCount )
+    <T> void invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> refPair, int trackingCount )
     {
         ComponentContextImpl<S> componentContext = m_componentContext;
         if ( componentContext != null )
         {
-            final S impl = componentContext.getImplementationObject( false );
             EdgeInfo info = componentContext.getEdgeInfo( dependencyManager );
-            dependencyManager.invokeUpdatedMethod( impl, refPair, trackingCount, info );
+            dependencyManager.invokeUpdatedMethod( componentContext, refPair, trackingCount, info );
         }
     }
 
-    <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<T> oldRefPair, int trackingCount )
+    <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> oldRefPair, int trackingCount )
     {
         ComponentContextImpl<S> componentContext = m_componentContext;
         if ( componentContext != null )
         {
-            final S impl = componentContext.getImplementationObject( false );
             EdgeInfo info = componentContext.getEdgeInfo( dependencyManager );
-            dependencyManager.invokeUnbindMethod( impl, oldRefPair, trackingCount, info );
+            dependencyManager.invokeUnbindMethod( componentContext, oldRefPair, trackingCount, info );
         }
     }
 
@@ -768,26 +764,15 @@
             boolean success = true;
             if ( m_componentContext == null )
             {
-                try
+                ComponentContextImpl<S> componentContext = new ComponentContextImpl<S>(this, null);
+                if ( collectDependencies(componentContext))
                 {
-                    if ( !collectDependencies() )
-                    {
                         log(
                                 LogService.LOG_DEBUG,
-                                "getService did not win collecting dependencies, try creating object anyway.",
+                                "getService (single component manager) dependencies collected.",
                                 null );
-
-                    }
-                    else
-                    {
-                        log(
-                                LogService.LOG_DEBUG,
-                                "getService won collecting dependencies, proceed to creating object.",
-                                null );
-
-                    }
                 }
-                catch ( IllegalStateException e )
+                else
                 {
                     log(
                             LogService.LOG_INFO,
@@ -801,7 +786,7 @@
                     if ( m_componentContext == null )
                     {
                         //state should be "Registered"
-                        S result = getService( );
+                        S result = getService(componentContext );
                         if ( result == null )
                         {
                             success = false;;
@@ -826,7 +811,7 @@
         }
     }
 
-    private S getService()
+    private S getService(ComponentContextImpl<S> componentContext)
     {
         //should be write locked
         if (!isInternalEnabled())
@@ -834,7 +819,7 @@
             return null;
         }
 
-        if ( createComponent() )
+        if ( createComponent(componentContext) )
         {
             return getInstance();
         }
@@ -879,7 +864,6 @@
                     if ( m_useCount.get() == 0 )
                     {
                         ungetService( );
-                        unsetDependenciesCollected();
                     }
                 }
                 finally
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/SinglePrototypeRefPair.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/SinglePrototypeRefPair.java
new file mode 100644
index 0000000..0de682a
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/SinglePrototypeRefPair.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package org.apache.felix.scr.impl.manager;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.felix.scr.impl.helper.SimpleLogger;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceObjects;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+/**
+ * @version $Rev:$ $Date:$
+ */
+public class SinglePrototypeRefPair<S, T> extends SingleRefPair<S, T>
+{
+    private final ServiceObjects<T> serviceObjects;
+    
+    public SinglePrototypeRefPair( BundleContext context, ServiceReference<T> ref )
+    {
+        super(ref);
+        this.serviceObjects = context.getServiceObjects(ref);
+    }
+
+    @Override
+    public String toString()
+    {
+        return "[SinglePrototypeRefPair: ref: [" + getRef() + "] service: [" + getServiceObject(null) + "]]";
+    }
+
+    @Override
+    public boolean getServiceObject(ComponentContextImpl<S> key, BundleContext context,
+        SimpleLogger logger)
+    {
+        T service = serviceObjects.getService();
+        if ( service == null )
+        {
+            setFailed();
+            logger.log(
+                 LogService.LOG_WARNING,
+                 "Could not get service from serviceobjects for ref {0}", new Object[] {getRef()}, null );
+            return false;
+        }
+        if (!setServiceObject(key, service))
+        {
+            // Another thread got the service before, so unget our
+            serviceObjects.ungetService( service );
+        }
+        return true;
+    }
+
+}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleRefPair.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleRefPair.java
new file mode 100644
index 0000000..47c727b
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleRefPair.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package org.apache.felix.scr.impl.manager;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.felix.scr.impl.helper.SimpleLogger;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+/**
+ * @version $Rev:$ $Date:$
+ */
+public class SingleRefPair<S, T> extends RefPair<S, T>
+{
+    private AtomicReference<T> serviceObjectRef = new AtomicReference<T>();
+
+    public SingleRefPair( ServiceReference<T> ref )
+    {
+        super(ref);
+    }
+
+    public T getServiceObject(ComponentContextImpl<S> key)
+    {
+        return serviceObjectRef.get();
+    }
+
+    public boolean setServiceObject( ComponentContextImpl<S> key, T serviceObject )
+    {
+        boolean set = serviceObjectRef.compareAndSet( null, serviceObject );
+        if ( serviceObject != null)
+        {
+            failed = false;
+        }
+        return set;
+    }
+    
+    public T unsetServiceObject(ComponentContextImpl<S> key)
+    {
+        return serviceObjectRef.getAndSet( null );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "[RefPair: ref: [" + getRef() + "] service: [" + serviceObjectRef.get() + "]]";
+    }
+
+    @Override
+    public boolean getServiceObject(ComponentContextImpl<S> key, BundleContext context,
+        SimpleLogger logger)
+    {
+        T service = context.getService( getRef() );
+        if ( service == null )
+        {
+            setFailed();
+            logger.log(
+                 LogService.LOG_WARNING,
+                 "Could not get service from ref {0}", new Object[] {getRef()}, null );
+            return false;
+        }
+        if (!setServiceObject(key, service))
+        {
+            // Another thread got the service before, so unget our
+            context.ungetService( getRef() );
+        }
+        return true;
+    }
+}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java b/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
index f8e6ca8..ce3dfae 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
@@ -269,7 +269,7 @@
         ComponentContainer container = newContainer();
         SingleComponentManager icm = new SingleComponentManager( container, new ComponentMethods() );
         ActivateMethod am = new ActivateMethod( methodName, methodName != null, obj.getClass(), true, false );
-        am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ), null, icm );
+        am.invoke( obj, new ActivatorParameter( m_ctx, -1 ), null, icm );
         Method m = get(am, "m_method");
         assertNotNull( m );
         assertEquals( methodName, m.getName() );
@@ -324,7 +324,7 @@
         ComponentContainer container = newContainer();
         SingleComponentManager icm = new SingleComponentManager( container, new ComponentMethods() );
         ActivateMethod am = new ActivateMethod( methodName, methodName != null, obj.getClass(), true, false );
-        am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ), null, icm );
+        am.invoke( obj, new ActivatorParameter( m_ctx, -1 ), null, icm );
         assertNull( get( am, "m_method" ) );
         assertNull( obj.getCalledMethod() );
     }
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java b/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java
index e0c45fd..b0a18b2 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java
@@ -23,8 +23,10 @@
 
 import org.apache.felix.scr.impl.BundleComponentActivator;
 import org.apache.felix.scr.impl.config.ComponentContainer;
+import org.apache.felix.scr.impl.manager.ComponentContextImpl;
 import org.apache.felix.scr.impl.manager.SingleComponentManager;
 import org.apache.felix.scr.impl.manager.RefPair;
+import org.apache.felix.scr.impl.manager.SingleRefPair;
 import org.apache.felix.scr.impl.manager.components.FakeService;
 import org.apache.felix.scr.impl.manager.components.T1;
 import org.apache.felix.scr.impl.manager.components.T1a;
@@ -434,9 +436,11 @@
         SingleComponentManager icm = new SingleComponentManager( container, new ComponentMethods() );
         BindMethod bm = new BindMethod( methodName, component.getClass(),
                 FakeService.class.getName(), isDS11, false );
-        RefPair refPair = new RefPair( m_serviceReference );
-        assertTrue( bm.getServiceObject( refPair, m_context, icm ) );
-        bm.invoke( component, refPair, null, icm );
+        RefPair refPair = new SingleRefPair( m_serviceReference );
+        ComponentContextImpl<T1> cc = new ComponentContextImpl(icm, null);
+        assertTrue( bm.getServiceObject( cc, refPair, m_context, icm ) );
+        BindParameters bp = new BindParameters(cc, refPair);
+        bm.invoke( component, bp, null, icm );
         assertEquals( expectCallPerformed, component.callPerformed );
     }