FELIX-4964 Activate a component at most once from a service event

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1691760 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
index 14b2142..b6c8d77 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
@@ -18,7 +18,6 @@
  */
 package org.apache.felix.scr.impl;
 
-
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
@@ -28,8 +27,11 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.StringTokenizer;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -39,23 +41,29 @@
 import org.apache.felix.scr.impl.helper.Logger;
 import org.apache.felix.scr.impl.manager.AbstractComponentManager;
 import org.apache.felix.scr.impl.manager.DependencyManager;
+import org.apache.felix.scr.impl.manager.ExtendedServiceEvent;
+import org.apache.felix.scr.impl.manager.ExtendedServiceListener;
+import org.apache.felix.scr.impl.manager.ExtendedServiceListenerContext;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.XmlHandler;
 import org.apache.felix.scr.impl.parser.KXml2SAXParser;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentException;
 import org.osgi.service.log.LogService;
 import org.osgi.util.tracker.ServiceTracker;
 
-
 /**
  * The BundleComponentActivator is helper class to load and unload Components of
  * a single bundle. It will read information from the metadata.xml file
  * descriptors and create the corresponding managers.
  */
-public class BundleComponentActivator implements Logger
+public class BundleComponentActivator implements Logger, ExtendedServiceListenerContext<ExtendedServiceEvent>
 {
     // global component registration
     private final ComponentRegistry m_componentRegistry;
@@ -82,10 +90,149 @@
     // the configuration
     private final ScrConfiguration m_configuration;
 
+    private final Map<String, ListenerInfo> listenerMap = new HashMap<String, ListenerInfo>();
+
+    private static class ListenerInfo implements ServiceListener
+    {
+        private Map<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>> filterMap = new HashMap<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>>();
+
+        public void serviceChanged(ServiceEvent event)
+        {
+            ServiceReference<?> ref = event.getServiceReference();
+            ExtendedServiceEvent extEvent = null;
+            ExtendedServiceEvent endMatchEvent = null;
+            Map<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>> filterMap;
+            synchronized (this)
+            {
+                filterMap = this.filterMap;
+            }
+            for (Map.Entry<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>> entry : filterMap.entrySet())
+            {
+                Filter filter = entry.getKey();
+                if (filter == null || filter.match(ref))
+                {
+                    if (extEvent == null)
+                    {
+                        extEvent = new ExtendedServiceEvent(event);
+                    }
+                    for (ExtendedServiceListener<ExtendedServiceEvent> forwardTo : entry.getValue())
+                    {
+                        forwardTo.serviceChanged(extEvent);
+                    }
+                }
+                else if (event.getType() == ServiceEvent.MODIFIED)
+                {
+                    if (endMatchEvent == null)
+                    {
+                        endMatchEvent = new ExtendedServiceEvent(
+                            ServiceEvent.MODIFIED_ENDMATCH, ref);
+                    }
+                    for (ExtendedServiceListener<ExtendedServiceEvent> forwardTo : entry.getValue())
+                    {
+                        forwardTo.serviceChanged(endMatchEvent);
+                    }
+                }
+            }
+            if (extEvent != null)
+            {
+                extEvent.activateManagers();
+            }
+            if (endMatchEvent != null)
+            {
+                endMatchEvent.activateManagers();
+            }
+        }
+
+        public synchronized void add(Filter filter,
+            ExtendedServiceListener<ExtendedServiceEvent> listener)
+        {
+            filterMap = new HashMap<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>>(
+                filterMap);
+            List<ExtendedServiceListener<ExtendedServiceEvent>> listeners = filterMap.get(filter);
+            if (listeners == null)
+            {
+                listeners = Collections.<ExtendedServiceListener<ExtendedServiceEvent>> singletonList(listener);
+            }
+            else
+            {
+                listeners = new ArrayList<ExtendedServiceListener<ExtendedServiceEvent>>(
+                    listeners);
+                listeners.add(listener);
+            }
+            filterMap.put(filter, listeners);
+        }
+
+        public synchronized boolean remove(Filter filter,
+            ExtendedServiceListener<ExtendedServiceEvent> listener)
+        {
+            List<ExtendedServiceListener<ExtendedServiceEvent>> listeners = filterMap.get(filter);
+            if (listeners != null)
+            {
+                filterMap = new HashMap<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>>(
+                    filterMap);
+                listeners = new ArrayList<ExtendedServiceListener<ExtendedServiceEvent>>(
+                    listeners);
+                listeners.remove(listener);
+                if (listeners.isEmpty())
+                {
+                    filterMap.remove(filter);
+                }
+                else
+                {
+                    filterMap.put(filter, listeners);
+                }
+            }
+            return filterMap.isEmpty();
+        }
+    }
+
+    public void addServiceListener(String classNameFilter, Filter eventFilter,
+        ExtendedServiceListener<ExtendedServiceEvent> listener)
+    {
+        ListenerInfo listenerInfo;
+        synchronized (listenerMap)
+        {
+            log(LogService.LOG_DEBUG, "classNameFilter: " + classNameFilter
+                + " event filter: " + eventFilter, null, null, null);
+            listenerInfo = listenerMap.get(classNameFilter);
+            if (listenerInfo == null)
+            {
+                listenerInfo = new ListenerInfo();
+                listenerMap.put(classNameFilter, listenerInfo);
+                try
+                {
+                    m_context.addServiceListener(listenerInfo, classNameFilter);
+                }
+                catch (InvalidSyntaxException e)
+                {
+                    throw (IllegalArgumentException) new IllegalArgumentException(
+                        "invalid class name filter").initCause(e);
+                }
+            }
+        }
+        listenerInfo.add(eventFilter, listener);
+    }
+
+    public void removeServiceListener(String className, Filter filter,
+        ExtendedServiceListener<ExtendedServiceEvent> listener)
+    {
+        synchronized (listenerMap)
+        {
+            ListenerInfo listenerInfo = listenerMap.get(className);
+            if (listenerInfo != null)
+            {
+                if (listenerInfo.remove(filter, listener))
+                {
+                    listenerMap.remove(className);
+                    m_context.removeServiceListener(listenerInfo);
+                }
+            }
+        }
+    }
 
     /**
      * Called upon starting of the bundle. This method invokes initialize() which
-     * parses the metadata and creates the instance managers
+     * parses the metadata and creates the holders
      *
      * @param componentRegistry The <code>ComponentRegistry</code> used to
      *      register components with to ensure uniqueness of component names
@@ -94,8 +241,7 @@
      *
      * @throws ComponentException if any error occurrs initializing this class
      */
-    BundleComponentActivator( ComponentRegistry componentRegistry,
-        ComponentActorThread componentActor, BundleContext context, ScrConfiguration configuration ) throws ComponentException
+    BundleComponentActivator(ComponentRegistry componentRegistry, ComponentActorThread componentActor, BundleContext context, ScrConfiguration configuration) throws ComponentException
     {
         // keep the parameters for later
         m_componentRegistry = componentRegistry;
@@ -104,24 +250,26 @@
         m_bundle = context.getBundle();
 
         // have the LogService handy (if available)
-        m_logService = new ServiceTracker<LogService, LogService>( context, Activator.LOGSERVICE_CLASS, null );
+        m_logService = new ServiceTracker<LogService, LogService>(context,
+            Activator.LOGSERVICE_CLASS, null);
         m_logService.open();
         m_configuration = configuration;
 
-        log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] active",
-                new Object[] {m_bundle.getBundleId()}, null, null, null );
+        log(LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] active",
+            new Object[] { m_bundle.getBundleId() }, null, null, null);
 
         // Get the Metadata-Location value from the manifest
-        String descriptorLocations = ( String ) m_bundle.getHeaders().get( "Service-Component" );
-        if ( descriptorLocations == null )
+        String descriptorLocations = (String) m_bundle.getHeaders().get(
+            "Service-Component");
+        if (descriptorLocations == null)
         {
-            throw new ComponentException( "Service-Component entry not found in the manifest" );
+            throw new ComponentException(
+                "Service-Component entry not found in the manifest");
         }
 
-        initialize( descriptorLocations );
+        initialize(descriptorLocations);
     }
 
-
     /**
      * Gets the MetaData location, parses the meta data and requests the processing
      * of binder instances
@@ -131,37 +279,38 @@
      *
      * @throws IllegalStateException If the bundle has already been uninstalled.
      */
-    private void initialize( String descriptorLocations )
+    private void initialize(String descriptorLocations)
     {
-        log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] descriptor locations {1}",
-                new Object[] {m_bundle.getBundleId(), descriptorLocations}, null, null, null );
+        log(LogService.LOG_DEBUG,
+            "BundleComponentActivator : Bundle [{0}] descriptor locations {1}",
+            new Object[] { m_bundle.getBundleId(), descriptorLocations }, null, null,
+            null);
 
         // 112.4.1: The value of the the header is a comma separated list of XML entries within the Bundle
-        StringTokenizer st = new StringTokenizer( descriptorLocations, ", " );
+        StringTokenizer st = new StringTokenizer(descriptorLocations, ", ");
 
-        while ( st.hasMoreTokens() )
+        while (st.hasMoreTokens())
         {
             String descriptorLocation = st.nextToken();
 
-            URL[] descriptorURLs = findDescriptors( m_bundle, descriptorLocation );
-            if ( descriptorURLs.length == 0 )
+            URL[] descriptorURLs = findDescriptors(m_bundle, descriptorLocation);
+            if (descriptorURLs.length == 0)
             {
                 // 112.4.1 If an XML document specified by the header cannot be located in the bundle and its attached
                 // fragments, SCR must log an error message with the Log Service, if present, and continue.
-                log( LogService.LOG_ERROR, "Component descriptor entry ''{0}'' not found", new Object[]
-                    { descriptorLocation }, null, null, null );
+                log(LogService.LOG_ERROR, "Component descriptor entry ''{0}'' not found",
+                    new Object[] { descriptorLocation }, null, null, null);
                 continue;
             }
 
             // load from the descriptors
-            for ( URL descriptorURL : descriptorURLs )
+            for (URL descriptorURL : descriptorURLs)
             {
-                loadDescriptor( descriptorURL );
+                loadDescriptor(descriptorURL);
             }
         }
     }
 
-
     /**
      * Called outside the constructor so that the m_managers field is completely initialized.
      * A component might possibly start a thread to enable other components, which could access m_managers
@@ -169,21 +318,27 @@
     void initialEnable()
     {
         //enable all the enabled components
-        for ( ComponentHolder<?> componentHolder : m_managers )
+        for (ComponentHolder<?> componentHolder : m_managers)
         {
-            log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] May enable component holder {1}",
-                    new Object[] {m_bundle.getBundleId(), componentHolder.getComponentMetadata().getName()}, null, null, null );
+            log(LogService.LOG_DEBUG,
+                "BundleComponentActivator : Bundle [{0}] May enable component holder {1}",
+                new Object[] { m_bundle.getBundleId(),
+                        componentHolder.getComponentMetadata().getName() }, null, null,
+                null);
 
-            if ( componentHolder.getComponentMetadata().isEnabled() )
+            if (componentHolder.getComponentMetadata().isEnabled())
             {
-                log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] Enabling component holder {1}",
-                        new Object[] {m_bundle.getBundleId(), componentHolder.getComponentMetadata().getName()}, null, null, null );
+                log(LogService.LOG_DEBUG,
+                    "BundleComponentActivator : Bundle [{0}] Enabling component holder {1}",
+                    new Object[] { m_bundle.getBundleId(),
+                            componentHolder.getComponentMetadata().getName() }, null,
+                    null, null);
 
                 try
                 {
-                    componentHolder.enableComponents( false );
+                    componentHolder.enableComponents(false);
                 }
-                catch ( Throwable t )
+                catch (Throwable t)
                 {
                     // caught on unhandled RuntimeException or Error
                     // (e.g. ClassDefNotFoundError)
@@ -191,26 +346,30 @@
                     // make sure the component is properly disabled, just in case
                     try
                     {
-                        componentHolder.disableComponents( false );
+                        componentHolder.disableComponents(false);
                     }
-                    catch ( Throwable ignore )
+                    catch (Throwable ignore)
                     {
                     }
 
-                    log( LogService.LOG_ERROR,
+                    log(LogService.LOG_ERROR,
                         "BundleComponentActivator : Bundle [{0}] Unexpected failure enabling component holder {1}",
-                        new Object[] { m_bundle.getBundleId(), componentHolder.getComponentMetadata().getName() }, null, null, t );
+                        new Object[] { m_bundle.getBundleId(),
+                                componentHolder.getComponentMetadata().getName() }, null,
+                        null, t);
                 }
             }
             else
             {
-                log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] Will not enable component holder {1}",
-                        new Object[] {m_bundle.getBundleId(), componentHolder.getComponentMetadata().getName()}, null, null, null );
+                log(LogService.LOG_DEBUG,
+                    "BundleComponentActivator : Bundle [{0}] Will not enable component holder {1}",
+                    new Object[] { m_bundle.getBundleId(),
+                            componentHolder.getComponentMetadata().getName() }, null,
+                    null, null);
             }
         }
     }
 
-
     /**
      * Finds component descriptors based on descriptor location.
      *
@@ -218,21 +377,22 @@
      * @param descriptorLocation descriptor location
      * @return array of descriptors or empty array if none found
      */
-    static URL[] findDescriptors( final Bundle bundle, final String descriptorLocation )
+    static URL[] findDescriptors(final Bundle bundle, final String descriptorLocation)
     {
-        if ( bundle == null || descriptorLocation == null || descriptorLocation.trim().length() == 0 )
+        if (bundle == null || descriptorLocation == null
+            || descriptorLocation.trim().length() == 0)
         {
             return new URL[0];
         }
 
         // split pattern and path
-        final int lios = descriptorLocation.lastIndexOf( "/" );
+        final int lios = descriptorLocation.lastIndexOf("/");
         final String path;
         final String filePattern;
-        if ( lios > 0 )
+        if (lios > 0)
         {
-            path = descriptorLocation.substring( 0, lios );
-            filePattern = descriptorLocation.substring( lios + 1 );
+            path = descriptorLocation.substring(0, lios);
+            filePattern = descriptorLocation.substring(lios + 1);
         }
         else
         {
@@ -241,23 +401,22 @@
         }
 
         // find the entries
-        final Enumeration<URL> entries = bundle.findEntries( path, filePattern, false );
-        if ( entries == null || !entries.hasMoreElements() )
+        final Enumeration<URL> entries = bundle.findEntries(path, filePattern, false);
+        if (entries == null || !entries.hasMoreElements())
         {
             return new URL[0];
         }
 
         // create the result list
         List<URL> urls = new ArrayList<URL>();
-        while ( entries.hasMoreElements() )
+        while (entries.hasMoreElements())
         {
-            urls.add( entries.nextElement() );
+            urls.add(entries.nextElement());
         }
-        return urls.toArray( new URL[urls.size()] );
+        return urls.toArray(new URL[urls.size()]);
     }
 
-
-    private void loadDescriptor( final URL descriptorURL )
+    private void loadDescriptor(final URL descriptorURL)
     {
         // simple path for log messages
         final String descriptorLocation = descriptorURL.getPath();
@@ -267,117 +426,125 @@
         {
             stream = descriptorURL.openStream();
 
-            BufferedReader in = new BufferedReader( new InputStreamReader( stream, "UTF-8" ) );
-            XmlHandler handler = new XmlHandler( m_bundle, this, getConfiguration().isFactoryEnabled(), getConfiguration().keepInstances() );
+            BufferedReader in = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
+            XmlHandler handler = new XmlHandler(m_bundle, this,
+                getConfiguration().isFactoryEnabled(), getConfiguration().keepInstances());
             KXml2SAXParser parser;
 
-            parser = new KXml2SAXParser( in );
+            parser = new KXml2SAXParser(in);
 
-            parser.parseXML( handler );
+            parser.parseXML(handler);
 
             // 112.4.2 Component descriptors may contain a single, root component element
             // or one or more component elements embedded in a larger document
-            for ( Object o : handler.getComponentMetadataList() )
+            for (Object o : handler.getComponentMetadataList())
             {
-                ComponentMetadata metadata = ( ComponentMetadata ) o;
+                ComponentMetadata metadata = (ComponentMetadata) o;
                 ComponentRegistryKey key = null;
                 try
                 {
                     // check and reserve the component name (if not null)
-                    if ( metadata.getName() != null )
+                    if (metadata.getName() != null)
                     {
-                        key = m_componentRegistry.checkComponentName( m_bundle, metadata.getName() );
+                        key = m_componentRegistry.checkComponentName(m_bundle,
+                            metadata.getName());
                     }
 
                     // validate the component metadata
-                    metadata.validate( this );
+                    metadata.validate(this);
 
                     // Request creation of the component manager
-                    ComponentHolder<?> holder = m_componentRegistry.createComponentHolder( this, metadata );
+                    ComponentHolder<?> holder = m_componentRegistry.createComponentHolder(
+                        this, metadata);
 
                     // register the component after validation
-                    m_componentRegistry.registerComponentHolder( key, holder );
-                    m_managers.add( holder );
+                    m_componentRegistry.registerComponentHolder(key, holder);
+                    m_managers.add(holder);
 
-                    log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] ComponentHolder created for {1}",
-                            new Object[] {m_bundle.getBundleId(), metadata.getName()}, null, null, null );
+                    log(LogService.LOG_DEBUG,
+                        "BundleComponentActivator : Bundle [{0}] ComponentHolder created for {1}",
+                        new Object[] { m_bundle.getBundleId(), metadata.getName() },
+                        null, null, null);
 
                 }
-                catch ( Throwable t )
+                catch (Throwable t)
                 {
                     // There is a problem with this particular component, we'll log the error
                     // and proceed to the next one
-                    log( LogService.LOG_ERROR, "Cannot register Component", metadata, null, t );
+                    log(LogService.LOG_ERROR, "Cannot register Component", metadata,
+                        null, t);
 
                     // make sure the name is not reserved any more
-                    if ( key != null )
+                    if (key != null)
                     {
-                        m_componentRegistry.unregisterComponentHolder( key );
+                        m_componentRegistry.unregisterComponentHolder(key);
                     }
                 }
             }
         }
-        catch ( IOException ex )
+        catch (IOException ex)
         {
             // 112.4.1 If an XML document specified by the header cannot be located in the bundle and its attached
             // fragments, SCR must log an error message with the Log Service, if present, and continue.
 
-            log( LogService.LOG_ERROR, "Problem reading descriptor entry ''{0}''", new Object[]
-                { descriptorLocation }, null, null, ex );
+            log(LogService.LOG_ERROR, "Problem reading descriptor entry ''{0}''",
+                new Object[] { descriptorLocation }, null, null, ex);
         }
-        catch ( Exception ex )
+        catch (Exception ex)
         {
-            log( LogService.LOG_ERROR, "General problem with descriptor entry ''{0}''", new Object[]
-                { descriptorLocation }, null, null, ex );
+            log(LogService.LOG_ERROR, "General problem with descriptor entry ''{0}''",
+                new Object[] { descriptorLocation }, null, null, ex);
         }
         finally
         {
-            if ( stream != null )
+            if (stream != null)
             {
                 try
                 {
                     stream.close();
                 }
-                catch ( IOException ignore )
+                catch (IOException ignore)
                 {
                 }
             }
         }
     }
 
-
     /**
     * Dispose of this component activator instance and all the component
     * managers.
     */
-    void dispose( int reason )
+    void dispose(int reason)
     {
-        if ( m_active.compareAndSet( true, false ))
+        if (m_active.compareAndSet(true, false))
         {
-            log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] will destroy {1} instances", new Object[]
-                    { m_bundle.getBundleId(), m_managers.size() }, null, null, null );
+            log(LogService.LOG_DEBUG,
+                "BundleComponentActivator : Bundle [{0}] will destroy {1} instances",
+                new Object[] { m_bundle.getBundleId(), m_managers.size() }, null, null,
+                null);
 
-            for (ComponentHolder<?> holder: m_managers )
+            for (ComponentHolder<?> holder : m_managers)
             {
                 try
                 {
-                    holder.disposeComponents( reason );
+                    holder.disposeComponents(reason);
                 }
-                catch ( Exception e )
+                catch (Exception e)
                 {
-                    log( LogService.LOG_ERROR, "BundleComponentActivator : Exception invalidating", holder
-                            .getComponentMetadata(), null, e );
+                    log(LogService.LOG_ERROR,
+                        "BundleComponentActivator : Exception invalidating",
+                        holder.getComponentMetadata(), null, e);
                 }
                 finally
                 {
-                    m_componentRegistry.unregisterComponentHolder( m_bundle, holder.getComponentMetadata()
-                            .getName() );
+                    m_componentRegistry.unregisterComponentHolder(m_bundle,
+                        holder.getComponentMetadata().getName());
                 }
 
             }
 
-            log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] STOPPED", new Object[]
-                    {m_bundle.getBundleId()}, null, null, null );
+            log(LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [{0}] STOPPED",
+                new Object[] { m_bundle.getBundleId() }, null, null, null);
 
             m_logService.close();
             m_closeLatch.countDown();
@@ -388,7 +555,7 @@
             {
                 m_closeLatch.await(m_configuration.lockTimeout(), TimeUnit.MILLISECONDS);
             }
-            catch ( InterruptedException e )
+            catch (InterruptedException e)
             {
                 //ignore interruption during concurrent shutdown.
             }
@@ -396,7 +563,6 @@
 
     }
 
-
     /**
      * Returns <true> if this instance is active, that is if components
      * may be activated for this component. The active flag is set early
@@ -409,7 +575,6 @@
         return m_active.get();
     }
 
-
     /**
     * Returns the BundleContext
     *
@@ -420,13 +585,11 @@
         return m_context;
     }
 
-
     public ScrConfiguration getConfiguration()
     {
         return m_configuration;
     }
 
-
     /**
      * Implements the <code>ComponentContext.enableComponent(String)</code>
      * method by first finding the component(s) for the <code>name</code> and
@@ -436,24 +599,25 @@
      * @param name The name of the component to enable or <code>null</code> to
      *      enable all components.
      */
-    public void enableComponent( final String name )
+    public void enableComponent(final String name)
     {
-        final List<ComponentHolder<?>> holder = getSelectedComponents( name );
-        for ( ComponentHolder<?> aHolder : holder )
+        final List<ComponentHolder<?>> holder = getSelectedComponents(name);
+        for (ComponentHolder<?> aHolder : holder)
         {
             try
             {
-                log( LogService.LOG_DEBUG, "Enabling Component", aHolder.getComponentMetadata(), null, null );
-                aHolder.enableComponents( true );
+                log(LogService.LOG_DEBUG, "Enabling Component",
+                    aHolder.getComponentMetadata(), null, null);
+                aHolder.enableComponents(true);
             }
-            catch ( Throwable t )
+            catch (Throwable t)
             {
-                log( LogService.LOG_ERROR, "Cannot enable component", aHolder.getComponentMetadata(), null, t );
+                log(LogService.LOG_ERROR, "Cannot enable component",
+                    aHolder.getComponentMetadata(), null, t);
             }
         }
     }
 
-
     /**
      * Implements the <code>ComponentContext.disableComponent(String)</code>
      * method by first finding the component(s) for the <code>name</code> and
@@ -463,24 +627,25 @@
      * @param name The name of the component to disable or <code>null</code> to
      *      disable all components.
      */
-    public void disableComponent( final String name )
+    public void disableComponent(final String name)
     {
-        final List<ComponentHolder<?>> holder = getSelectedComponents( name );
-        for ( ComponentHolder<?> aHolder : holder )
+        final List<ComponentHolder<?>> holder = getSelectedComponents(name);
+        for (ComponentHolder<?> aHolder : holder)
         {
             try
             {
-                log( LogService.LOG_DEBUG, "Disabling Component", aHolder.getComponentMetadata(), null, null );
-                aHolder.disableComponents( true );
+                log(LogService.LOG_DEBUG, "Disabling Component",
+                    aHolder.getComponentMetadata(), null, null);
+                aHolder.disableComponents(true);
             }
-            catch ( Throwable t )
+            catch (Throwable t)
             {
-                log( LogService.LOG_ERROR, "Cannot disable component", aHolder.getComponentMetadata(), null, t );
+                log(LogService.LOG_ERROR, "Cannot disable component",
+                    aHolder.getComponentMetadata(), null, t);
             }
         }
     }
 
-
     /**
      * Returns an array of {@link ComponentHolder} instances which match the
      * <code>name</code>. If the <code>name</code> is <code>null</code> an
@@ -496,32 +661,34 @@
      *      to the <code>name</code> parameter or <code>null</code> if no
      *      component manager with the given name is currently registered.
      */
-    private List<ComponentHolder<?>> getSelectedComponents( String name )
+    private List<ComponentHolder<?>> getSelectedComponents(String name)
     {
         // if all components are selected
-        if ( name == null )
+        if (name == null)
         {
             return m_managers;
         }
 
-        ComponentHolder<?> componentHolder = m_componentRegistry.getComponentHolder( m_bundle, name );
+        ComponentHolder<?> componentHolder = m_componentRegistry.getComponentHolder(
+            m_bundle, name);
         if (componentHolder != null)
         {
-            return Collections.<ComponentHolder<?>>singletonList( componentHolder );
+            return Collections.<ComponentHolder<?>> singletonList(componentHolder);
         }
 
         // if the component is not known
         return Collections.emptyList();
     }
 
-
     //---------- Component ID support
 
-    public long registerComponentId(AbstractComponentManager<?> componentManager) {
+    public long registerComponentId(AbstractComponentManager<?> componentManager)
+    {
         return m_componentRegistry.registerComponentId(componentManager);
     }
 
-    public void unregisterComponentId(AbstractComponentManager<?> componentManager) {
+    public void unregisterComponentId(AbstractComponentManager<?> componentManager)
+    {
         m_componentRegistry.unregisterComponentId(componentManager.getId());
     }
 
@@ -534,48 +701,50 @@
      *
      * @param task The component task to execute
      */
-    public void schedule( Runnable task )
+    public void schedule(Runnable task)
     {
-        if ( isActive() )
+        if (isActive())
         {
             ComponentActorThread cat = m_componentActor;
-            if ( cat != null )
+            if (cat != null)
             {
-                cat.schedule( task );
+                cat.schedule(task);
             }
             else
             {
-                log( LogService.LOG_DEBUG, "Component Actor Thread not running, calling synchronously", null, null, null );
+                log(LogService.LOG_DEBUG,
+                    "Component Actor Thread not running, calling synchronously", null,
+                    null, null);
                 try
                 {
-                    synchronized ( this )
+                    synchronized (this)
                     {
                         task.run();
                     }
                 }
-                catch ( Throwable t )
+                catch (Throwable t)
                 {
-                    log( LogService.LOG_WARNING, "Unexpected problem executing task", null, null, t );
+                    log(LogService.LOG_WARNING, "Unexpected problem executing task",
+                        null, null, t);
                 }
             }
         }
         else
         {
-            log( LogService.LOG_WARNING, "BundleComponentActivator is not active; not scheduling {0}", new Object[]
-                { task }, null, null, null );
+            log(LogService.LOG_WARNING,
+                "BundleComponentActivator is not active; not scheduling {0}",
+                new Object[] { task }, null, null, null);
         }
     }
 
-
     /**
      * Returns <code>true</code> if logging for the given level is enabled.
      */
-    public boolean isLogEnabled( int level )
+    public boolean isLogEnabled(int level)
     {
         return m_configuration.getLogLevel() >= level;
     }
 
-
     /**
      * Method to actually emit the log message. If the LogService is available,
      * the message will be logged through the LogService. Otherwise the message
@@ -585,20 +754,20 @@
      * @param pattern The <code>java.text.MessageFormat</code> message format
      *      string for preparing the message
      * @param arguments The format arguments for the <code>pattern</code>
- *      string.
+    *      string.
      * @param componentId
      * @param ex An optional <code>Throwable</code> whose stack trace is written,
      */
-    public void log( int level, String pattern, Object[] arguments, ComponentMetadata metadata, Long componentId, Throwable ex )
+    public void log(int level, String pattern, Object[] arguments,
+        ComponentMetadata metadata, Long componentId, Throwable ex)
     {
-        if ( isLogEnabled( level ) )
+        if (isLogEnabled(level))
         {
-            final String message = MessageFormat.format( pattern, arguments );
-            log( level, message, metadata, componentId, ex );
+            final String message = MessageFormat.format(pattern, arguments);
+            log(level, message, metadata, componentId, ex);
         }
     }
 
-
     /**
      * Method to actually emit the log message. If the LogService is available,
      * the message will be logged through the LogService. Otherwise the message
@@ -609,16 +778,18 @@
      * @param componentId
      * @param ex An optional <code>Throwable</code> whose stack trace is written,
      */
-    public void log( int level, String message, ComponentMetadata metadata, Long componentId, Throwable ex )
+    public void log(int level, String message, ComponentMetadata metadata,
+        Long componentId, Throwable ex)
     {
-        if ( isLogEnabled( level ) )
+        if (isLogEnabled(level))
         {
             // prepend the metadata name to the message
-            if ( metadata != null )
+            if (metadata != null)
             {
-                if ( componentId != null )
+                if (componentId != null)
                 {
-                    message = "[" + metadata.getName() + "(" + componentId + ")] " + message;
+                    message = "[" + metadata.getName() + "(" + componentId + ")] "
+                        + message;
                 }
                 else
                 {
@@ -627,33 +798,35 @@
             }
 
             ServiceTracker<LogService, LogService> logService = m_logService;
-            if ( logService != null )
+            if (logService != null)
             {
                 LogService logger = logService.getService();
-                if ( logger == null )
+                if (logger == null)
                 {
-                    Activator.log( level, m_bundle, message, ex );
+                    Activator.log(level, m_bundle, message, ex);
                 }
                 else
                 {
-                    logger.log( level, message, ex );
+                    logger.log(level, message, ex);
                 }
             }
             else
             {
                 // BCA has been disposed off, bundle context is probably invalid. Try to log something.
-                Activator.log( level, null, message, ex );
+                Activator.log(level, null, message, ex);
             }
         }
     }
 
-    public void missingServicePresent( ServiceReference<?> serviceReference )
+    public void missingServicePresent(ServiceReference<?> serviceReference)
     {
-        m_componentRegistry.missingServicePresent( serviceReference, m_componentActor );
+        m_componentRegistry.missingServicePresent(serviceReference, m_componentActor);
     }
 
-    public <T> void registerMissingDependency( DependencyManager<?, T> dependencyManager, ServiceReference<T> serviceReference, int trackingCount )
+    public <T> void registerMissingDependency(DependencyManager<?, T> dependencyManager,
+        ServiceReference<T> serviceReference, int trackingCount)
     {
-        m_componentRegistry.registerMissingDependency(dependencyManager, serviceReference, trackingCount );
+        m_componentRegistry.registerMissingDependency(dependencyManager,
+            serviceReference, 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 8500fe5..a668e1d 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
@@ -74,14 +74,11 @@
     private volatile ReferenceMethods m_bindMethods;
 
     //reset on filter change
-    private volatile ServiceTracker<T, RefPair<S, T>> m_tracker;
+    private volatile ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> m_tracker;
 
     // the target service filter string
     private volatile String m_target;
 
-    // the target service filter
-    private volatile Filter m_targetFilter;
-
     private volatile int m_minCardinality;
 
     /**
@@ -127,7 +124,7 @@
        m_bindMethods = bindMethods;
     }
 
-    private interface Customizer<S, T> extends ServiceTrackerCustomizer<T, RefPair<S, T>>
+    private interface Customizer<S, T> extends ServiceTrackerCustomizer<T, RefPair<S, T>, ExtendedServiceEvent>
     {
         /**
          * attempt to obtain the services from the tracked service references that will be used in inital bind calls
@@ -143,7 +140,7 @@
 
         boolean isSatisfied();
 
-        void setTracker( ServiceTracker<T, RefPair<S, T>> tracker );
+        void setTracker( ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker );
 
         void setTrackerOpened();
 
@@ -158,7 +155,7 @@
 
         private volatile Map<ServiceReference<T>, RefPair<S, T>> previousRefMap = EMPTY_REF_MAP;
 
-        public void setTracker( ServiceTracker<T, RefPair<S, T>> tracker )
+        public void setTracker( ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker )
         {
             m_tracker = tracker;
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracker reset (closed)", new Object[] {getName()}, null );
@@ -167,7 +164,7 @@
 
         public boolean isSatisfied()
         {
-            ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
+            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
             if ( tracker == null)
             {
                 return false;
@@ -175,7 +172,7 @@
             return cardinalitySatisfied( tracker.getServiceCount() );
         }
 
-        protected ServiceTracker<T, RefPair<S, T>> getTracker()
+        protected ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> getTracker()
         {
             return m_tracker;
         }
@@ -202,7 +199,7 @@
 
         protected void deactivateTracker()
         {
-            ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
+            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
             if ( tracker != null )
             {
                 tracker.deactivate();
@@ -256,7 +253,7 @@
             return refPair;
         }
 
-        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount, ExtendedServiceEvent event )
         {
             if ( cardinalityJustSatisfied( serviceCount ) )
             {
@@ -264,11 +261,11 @@
             }
         }
 
-        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
         {
         }
 
-        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
         {
             refPair.markDeleted();
             if ( !cardinalitySatisfied( getTracker().getServiceCount() ) )
@@ -310,7 +307,7 @@
             return refPair;
         }
 
-        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleDynamic added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
         	boolean tracked = false;
@@ -344,7 +341,7 @@
 			}
         }
 
-        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleDynamic modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             if (isActive())
@@ -355,7 +352,7 @@
             tracked( trackingCount );
         }
 
-        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleDynamic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             refPair.markDeleted();
@@ -415,7 +412,7 @@
         {
             if ( lastRefPair == null )
             {
-                ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
+                ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
                 if (tracker == null) {
                     trackingCount.set( lastRefPairTrackingCount );
                     return Collections.emptyList();
@@ -439,7 +436,7 @@
             return refPair;
         }
 
-        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             tracked( trackingCount );
@@ -449,7 +446,11 @@
                         "Dependency Manager: Static dependency on {0}/{1} is broken", new Object[]
                         {getName(), m_dependencyMetadata.getInterface()}, null );
                 m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false );
-                m_componentManager.activateInternal( );
+                //event may be null during initial operations.
+                if (event != null)
+                {
+                    event.addComponentManager(m_componentManager);
+                }
 
             }
             else if ( isTrackerOpened() && cardinalityJustSatisfied( serviceCount ) )
@@ -459,7 +460,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<S, T> refPair, int trackingCount )
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             boolean reactivate = false;
@@ -471,12 +472,15 @@
             if ( reactivate )
             {
                 m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false );
-                m_componentManager.activateInternal( );
+                if (event != null)
+                {
+                    event.addComponentManager(m_componentManager);
+                }
             }
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy modified {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             refPair.markDeleted();
@@ -489,7 +493,10 @@
                         {getName(), m_dependencyMetadata.getInterface()}, null );
                 m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false );
                 //try to reactivate after ref is no longer tracked.
-                m_componentManager.activateInternal( );
+                if (event != null)
+                {
+                    event.addComponentManager(m_componentManager);
+                }
             }
             else if ( !cardinalitySatisfied( getTracker().getServiceCount() ) ) //may be called from an old tracker, so getTracker() may give a different answer
             {
@@ -507,7 +514,7 @@
         {
             int serviceCount = 0;
             AtomicInteger trackingCount = new AtomicInteger( );
-            final ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
+            final ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
             SortedMap<ServiceReference<T>, RefPair<S, T>> tracked = tracker.getTracked( cardinalitySatisfied( tracker.getServiceCount() ), trackingCount );
             for (RefPair<S, T> refPair: tracked.values())
             {
@@ -536,7 +543,7 @@
 
         public Collection<RefPair<S, T>> getRefs( AtomicInteger trackingCount )
         {
-            ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
+            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
             if (tracker == null) {
                 return Collections.emptyList();
             }
@@ -555,7 +562,7 @@
             return refPair;
         }
 
-        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             tracked( trackingCount );
@@ -566,7 +573,7 @@
             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<S, T> refPair, int trackingCount )
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             boolean reactivate = false;
@@ -579,12 +586,15 @@
             if ( reactivate )
             {
                 m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false );
-                m_componentManager.activateInternal( );
+                if (event != null)
+                {
+                    event.addComponentManager(m_componentManager);
+                }
             }
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant modified {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             refPair.markDeleted();
@@ -601,7 +611,10 @@
                     m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false );
 
                     // FELIX-2368: immediately try to reactivate
-                    m_componentManager.activateInternal( );
+                    if (event != null)
+                    {
+                        event.addComponentManager(m_componentManager);
+                    }
 
                 }
             }
@@ -695,7 +708,7 @@
             return refPair;
         }
 
-        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             boolean tracked = false;
@@ -744,7 +757,7 @@
             }
         }
 
-        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             boolean invokeUpdated;
@@ -761,7 +774,7 @@
             tracked( trackingCount );
         }
 
-        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             refPair.markDeleted();
@@ -907,7 +920,7 @@
             return refPair;
         }
 
-        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, int serviceCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic added {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             this.trackingCount = trackingCount;
@@ -922,7 +935,10 @@
                 if ( reactivate )
                 {
                     m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false );
-                    m_componentManager.activateInternal( );
+                    if (event != null)
+                    {
+                        event.addComponentManager(m_componentManager);
+                    }
                 }
                 else
                 {
@@ -940,7 +956,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<S, T> refPair, int trackingCount )
+        public void modifiedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             boolean invokeUpdated;
@@ -966,12 +982,15 @@
                         this.refPair = null;
                     }
                 }
-                m_componentManager.activateInternal( );
+                if (event != null)
+                {
+                    event.addComponentManager(m_componentManager);
+                }
             }
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic modified {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount )
+        public void removedService( ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount, ExtendedServiceEvent event )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             refPair.markDeleted();
@@ -996,7 +1015,10 @@
                         this.refPair = null;
                     }
                 }
-                m_componentManager.activateInternal( );
+                if (event != null)
+                {
+                    event.addComponentManager(m_componentManager);
+                }
             }
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic removed {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
@@ -1032,7 +1054,7 @@
 
         public void close()
         {
-            ServiceTracker<T, RefPair<S, T>> tracker = getTracker();
+            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
             if ( tracker != null )
             {
                 RefPair<S, T> ref;
@@ -1089,7 +1111,7 @@
             return isOptional();
         }
 
-        public void setTracker( ServiceTracker<T, RefPair<S, T>> tRefPairServiceTracker )
+        public void setTracker( ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tRefPairServiceTracker )
         {
         }
 
@@ -1106,15 +1128,15 @@
             return null;
         }
 
-        public void addedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount, int serviceCount )
+        public void addedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount, int serviceCount, ExtendedServiceEvent event )
         {
         }
 
-        public void modifiedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount )
+        public void modifiedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount, ExtendedServiceEvent event )
         {
         }
 
-        public void removedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount )
+        public void removedService( ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount, ExtendedServiceEvent event )
         {
         }
     }
@@ -1316,7 +1338,7 @@
      */
     private RefPair<S, T> getRefPair( ServiceReference<T> serviceReference )
     {
-        final ServiceTracker<T, RefPair<S, T>> tracker = m_tracker;
+        final ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = m_tracker;
         if ( tracker != null )
         {
             AtomicInteger trackingCount = new AtomicInteger( );
@@ -1873,6 +1895,8 @@
         return minimumCardinality;
     }
 
+    private static final String OBJECTCLASS_CLAUSE = "(" + Constants.OBJECTCLASS + "=";
+    private static final String PROTOTYPE_SCOPE_CLAUSE = "(" + Constants.SERVICE_SCOPE + "=" + Constants.SCOPE_PROTOTYPE + ")";
 
     /**
      * Sets the target filter of this dependency to the new filter value. If the
@@ -1904,41 +1928,45 @@
         }
         m_target = target;
         final boolean multipleExpr = m_target != null || m_dependencyMetadata.getScope() == ReferenceScope.prototype_required;
-        final StringBuilder filterSB = new StringBuilder();
+        final boolean allExpr = m_target != null && m_dependencyMetadata.getScope() == ReferenceScope.prototype_required;
+        final StringBuilder initialReferenceFilterSB = new StringBuilder();
         if (multipleExpr )
         {
-            filterSB.append("(&");
+            initialReferenceFilterSB.append("(&");
         }
         // "(" + Constants.OBJECTCLASS + "=" + m_dependencyMetadata.getInterface() + ")"
-        filterSB.append('(');
-        filterSB.append(Constants.OBJECTCLASS);
-        filterSB.append('=');
-        filterSB.append(m_dependencyMetadata.getInterface());
-        filterSB.append(')');
+        String classFilterString = OBJECTCLASS_CLAUSE + m_dependencyMetadata.getInterface() + ")";
+        initialReferenceFilterSB.append(classFilterString);
 
         // if reference scope is prototype_required, we simply add
-        // service.scope=prototype to the filter
+        // (service.scope=prototype) to the filter
         if ( m_dependencyMetadata.getScope() == ReferenceScope.prototype_required )
         {
-            filterSB.append('(');
-            filterSB.append(Constants.SERVICE_SCOPE);
-            filterSB.append('=');
-            filterSB.append(Constants.SCOPE_PROTOTYPE);
-            filterSB.append(')');
+            initialReferenceFilterSB.append(PROTOTYPE_SCOPE_CLAUSE);
         }
 
         // append target
         if ( m_target != null )
         {
-            filterSB.append(m_target);
+            initialReferenceFilterSB.append(m_target);
         }
         if (multipleExpr )
         {
-            filterSB.append(')');
+            initialReferenceFilterSB.append(')');
         }
-        String filterString = filterSB.toString();
+        String initialReferenceFilterString= initialReferenceFilterSB.toString();
+        String eventFilterString;
+        if (allExpr)
+        {
+            StringBuilder sb = new StringBuilder("(&").append(PROTOTYPE_SCOPE_CLAUSE).append(m_target).append(")");
+            eventFilterString = sb.toString();
+        }
+        else 
+        {
+            eventFilterString = m_target;
+        }
 
-        final ServiceTracker<T, RefPair<S, T>> oldTracker = m_tracker;
+        final ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> oldTracker = m_tracker;
         AtomicInteger trackingCount = new AtomicInteger();
         SortedMap<ServiceReference<T>, RefPair<S, T>> refMap = unregisterServiceListener( trackingCount );
         if ( trackingCount.get() != -1 )
@@ -1949,29 +1977,34 @@
         m_componentManager.log( LogService.LOG_DEBUG, "Setting target property for dependency {0} to {1}", new Object[]
                 {getName(), target}, null );
         BundleContext bundleContext = m_componentManager.getBundleContext();
+        Filter eventFilter = null;
         if ( bundleContext != null )
         {
-            try
+            if ( eventFilterString != null )
             {
-                m_targetFilter = bundleContext.createFilter( filterString );
-            }
-            catch ( InvalidSyntaxException ise )
-            {
-                m_componentManager.log( LogService.LOG_ERROR, "Invalid syntax in target property for dependency {0} to {1}", new Object[]
-                        {getName(), target}, null );
-
-                //create a filter that will never be satisfied
-                filterString = "(component.id=-1)";
                 try
                 {
-                    m_targetFilter = bundleContext.createFilter( filterString );
+                    eventFilter = bundleContext.createFilter(eventFilterString);
                 }
-                catch ( InvalidSyntaxException e )
+                catch (InvalidSyntaxException ise)
                 {
-                    //this should not happen
-                    return;
-                }
+                    m_componentManager.log(LogService.LOG_ERROR,
+                        "Invalid syntax in target property for dependency {0} to {1}",
+                        new Object[] { getName(), target }, null);
 
+                    //create a filter that will never be satisfied
+                    eventFilterString = "(component.id=-1)";
+                    try
+                    {
+                        eventFilter = bundleContext.createFilter(eventFilterString);
+                    }
+                    catch (InvalidSyntaxException e)
+                    {
+                        //this should not happen
+                        return;
+                    }
+
+                }
             }
         }
         else
@@ -1983,9 +2016,15 @@
 
         m_customizer.setPreviousRefMap( refMap );
         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<S, T>> tracker = new ServiceTracker<T, RefPair<S, T>>( bundleContext, m_targetFilter, m_customizer, initialActive );
+        m_componentManager.log( LogService.LOG_DEBUG, "New service tracker for {0}, initial active: {1}, previous references: {2}, classFilter: {3}, eventFilter {4}, initialReferenceFilter {5}", new Object[]
+                {getName(), initialActive, refMap, classFilterString, eventFilter, initialReferenceFilterString}, null );
+        ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = new ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent>( bundleContext, 
+            m_customizer, 
+            initialActive, 
+            m_componentManager.getActivator(),
+            eventFilter,
+            classFilterString,
+            initialReferenceFilterString);
         m_customizer.setTracker( tracker );
         //set minimum cardinality
         m_minCardinality = minimumCardinality;
@@ -2048,7 +2087,7 @@
     SortedMap<ServiceReference<T>, RefPair<S, T>> unregisterServiceListener( AtomicInteger trackingCount )
     {
         SortedMap<ServiceReference<T>, RefPair<S, T>> refMap;
-        ServiceTracker<T, RefPair<S, T>> tracker = m_tracker;
+        ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = m_tracker;
         if ( tracker != null )
         {
             refMap = tracker.close( trackingCount );
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceEvent.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceEvent.java
new file mode 100644
index 0000000..f06345a
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceEvent.java
@@ -0,0 +1,63 @@
+/*
+ * 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.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+
+public class ExtendedServiceEvent extends ServiceEvent
+{
+    private List<AbstractComponentManager<?>> managers;
+
+    public ExtendedServiceEvent(ServiceEvent source)
+    {
+        super(source.getType(), source.getServiceReference());
+    }
+
+    public ExtendedServiceEvent(int type, ServiceReference ref)
+    {
+        super(type, ref);
+    }
+
+    public void addComponentManager(AbstractComponentManager<?> manager)
+    {
+        if (managers == null)
+            managers = new ArrayList<AbstractComponentManager<?>>();
+        managers.add(manager);
+    }
+
+    public List<AbstractComponentManager<?>> getManagers()
+    {
+        return managers == null ? Collections.<AbstractComponentManager<?>> emptyList()
+            : managers;
+    }
+
+    public void activateManagers()
+    {
+        for (AbstractComponentManager<?> manager : getManagers())
+        {
+            manager.activateInternal();
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceListener.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceListener.java
new file mode 100644
index 0000000..55b31b3
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceListener.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.osgi.framework.ServiceEvent;
+
+public interface ExtendedServiceListener<U extends ServiceEvent>
+{
+    void serviceChanged(U event);
+}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceListenerContext.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceListenerContext.java
new file mode 100644
index 0000000..3583ea2
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ExtendedServiceListenerContext.java
@@ -0,0 +1,32 @@
+/*
+ * 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 org.osgi.framework.Filter;
+import org.osgi.framework.ServiceEvent;
+
+public interface ExtendedServiceListenerContext<U extends ServiceEvent>
+{
+
+    void addServiceListener(String className, Filter filter,
+        ExtendedServiceListener<U> listener);
+
+    void removeServiceListener(String className, Filter filter,
+        ExtendedServiceListener<U> listener);
+}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java
index ab37e62..5a811a4 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTracker.java
@@ -27,13 +27,11 @@
 import java.util.TreeMap;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import org.osgi.framework.AllServiceListener;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServiceReference;
 
 /**
@@ -72,7 +70,7 @@
  * @param <S>
  * @param <T>
  */
-public class ServiceTracker<S, T> {
+public class ServiceTracker<S, T, U extends ServiceEvent> {
 	/* set this to true to compile in debug messages */
 	static final boolean					DEBUG	= false;
 	/**
@@ -85,27 +83,18 @@
 	 * 
 	 * @since 1.1
 	 */
-	protected final Filter					filter;
+	protected final Filter					eventFilter;
     /**
      * The {@code ServiceTrackerCustomizer} for this tracker.
      */
-    final ServiceTrackerCustomizer<S, T> customizer;
+    final ServiceTrackerCustomizer<S, T, U> customizer;
 	/**
 	 * Filter string for use when adding the ServiceListener. If this field is
 	 * set, then certain optimizations can be taken since we don't have a user
 	 * supplied filter.
 	 */
-	final String							listenerFilter;
-	/**
-	 * Class name to be tracked. If this field is set, then we are tracking by
-	 * class name.
-	 */
-	private final String					trackClass;
-	/**
-	 * Reference to be tracked. If this field is set, then we are tracking a
-	 * single ServiceReference.
-	 */
-	private final ServiceReference<S>		trackReference;
+	final String							initialReferenceFilterString;
+
 	/**
 	 * Tracked services: {@code ServiceReference} -> customized Object and
 	 * {@code ServiceListener} object
@@ -129,93 +118,9 @@
 		return tracked;
 	}
 
-	/**
-	 * Cached ServiceReference for getServiceReference.
-	 * 
-	 * This field is volatile since it is accessed by multiple threads.
-	 */
-	private volatile ServiceReference<S>	cachedReference;
-	/**
-	 * Cached service object for getService.
-	 * 
-	 * This field is volatile since it is accessed by multiple threads.
-	 */
-	private volatile T						cachedService;
+    private ExtendedServiceListenerContext<U> extendedServiceListenerContext;
+    private String classFilterString;
 
-	/**
-	 * Create a {@code ServiceTracker} on the specified {@code ServiceReference}
-	 * .
-	 * 
-	 * <p>
-	 * The service referenced by the specified {@code ServiceReference} will be
-	 * tracked by this {@code ServiceTracker}.
-	 * 
-	 * @param context The {@code BundleContext} against which the tracking is
-	 *        done.
-	 * @param reference The {@code ServiceReference} for the service to be
-	 *        tracked.
-	 * @param customizer The customizer object to call when services are added,
-	 *        modified, or removed in this {@code ServiceTracker}. If customizer
-	 *        is {@code null}, then this {@code ServiceTracker} will be used as
-	 *        the {@code ServiceTrackerCustomizer} and this
-	 *        {@code ServiceTracker} will call the
-	 *        {@code ServiceTrackerCustomizer} methods on itself.
-	 */
-	public ServiceTracker(final BundleContext context, final ServiceReference<S> reference, final ServiceTrackerCustomizer<S, T> customizer) {
-		this.context = context;
-		this.trackReference = reference;
-		this.trackClass = null;
-		this.customizer = customizer;
-		this.listenerFilter = "(" + Constants.SERVICE_ID + "=" + reference.getProperty(Constants.SERVICE_ID).toString() + ")";
-		try {
-			this.filter = context.createFilter(listenerFilter);
-		} catch (InvalidSyntaxException e) {
-			/*
-			 * we could only get this exception if the ServiceReference was
-			 * invalid
-			 */
-			IllegalArgumentException iae = new IllegalArgumentException("unexpected InvalidSyntaxException: " + e.getMessage());
-			iae.initCause(e);
-			throw iae;
-		}
-	}
-
-	/**
-	 * Create a {@code ServiceTracker} on the specified class name.
-	 * 
-	 * <p>
-	 * Services registered under the specified class name will be tracked by
-	 * this {@code ServiceTracker}.
-	 * 
-	 * @param context The {@code BundleContext} against which the tracking is
-	 *        done.
-	 * @param clazz The class name of the services to be tracked.
-	 * @param customizer The customizer object to call when services are added,
-	 *        modified, or removed in this {@code ServiceTracker}. If customizer
-	 *        is {@code null}, then this {@code ServiceTracker} will be used as
-	 *        the {@code ServiceTrackerCustomizer} and this
-	 *        {@code ServiceTracker} will call the
-	 *        {@code ServiceTrackerCustomizer} methods on itself.
-	 */
-	public ServiceTracker(final BundleContext context, final String clazz, final ServiceTrackerCustomizer<S, T> customizer) {
-		this.context = context;
-		this.trackReference = null;
-		this.trackClass = clazz;
-		this.customizer = customizer;
-		// we call clazz.toString to verify clazz is non-null!
-		this.listenerFilter = "(" + Constants.OBJECTCLASS + "=" + clazz + ")";
-		try {
-			this.filter = context.createFilter(listenerFilter);
-		} catch (InvalidSyntaxException e) {
-			/*
-			 * we could only get this exception if the clazz argument was
-			 * malformed
-			 */
-			IllegalArgumentException iae = new IllegalArgumentException("unexpected InvalidSyntaxException: " + e.getMessage());
-			iae.initCause(e);
-			throw iae;
-		}
-	}
 
 	/**
 	 * Create a {@code ServiceTracker} on the specified {@code Filter} object.
@@ -226,51 +131,38 @@
 	 * 
 	 * @param context The {@code BundleContext} against which the tracking is
 	 *        done.
-	 * @param filter The {@code Filter} to select the services to be tracked.
 	 * @param customizer The customizer object to call when services are added,
 	 *        modified, or removed in this {@code ServiceTracker}. If customizer
 	 *        is null, then this {@code ServiceTracker} will be used as the
 	 *        {@code ServiceTrackerCustomizer} and this {@code ServiceTracker}
 	 *        will call the {@code ServiceTrackerCustomizer} methods on itself.
 	 * @param initialActive Initial active state of the tracker.
+	 * @param bundleComponentActivator TODO
+	 * @param eventFilter The {@code Filter} to select the services to be tracked.
+	 * @param classFilterString TODO
+	 * @param initialReferenceFilterString TODO
 	 * @since 1.1
 	 */
-	public ServiceTracker(final BundleContext context, final Filter filter, final ServiceTrackerCustomizer<S, T> customizer, boolean initialActive) {
+	public ServiceTracker(final BundleContext context,
+	    final ServiceTrackerCustomizer<S, T, U> customizer,
+	    boolean initialActive,
+	    ExtendedServiceListenerContext<U> bundleComponentActivator,
+	    final Filter eventFilter,
+	    final String classFilterString,
+	    final String initialReferenceFilterString) {
+        if ((context == null)) {
+            /*
+             * we throw a NPE here to be consistent with the other constructors
+             */
+            throw new NullPointerException( "BundleContext");
+        }
 		this.context = context;
-		this.trackReference = null;
-		this.trackClass = null;
-		this.listenerFilter = filter.toString();
-		this.filter = filter;
+		this.initialReferenceFilterString = initialReferenceFilterString;
+		this.eventFilter = eventFilter;
 		this.customizer = customizer;
 		this.active = initialActive;
-		if ((context == null)) {
-			/*
-			 * we throw a NPE here to be consistent with the other constructors
-			 */
-			throw new NullPointerException( "BundleContext");
-		}
-	}
-
-	/**
-	 * Create a {@code ServiceTracker} on the specified class.
-	 * 
-	 * <p>
-	 * Services registered under the name of the specified class will be tracked
-	 * by this {@code ServiceTracker}.
-	 * 
-	 * @param context The {@code BundleContext} against which the tracking is
-	 *        done.
-	 * @param clazz The class of the services to be tracked.
-	 * @param customizer The customizer object to call when services are added,
-	 *        modified, or removed in this {@code ServiceTracker}. If customizer
-	 *        is {@code null}, then this {@code ServiceTracker} will be used as
-	 *        the {@code ServiceTrackerCustomizer} and this
-	 *        {@code ServiceTracker} will call the
-	 *        {@code ServiceTrackerCustomizer} methods on itself.
-	 * @since 1.5
-	 */
-	public ServiceTracker(final BundleContext context, final Class<S> clazz, final ServiceTrackerCustomizer<S, T> customizer) {
-		this(context, clazz.getName(), customizer);
+		this.extendedServiceListenerContext = bundleComponentActivator;
+		this.classFilterString = classFilterString;
 	}
 
 	/**
@@ -315,25 +207,13 @@
 				return;
 			}
 			if (DEBUG) {
-				System.out.println("ServiceTracker.open: " + filter);
+				System.out.println("ServiceTracker.open: " + eventFilter);
 			}
-			t = trackAllServices ? new AllTracked( trackingCount ) : new Tracked( trackingCount );
+			t = new Tracked( trackingCount );
 			synchronized (t) {
 				try {
-					context.addServiceListener(t, listenerFilter);
-					ServiceReference<S>[] references = null;
-					if (trackClass != null) {
-						references = getInitialReferences(trackAllServices, trackClass, null);
-					} else {
-						if (trackReference != null) {
-							if (trackReference.getBundle() != null) {
-								ServiceReference<S>[] single = new ServiceReference[] {trackReference};
-								references = single;
-							}
-						} else { /* user supplied filter */
-							references = getInitialReferences(trackAllServices, null, listenerFilter);
-						}
-					}
+					extendedServiceListenerContext.addServiceListener(classFilterString, eventFilter, t);
+					ServiceReference<S>[] references = getInitialReferences(null, initialReferenceFilterString);
 					/* set tracked with the initial references */
 					t.setInitial(references);
 				} catch (InvalidSyntaxException e) {
@@ -349,18 +229,16 @@
 	/**
 	 * Returns the list of initial {@code ServiceReference}s that will be
 	 * tracked by this {@code ServiceTracker}.
-	 * 
-	 * @param trackAllServices If {@code true}, use
-	 *        {@code getAllServiceReferences}.
 	 * @param className The class name with which the service was registered, or
 	 *        {@code null} for all services.
 	 * @param filterString The filter criteria or {@code null} for all services.
+	 * 
 	 * @return The list of initial {@code ServiceReference}s.
 	 * @throws InvalidSyntaxException If the specified filterString has an
 	 *         invalid syntax.
 	 */
-	private ServiceReference<S>[] getInitialReferences(boolean trackAllServices, String className, String filterString) throws InvalidSyntaxException {
-		ServiceReference<S>[] result = (ServiceReference<S>[]) ((trackAllServices) ? context.getAllServiceReferences(className, filterString) : context.getServiceReferences(className, filterString));
+	private ServiceReference<S>[] getInitialReferences(String className, String filterString) throws InvalidSyntaxException {
+		ServiceReference<S>[] result = (ServiceReference<S>[]) context.getServiceReferences(className, filterString);
 		return result;
 	}
 
@@ -386,7 +264,7 @@
 				return map;
 			}
 			if (DEBUG) {
-				System.out.println("ServiceTracker.close: " + filter);
+				System.out.println("ServiceTracker.close: " + eventFilter);
 			}
 			outgoing.close();
             synchronized ( outgoing )
@@ -397,7 +275,7 @@
 //			references = getServiceReferences();
 //			tracked = null;
 			try {
-				context.removeServiceListener(outgoing);
+				extendedServiceListenerContext.removeServiceListener(classFilterString, eventFilter, outgoing);
 			} catch (IllegalStateException e) {
 				/* In case the context was stopped. */
 			}
@@ -412,9 +290,7 @@
 //			}
 //		}
 		if (DEBUG) {
-			if ((cachedReference == null) && (cachedService == null)) {
-				System.out.println("ServiceTracker.close[cached cleared]: " + filter);
-			}
+				System.out.println("ServiceTracker.close[cached cleared]: " + eventFilter);
 		}
         return map;
 	}
@@ -427,7 +303,7 @@
                 return;
             }
             if (DEBUG) {
-                System.out.println("ServiceTracker.close: " + filter);
+                System.out.println("ServiceTracker.close: " + eventFilter);
             }
         }
         for (ServiceReference<S> ref: toUntrack.keySet()) {
@@ -479,7 +355,7 @@
 	 * 
 	 * @param reference The reference to modified service.
 	 * @param service The service object for the modified service.
-	 * @see ServiceTrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, Object, int)
+	 * @see ServiceTrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, Object, int, ServiceEvent)
 	 */
 	public void modifiedService(ServiceReference<S> reference, T service, int trackingCount) {
 		/* do nothing */
@@ -504,67 +380,13 @@
 	 * 
 	 * @param reference The reference to removed service.
 	 * @param service The service object for the removed service.
-	 * @see ServiceTrackerCustomizer#removedService(org.osgi.framework.ServiceReference, Object, int)
+	 * @see ServiceTrackerCustomizer#removedService(org.osgi.framework.ServiceReference, Object, int, ServiceEvent)
 	 */
 	public void removedService(ServiceReference<S> reference, T service, int trackingCount) {
 		context.ungetService(reference);
 	}
 
 	/**
-	 * Wait for at least one service to be tracked by this
-	 * {@code ServiceTracker}. This method will also return when this
-	 * {@code ServiceTracker} is closed.
-	 * 
-	 * <p>
-	 * It is strongly recommended that {@code waitForService} is not used during
-	 * the calling of the {@code BundleActivator} methods.
-	 * {@code BundleActivator} methods are expected to complete in a short
-	 * period of time.
-	 * 
-	 * <p>
-	 * This implementation calls {@link #getService()} to determine if a service
-	 * is being tracked.
-	 * 
-	 * @param timeout The time interval in milliseconds to wait. If zero, the
-	 *        method will wait indefinitely.
-	 * @return Returns the result of {@link #getService()}.
-	 * @throws InterruptedException If another thread has interrupted the
-	 *         current thread.
-	 * @throws IllegalArgumentException If the value of timeout is negative.
-	 */
-	public T waitForService(long timeout) throws InterruptedException {
-		if (timeout < 0) {
-			throw new IllegalArgumentException("timeout value is negative");
-		}
-
-		T object = getService();
-		if (object != null) {
-			return object;
-		}
-
-		final long endTime = (timeout == 0) ? 0 : (System.currentTimeMillis() + timeout);
-		do {
-			final Tracked t = tracked();
-			if (t == null) { /* if ServiceTracker is not open */
-				return null;
-			}
-			synchronized (t) {
-				if (t.size() == 0) {
-					t.wait(timeout);
-				}
-			}
-			object = getService();
-			if (endTime > 0) { // if we have a timeout
-				timeout = endTime - System.currentTimeMillis();
-				if (timeout <= 0) { // that has expired
-					break;
-				}
-			}
-		} while (object == null);
-		return object;
-	}
-
-	/**
 	 * Return an array of {@code ServiceReference}s for all services being
 	 * tracked by this {@code ServiceTracker}.
 	 * 
@@ -586,76 +408,6 @@
 		}
 	}
 
-	/**
-	 * Returns a {@code ServiceReference} for one of the services being tracked
-	 * by this {@code ServiceTracker}.
-	 * 
-	 * <p>
-	 * If multiple services are being tracked, the service with the highest
-	 * ranking (as specified in its {@code service.ranking} property) is
-	 * returned. If there is a tie in ranking, the service with the lowest
-	 * service ID (as specified in its {@code service.id} property); that is,
-	 * the service that was registered first is returned. This is the same
-	 * algorithm used by {@code BundleContext.getServiceReference}.
-	 * 
-	 * <p>
-	 * This implementation calls {@link #getServiceReferences()} to get the list
-	 * of references for the tracked services.
-	 * 
-	 * @return A {@code ServiceReference} or {@code null} if no services are
-	 *         being tracked.
-	 * @since 1.1
-	 */
-	public ServiceReference<S> getServiceReference() {
-		ServiceReference<S> reference = cachedReference;
-		if (reference != null) {
-			if (DEBUG) {
-				System.out.println("ServiceTracker.getServiceReference[cached]: " + filter);
-			}
-			return reference;
-		}
-		if (DEBUG) {
-			System.out.println("ServiceTracker.getServiceReference: " + filter);
-		}
-		ServiceReference<S>[] references = getServiceReferences();
-		int length = (references == null) ? 0 : references.length;
-		if (length == 0) { /* if no service is being tracked */
-			return null;
-		}
-		int index = 0;
-		if (length > 1) { /* if more than one service, select highest ranking */
-			int rankings[] = new int[length];
-			int count = 0;
-			int maxRanking = Integer.MIN_VALUE;
-			for (int i = 0; i < length; i++) {
-				Object property = references[i].getProperty(Constants.SERVICE_RANKING);
-				int ranking = (property instanceof Integer) ? ((Integer) property).intValue() : 0;
-				rankings[i] = ranking;
-				if (ranking > maxRanking) {
-					index = i;
-					maxRanking = ranking;
-					count = 1;
-				} else {
-					if (ranking == maxRanking) {
-						count++;
-					}
-				}
-			}
-			if (count > 1) { /* if still more than one service, select lowest id */
-				long minId = Long.MAX_VALUE;
-				for (int i = 0; i < length; i++) {
-					if (rankings[i] == maxRanking) {
-						long id = ((Long) (references[i].getProperty(Constants.SERVICE_ID))).longValue();
-						if (id < minId) {
-							index = i;
-							minId = id;
-						}
-					}
-				}
-			}
-		}
-		return cachedReference = references[index];
-	}
 
 	/**
 	 * Returns the service object for the specified {@code ServiceReference} if
@@ -708,34 +460,6 @@
 		}
 	}
 
-	/**
-	 * Returns a service object for one of the services being tracked by this
-	 * {@code ServiceTracker}.
-	 * 
-	 * <p>
-	 * If any services are being tracked, this implementation returns the result
-	 * of calling {@code getService(getServiceReference())}.
-	 * 
-	 * @return A service object or {@code null} if no services are being
-	 *         tracked.
-	 */
-	public T getService() {
-		T service = cachedService;
-		if (service != null) {
-			if (DEBUG) {
-				System.out.println("ServiceTracker.getService[cached]: " + filter);
-			}
-			return service;
-		}
-		if (DEBUG) {
-			System.out.println("ServiceTracker.getService: " + filter);
-		}
-		ServiceReference<S> reference = getServiceReference();
-		if (reference == null) {
-			return null;
-		}
-		return cachedService = getService(reference);
-	}
 
 	/**
 	 * Remove a service from this {@code ServiceTracker}.
@@ -810,10 +534,8 @@
 	 * between the listener thread and the user thread.
 	 */
 	void modified() {
-		cachedReference = null; /* clear cached value */
-		cachedService = null; /* clear cached value */
 		if (DEBUG) {
-			System.out.println("ServiceTracker.modified: " + filter);
+			System.out.println("ServiceTracker.modified: " + eventFilter);
 		}
 	}
 
@@ -1106,11 +828,12 @@
                 if (DEBUG) {
                     System.out.println("AbstractTracked.trackInitial: " + item); //$NON-NLS-1$
                 }
-                trackAdding(item, null); /*
-                                         * Begin tracking it. We call trackAdding
-                                         * since we have already put the item in the
-                                         * adding list.
-                                         */
+                /*
+                 * Begin tracking it. We call trackAdding
+                 * since we have already put the item in the
+                 * adding list.
+                 */
+                trackAdding(item, null); 
             }
         }
 
@@ -1410,7 +1133,7 @@
 	 * 
 	 * @ThreadSafe
 	 */
-	private class Tracked extends AbstractTracked<ServiceReference<S>, T, ServiceEvent> implements ServiceListener {
+	private class Tracked extends AbstractTracked<ServiceReference<S>, T, U> implements ExtendedServiceListener<U> {
 		/**
 		 * Tracked constructor.
          * @param trackingCount
@@ -1425,7 +1148,7 @@
 		 * 
 		 * @param event {@code ServiceEvent} object from the framework.
 		 */
-		final public void serviceChanged(final ServiceEvent event) {
+		final public void serviceChanged(final U event) {
 			/*
 			 * Check if we had a delayed call (which could happen when we
 			 * close).
@@ -1484,12 +1207,12 @@
          * @return Customized object for the tracked item or {@code null} if the
 		 *         item is not to be tracked.
 		 */
-		final T customizerAdding( final ServiceReference<S> item, final ServiceEvent related ) {
+		final T customizerAdding( final ServiceReference<S> item, final U related ) {
 			return customizer.addingService( item );
 		}
 
-		final void customizerAdded( final ServiceReference<S> item, final ServiceEvent related, final T object, int trackingCount, int serviceCount ) {
-		    customizer.addedService( item, object, trackingCount, serviceCount );
+		final void customizerAdded( final ServiceReference<S> item, final U related, final T object, int trackingCount, int serviceCount ) {
+		    customizer.addedService( item, object, trackingCount, serviceCount, related );
 		}
 
 		/**
@@ -1501,8 +1224,8 @@
          * @param object Customized object for the tracked item.
          * @param trackingCount
          */
-		final void customizerModified( final ServiceReference<S> item, final ServiceEvent related, final T object, int trackingCount ) {
-			customizer.modifiedService( item, object, trackingCount );
+		final void customizerModified( final ServiceReference<S> item, final U related, final T object, int trackingCount ) {
+			customizer.modifiedService( item, object, trackingCount, related );
 		}
 
         /**
@@ -1514,8 +1237,8 @@
          * @param object Customized object for the tracked item.
          * @param trackingCount
          */
-		final void customizerRemoved( final ServiceReference<S> item, final ServiceEvent related, final T object, int trackingCount ) {
-			customizer.removedService(item, object, trackingCount );
+		final void customizerRemoved( final ServiceReference<S> item, final U related, final T object, int trackingCount ) {
+			customizer.removedService(item, object, trackingCount, related );
 		}
 	}
 
@@ -1526,13 +1249,13 @@
 	 * @since 1.3
 	 * @ThreadSafe
 	 */
-	private class AllTracked extends Tracked implements AllServiceListener {
-		/**
-		 * AllTracked constructor.
-         * @param trackingCount
-         */
-		AllTracked( AtomicInteger trackingCount ) {
-			super( trackingCount );
-		}
-	}
+//	private class AllTracked extends Tracked<U> implements AllServiceListener {
+//		/**
+//		 * AllTracked constructor.
+//         * @param trackingCount
+//         */
+//		AllTracked( AtomicInteger trackingCount ) {
+//			super( trackingCount );
+//		}
+//	}
 }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTrackerCustomizer.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTrackerCustomizer.java
index 84403ec..6f0c794 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTrackerCustomizer.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceTrackerCustomizer.java
@@ -16,6 +16,7 @@
 
 package org.apache.felix.scr.impl.manager;
 
+import org.osgi.framework.ServiceEvent;
 import org.osgi.framework.ServiceReference;
 
 /**
@@ -47,7 +48,7 @@
  * @ThreadSafe
  * @version $Id: c14b8d47026b6bd4ba1f2db7bf7e755d00fc6f6a $
  */
-public interface ServiceTrackerCustomizer<S, T> {
+public interface ServiceTrackerCustomizer<S, T, U extends ServiceEvent> {
 	/**
 	 * A service is being added to the {@code ServiceTracker}.
 	 * 
@@ -69,7 +70,7 @@
 	 */
 	public T addingService( ServiceReference<S> reference );
 
-    public void addedService( ServiceReference<S> reference, T service, int trackingCount, int serviceCount );
+    public void addedService( ServiceReference<S> reference, T service, int trackingCount, int serviceCount, U event );
 
 	/**
 	 * A service tracked by the {@code ServiceTracker} has been modified.
@@ -79,10 +80,11 @@
 	 * {@code ServiceTracker} has had it properties modified.
 	 *
      * @param reference The reference to the service that has been modified.
-     * @param service The service object for the specified referenced service.
-     * @param trackingCount
+	 * @param service The service object for the specified referenced service.
+	 * @param trackingCount
+	 * @param event TODO
      */
-	public void modifiedService( ServiceReference<S> reference, T service, int trackingCount );
+	public void modifiedService( ServiceReference<S> reference, T service, int trackingCount, U event );
 
 	/**
 	 * A service tracked by the {@code ServiceTracker} has been removed.
@@ -94,7 +96,8 @@
      * @param reference The reference to the service that has been removed.
 	 * @param service The service object for the specified referenced service.
 	 * @param trackingCount
+	 * @param event TODO
      */
-	public void removedService( ServiceReference<S> reference, T service, int trackingCount );
+	public void removedService( ServiceReference<S> reference, T service, int trackingCount, U event );
 
 }
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java b/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
index d6f60bf..9854c33 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
@@ -374,7 +374,7 @@
         Collection<ServiceReference<S>> srs;
         try {
             srs = bundleContext.getServiceReferences(clazz, filter);
-            Assert.assertEquals(1, srs.size());
+            Assert.assertEquals("Nothing for filter: " + filter, 1, srs.size());
             ServiceReference<S> sr = srs.iterator().next();
             S s = bundleContext.getService(sr);
             Assert.assertNotNull(s);
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/LocateTest.java b/scr/src/test/java/org/apache/felix/scr/integration/LocateTest.java
index 6674ee4..cd01550 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/LocateTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/LocateTest.java
@@ -46,18 +46,20 @@
     {
         bundleContext.registerService( Object.class, new Object(), null );
         
-        findComponentConfigurationByName( "AsyncLocate", ComponentConfigurationDTO.ACTIVE );
+        findComponentConfigurationByName( "Consumer", ComponentConfigurationDTO.ACTIVE );
         
-        final String pid = "SimpleComponent";
+        final String pid = "TestComponent";
         Configuration config = getConfigurationAdmin().getConfiguration( pid, null );
         final Hashtable props = new Hashtable();
+        //wrong target property, will not bind
         props.put( "target", "bar" );
         config.update(props);
         delay();
         
         //when deadlock is present the state is actually unsatisfied.
-        ComponentConfigurationDTO cc = findComponentConfigurationByName( pid, ComponentConfigurationDTO.ACTIVE );
-        delay();
+        ComponentConfigurationDTO cc = findComponentConfigurationByName( pid, ComponentConfigurationDTO.SATISFIED );
+//        delay();
+        //correct target property: will bind as new properties are propagated.
         props.put( "target", "foo" );
         config.update(props);
         delay();
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/components/deadlock/Consumer.java b/scr/src/test/java/org/apache/felix/scr/integration/components/deadlock/Consumer.java
index b99d824..4673cdb 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/components/deadlock/Consumer.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/components/deadlock/Consumer.java
@@ -31,12 +31,12 @@
         this.cc = cc;
     }
     
-    protected void setSimpleComponent(TestComponent sc)
+    protected void setTestComponent(TestComponent tc)
     {
-        sc.doIt( );       
+        tc.doIt( );       
     }
     
-    protected void unsetSimpleComponent(ServiceReference<TestComponent> sr)
+    protected void unsetTestComponent(ServiceReference<TestComponent> sr)
     {
         
     }    
diff --git a/scr/src/test/resources/integration_test_locate.xml b/scr/src/test/resources/integration_test_locate.xml
index 1ca586e..9e285c8 100644
--- a/scr/src/test/resources/integration_test_locate.xml
+++ b/scr/src/test/resources/integration_test_locate.xml
@@ -11,7 +11,7 @@
 	language governing permissions and limitations under the License. -->
 <components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"> 
 
-    <scr:component name="SimpleComponent"
+    <scr:component name="TestComponent"
         configuration-policy="require">
         <implementation class="org.apache.felix.scr.integration.components.deadlock.TestComponent" />
         <service>
@@ -28,17 +28,17 @@
     </scr:component>
 
 
-    <scr:component name="AsyncLocate"
+    <scr:component name="Consumer"
         immediate="true">
         <implementation class="org.apache.felix.scr.integration.components.deadlock.Consumer" />
         <reference
-            name="SimpleComponent"
+            name="TestComponent"
             interface="org.apache.felix.scr.integration.components.deadlock.TestComponent"
             cardinality="0..1"
             policy="dynamic"
-            bind="setSimpleComponent"
-            unbind="unsetSimpleComponent"
-            target='target="foo"'
+            bind="setTestComponent"
+            unbind="unsetTestComponent"
+            target='(target=foo)'
         />
     </scr:component>