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 5df26a4..6832c45 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
@@ -733,462 +733,6 @@
         }
     }
 
-    private boolean isActive()
-    {
-        ServiceTracker<T, RefPair<T>> tracker = trackerRef.get();
-        return tracker != null && tracker.isActive();
-    }
-
-    //---------- ServiceListener interface ------------------------------------
-
-    /**
-     * Called when a registered service changes state. In the case of service
-     * modification the service is assumed to be removed and added again.
-     */
-    /*
-    public void serviceChanged( ServiceEvent event )
-    {
-        final ServiceReference<T> ref = ( ServiceReference<T> ) event.getServiceReference();
-        final String serviceString = "Service " + m_dependencyMetadata.getInterface() + "/"
-            + ref.getProperty( Constants.SERVICE_ID );
-        Collection<ServiceReference<T>> changes = null;
-        try
-        {
-            switch ( event.getType() )
-            {
-                case ServiceEvent.REGISTERED:
-                    m_componentManager.log( LogService.LOG_DEBUG, "Dependency Manager: Adding {0}", new Object[]
-                        { serviceString }, null );
-
-                    // consider the service if the filter matches
-                    if ( targetFilterMatch( ref ) )
-                    {
-                        synchronized ( added )
-                        {
-                            added.add( ref );
-                        }
-                        synchronized (enableLock)
-                        {
-                            //wait for enable to complete
-                        }
-                        synchronized ( added )
-                        {
-                            if (!added.contains( ref ))
-                            {
-                                break;
-                            }
-                        }
-                        m_size.incrementAndGet();
-                        changes = added;
-                        serviceAdded( ref );
-                    }
-                    else
-                    {
-                        m_componentManager.log( LogService.LOG_DEBUG,
-                            "Dependency Manager: Ignoring added Service for {0} : does not match target filter {1}",
-                            new Object[]
-                                { m_dependencyMetadata.getName(), getTarget() }, null );
-                    }
-                    break;
-
-                case ServiceEvent.MODIFIED:
-                    m_componentManager.log( LogService.LOG_DEBUG, "Dependency Manager: Updating {0}", new Object[]
-                        { serviceString }, null );
-
-                    if ( getBoundService( ref ) == null )
-                    {
-                        // service not currently bound --- what to do ?
-                        // if static
-                        //    if inactive and target match: activate
-                        // if dynamic or greedy
-                        //    if multiple and target match: bind
-                        if ( targetFilterMatch( ref ) )
-                        {
-                            synchronized ( added )
-                            {
-                                added.add( ref );
-                            }
-                            synchronized (enableLock)
-                            {
-                                //wait for enable to complete
-                            }
-                            synchronized ( added )
-                            {
-                                if (!added.contains( ref ))
-                                {
-                                    break;
-                                }
-                            }
-                            changes = added;
-                            m_size.incrementAndGet();
-                                if ( isStatic() )
-                                {
-                                    // if static reference: activate if currentl unsatisifed, otherwise no influence
-                                    if ( m_componentManager.getState() == AbstractComponentManager.STATE_UNSATISFIED )
-                                    {
-                                        m_componentManager.log( LogService.LOG_DEBUG,
-                                            "Dependency Manager: Service {0} registered, activate component", new Object[]
-                                                { m_dependencyMetadata.getName() }, null );
-
-                                        // immediately try to activate the component (FELIX-2368)
-                                        m_componentManager.activateInternal();
-                                    }
-                                }
-                                else if ( isMultiple() || !isReluctant())
-                                {
-                                    // if dynamic and multiple reference, bind, otherwise ignore
-                                    serviceAdded( ref );
-                                }
-                            }
-
-                    }
-                    else if ( !targetFilterMatch( ref ) )
-                    {
-                        synchronized ( removed )
-                        {
-                            removed.add( ref );
-                        }
-                        synchronized (enableLock)
-                        {
-                            //wait for enable to complete
-                        }
-                        synchronized ( removed )
-                        {
-                            if (!removed.contains( ref ))
-                            {
-                                break;
-                            }
-                        }
-                        changes = removed;
-                        m_size.set( getServiceReferenceCount() );
-                        serviceRemoved( ref );
-                    }
-                    else
-                    {
-                        // update the service binding due to the new properties
-                        m_componentManager.update( this, ref );
-                    }
-
-                    break;
-
-                case ServiceEvent.UNREGISTERING:
-                    m_componentManager.log( LogService.LOG_DEBUG, "Dependency Manager: Removing {0}", new Object[]
-                        { serviceString }, null );
-
-                    // manage the service counter if the filter matchs
-                    if ( targetFilterMatch( ref ) )
-                    {
-                        synchronized ( removed )
-                        {
-                            removed.add( ref );
-                        }
-                        synchronized (enableLock)
-                        {
-                            //wait for enable to complete
-                        }
-                        synchronized ( removed )
-                        {
-                            if (!removed.contains( ref ))
-                            {
-                                break;
-                            }
-                        }
-                        changes = removed;
-                        m_size.set( getServiceReferenceCount() );
-                        serviceRemoved( ref );
-                    }
-                    else
-                    {
-                        m_componentManager
-                            .log(
-                                LogService.LOG_DEBUG,
-                                "Dependency Manager: Not counting Service for {0} : Service {1} does not match target filter {2}",
-                                new Object[]
-                                    { m_dependencyMetadata.getName(), ref.getProperty( Constants.SERVICE_ID ), getTarget() },
-                                null );
-                        // remove the service ignoring the filter match because if the
-                        // service is bound, it has to be removed no matter what
-                        serviceRemoved( ref );
-                    }
-
-
-                    break;
-            }
-        }
-        finally
-        {
-            if ( changes != null)
-            {
-                synchronized ( changes )
-                {
-                    changes.remove( ref );
-                    changes.notify();
-                }
-            }
-        }
-    }
- *?
-
-    /**
-     * Called by the {@link #serviceChanged(ServiceEvent)} method if a new
-     * service is registered with the system or if a registered service has been
-     * modified.
-     * <p>
-     * Depending on the component state and dependency configuration, the
-     * component may be activated, re-activated or the service just be provided.
-     *
-     * See Compendium 4.3 table 112.1
-     *
-     * @param reference The reference to the service newly registered or
-     *      modified.
-     */
-    /*
-    private void serviceAdded( ServiceReference<T> reference )
-    {
-        // if the component is currently unsatisfied, it may become satisfied
-        // by adding this service, try to activate (also schedule activation
-        // if the component is pending deactivation)
-        if ( m_componentManager.getState() == AbstractComponentManager.STATE_UNSATISFIED && !isOptional() )
-        {
-            m_componentManager.log( LogService.LOG_DEBUG,
-                "Dependency Manager: Service {0} registered, activate component", new Object[]
-                    { m_dependencyMetadata.getName() }, null );
-
-            // immediately try to activate the component (FELIX-2368)
-            boolean handled = m_componentManager.activateInternal();
-            if (!handled)
-            {
-                m_componentManager.log( LogService.LOG_DEBUG,
-                    "Dependency Manager: Service {0} activation did not occur on this thread", new Object[]
-                        { m_dependencyMetadata.getName() }, null );
-
-                Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependenciesMap = m_componentManager.getDependencyMap();
-                if (dependenciesMap  != null) {
-                    //someone else has managed to activate
-                    Map<ServiceReference<T>, RefPair<T>> references = (Map)dependenciesMap.get( this );
-                    if (references == null )
-                    {
-                        throw new IllegalStateException( "Allegedly active but dependency manager not represented: " + this );
-                    }
-                    handled = references.containsKey( reference );
-                }
-            }
-            if (handled)
-            {
-                m_componentManager.log( LogService.LOG_DEBUG,
-                    "Dependency Manager: Service {0} activation on other thread bound service reference {1}", new Object[]
-                        { m_dependencyMetadata.getName(), reference }, null );
-                return;
-            }
-            //release our read lock and wait for activation to complete
-//            m_componentManager.releaseReadLock( "DependencyManager.serviceAdded.nothandled.1" );
-//            m_componentManager.obtainReadLock( "DependencyManager.serviceAdded.nothandled.2" );
-            m_componentManager.log( LogService.LOG_DEBUG,
-                    "Dependency Manager: Service {0} activation on other thread: after releasing lock, component instance is: {1}", new Object[]
-                    {m_dependencyMetadata.getName(), m_componentManager.getInstance()}, null );
-        }
-
-        // otherwise check whether the component is in a state to handle the event
-        if ( handleServiceEvent() )
-        {
-
-            // FELIX-1413: if the dependency is static and reluctant and the component is
-            // satisfied (active) added services are not considered until
-            // the component is reactivated for other reasons.
-            if ( m_dependencyMetadata.isStatic() )
-            {
-                if ( m_dependencyMetadata.isReluctant() )
-                {
-                    m_componentManager.log( LogService.LOG_DEBUG,
-                            "Dependency Manager: Added service {0} is ignored for static reluctant reference", new Object[]
-                            {m_dependencyMetadata.getName()}, null );
-                }
-                else
-                {
-                    Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependenciesMap = m_componentManager.getDependencyMap();
-                    if ( dependenciesMap != null )
-                    {
-                        Map<ServiceReference<T>, RefPair<T>> bound = (Map)dependenciesMap.get( this );
-                        if ( m_dependencyMetadata.isMultiple() ||
-                                                bound.isEmpty() ||
-                                                reference.compareTo( bound.keySet().iterator().next() ) > 0 )
-                                        {
-                                            m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
-                                            m_componentManager.activateInternal();
-                                        }
-                    }
-                }
-            }
-
-            // otherwise bind if we have a bind method and the service needs
-            // be bound
-            else if ( m_dependencyMetadata.getBind() != null )
-            {
-                // multiple bindings or not bound at all yet
-                if ( m_dependencyMetadata.isMultiple() || !isBound() )
-                {
-                    // bind the service, getting it if required
-                    m_componentManager.invokeBindMethod( this, reference );
-                }
-                else if ( !isReluctant() )
-                {
-                    //dynamic greedy single: bind then unbind
-                    Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependenciesMap = m_componentManager.getDependencyMap();
-                    if ( dependenciesMap != null )
-                    {
-                        Map<ServiceReference<T>, RefPair<T>> bound = (Map)dependenciesMap.get( this );
-                        ServiceReference oldRef = bound.keySet().iterator().next();
-                        if ( reference.compareTo( oldRef ) > 0 )
-                        {
-                            m_componentManager.invokeBindMethod( this, reference );
-                            m_componentManager.invokeUnbindMethod( this, oldRef );
-                        }
-                    }
-                }
-            }
-        }
-
-        else
-        {
-            m_componentManager.log( LogService.LOG_DEBUG,
-                "Dependency Manager: Ignoring service addition, wrong state {0}", new Object[]
-                    { m_componentManager.state() }, null );
-        }
-    }
-
-   *?
-    /**
-     * Called by the {@link #serviceChanged(ServiceEvent)} method if an existing
-     * service is unregistered from the system or if a registered service has
-     * been modified.
-     * <p>
-     * Depending on the component state and dependency configuration, the
-     * component may be deactivated, re-activated, the service just be unbound
-     * with or without a replacement service.
-     *
-     * @param reference The reference to the service unregistering or being
-     *      modified.
-     */
-    /*
-    private void serviceRemoved( ServiceReference<T> reference )
-    {
-        // if the dependency is not satisfied anymore, we have to
-        // deactivate the component
-        if ( !isSatisfied() )
-        {
-            m_componentManager.log( LogService.LOG_DEBUG,
-                "Dependency Manager: Deactivating component due to mandatory dependency on {0}/{1} not satisfied",
-                new Object[]
-                    { m_dependencyMetadata.getName(), m_dependencyMetadata.getInterface() }, null );
-
-            // deactivate the component now
-            m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
-        }
-
-        // check whether we are bound to that service, do nothing if not
-        if ( getBoundService( reference ) == null )
-        {
-            m_componentManager.log( LogService.LOG_DEBUG,
-                "Dependency Manager: Ignoring removed Service for {0} : Service {1} not bound", new Object[]
-                    { m_dependencyMetadata.getName(), reference.getProperty( Constants.SERVICE_ID ) }, null );
-        }
-
-        // otherwise check whether the component is in a state to handle the event
-        else if ( handleServiceEvent() || (m_componentManager.getState() & (Component.STATE_DISABLED | Component.STATE_DISPOSED)) != 0 )
-        {
-            Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependencyMap = m_componentManager.getDependencyMap();
-            Map<ServiceReference<T>, RefPair<T>> referenceMap = null;
-            if (dependencyMap != null)
-            {
-                referenceMap = (Map)dependencyMap.get( this );
-            }
-            // if the dependency is static, we have to deactivate the component
-            // to "remove" the dependency
-            if ( m_dependencyMetadata.isStatic() )
-            {
-                try
-                {
-                    m_componentManager.log( LogService.LOG_DEBUG,
-                        "Dependency Manager: Static dependency on {0}/{1} is broken", new Object[]
-                            { m_dependencyMetadata.getName(), m_dependencyMetadata.getInterface() }, null );
-                    m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
-                    if ( referenceMap != null )
-                    {
-                        referenceMap.remove( reference );
-                    }
-
-                    // FELIX-2368: immediately try to reactivate
-                    m_componentManager.activateInternal();
-                }
-                catch ( Exception ex )
-                {
-                    m_componentManager.log( LogService.LOG_ERROR, "Exception while recreating dependency ", ex );
-                }
-            }
-
-            // dynamic dependency, multiple or single but this service is the bound one
-            else
-            {
-
-                // try to bind a replacement service first if this is a unary
-                // cardinality reference and a replacement is available.
-                if ( !m_dependencyMetadata.isMultiple() )
-                {
-                    // if the dependency is mandatory and no replacement is
-                    // available, bind returns false and we deactivate
-                    // bind best matching service
-                    ServiceReference<T> ref = getFrameworkServiceReference();
-
-                    if ( ref == null )
-                    {
-                        if ( !m_dependencyMetadata.isOptional() )
-                        {
-                            m_componentManager
-                                .log(
-                                        LogService.LOG_DEBUG,
-                                        "Dependency Manager: Deactivating component due to mandatory dependency on {0}/{1} not satisfied",
-                                        new Object[]
-                                                {m_dependencyMetadata.getName(), m_dependencyMetadata.getInterface()}, null );
-                            m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false );
-                        }
-                    }
-                    else
-                    {
-                        m_componentManager.invokeBindMethod( this, ref );
-                    }
-                }
-
-                // call the unbind method if one is defined
-                if ( m_dependencyMetadata.getUnbind() != null )
-                {
-                    m_componentManager.invokeUnbindMethod( this, reference );
-                }
-
-                // make sure the service is returned
-                ungetService( reference );
-                //service is no longer available, don't track it any longer.
-                if ( referenceMap != null )
-                {
-                    referenceMap.remove( reference );
-                }
-            }
-        }
-
-        else
-        {
-            m_componentManager.log( LogService.LOG_DEBUG,
-                "Dependency Manager: Ignoring service removal, wrong state {0}", new Object[]
-                    { m_componentManager.state() }, null );
-        }
-    }
-   */
-
-    private boolean handleServiceEvent()
-    {
-        return ( m_componentManager.getState() & STATE_MASK ) != 0;
-    }
-
-
     //---------- Reference interface ------------------------------------------
 
     public String getServiceName()
@@ -1420,15 +964,6 @@
 
 
     /**
-     * Returns <code>true</code> if at least one service has been bound
-     */
-    private boolean isBound()
-    {
-        return !customizerRef.get().getRefs().isEmpty();
-    }
-
-
-    /**
      * Returns the RefPair containing the given service reference and the bound service
      * or <code>null</code> if this is instance is not currently bound to that
      * service.
@@ -1501,45 +1036,6 @@
         return serviceObject;
     }
 
-
-    /**
-     * Ungets the service described by the ServiceReference and removes it from
-     * the list of bound services.
-     */
-//    void ungetService( ServiceReference<T> serviceReference )
-//    {
-//        // check we really have this service, do nothing if not
-//        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependencyMap = m_componentManager.getDependencyMap();
-//        if ( dependencyMap != null )
-//        {
-//            RefPair refPair  = dependencyMap.get( this ).get( serviceReference );
-//            if ( refPair != null && refPair.getServiceObject() != null )
-//            {
-//                BundleComponentActivator activator = m_componentManager.getActivator();
-//                if ( activator != null )
-//                {
-//                    BundleContext bundleContext = activator.getBundleContext();
-//                    if ( bundleContext != null )
-//                    {
-//                        try
-//                        {
-//                            bundleContext.ungetService( serviceReference );
-//                        }
-//                        catch ( IllegalStateException e )
-//                        {
-//                            m_componentManager.log( LogService.LOG_INFO,
-//                                "For dependency {0}, trying to unget ServiceReference {1} on invalid bundle context {2}",
-//                                new Object[]
-//                                    { m_dependencyMetadata.getName(), serviceReference.getProperty( Constants.SERVICE_ID ),
-//                                        serviceReference }, null );
-//                        }
-//                    }
-//                }
-//            }
-//        }
-//    }
-
-
     //---------- DependencyManager core ---------------------------------------
 
     /**
@@ -1600,78 +1096,6 @@
     {
 
         return customizerRef.get().open();
-//        // If no references were received, we have to check if the dependency
-//        // is optional, if it is not then the dependency is invalid
-//        if ( !isSatisfied() )
-//        {
-//            return false;
-//        }
-//
-//        // if no bind method is configured or if this is a delayed component,
-//        // we have nothing to do and just signal success
-//        if ( m_dependencyMetadata.getBind() == null )
-//        {
-//            dependencyMap.put( this, new HashMap<ServiceReference<T>, RefPair<T>>( ) );
-//            return true;
-//        }
-//
-//        Map<ServiceReference<T>, RefPair<T>> result = new HashMap<ServiceReference<T>, RefPair<T>>();
-//        // assume success to begin with: if the dependency is optional,
-//        // we don't care, whether we can bind a service. Otherwise, we
-//        // require at least one service to be bound, thus we require
-//        // flag being set in the loop below
-//        boolean success = m_dependencyMetadata.isOptional();
-//
-//        // Get service reference(s)
-//        if ( m_dependencyMetadata.isMultiple() )
-//        {
-//            // bind all registered services
-//            ServiceReference<T>[] refs = getFrameworkServiceReferences();
-//            if ( refs != null )
-//            {
-//                for ( ServiceReference<T> ref : refs )
-//                {
-//                    RefPair refPair = new RefPair( ref );
-//                    // success is if we have the minimal required number of services bound
-//                    if ( m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext() ) )
-//                    {
-//                        result.put( ref, refPair );
-//                        // of course, we have success if the service is bound
-//                        success = true;
-//                    }
-//                    else
-//                    {
-//                        m_componentManager.getActivator().registerMissingDependency( this, ref );
-//                    }
-//                }
-//            }
-//        }
-//        else
-//        {
-//            // bind best matching service
-//            ServiceReference ref = getFrameworkServiceReference();
-//            if ( ref != null )
-//            {
-//                RefPair refPair = new RefPair( ref );
-//                // success is if we have the minimal required number of services bound
-//                if ( m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext() ) )
-//                {
-//                    result.put( ref, refPair );
-//                    // of course, we have success if the service is bound
-//                    success = true;
-//                }
-//                else if ( isOptional() )
-//                {
-//                    m_componentManager.getActivator().registerMissingDependency( this, ref );
-//                }
-//            }
-//        }
-//
-//        // success will be true, if the service is optional or if at least
-//        // one service was available to be bound (regardless of whether the
-//        // bind method succeeded or not)
-//        dependencyMap.put( this, result );
-//        return success;
     }
 
     /**
@@ -1772,35 +1196,6 @@
             }
     }
 
-//    boolean invokeBindMethod( S componentInstance, ServiceReference<T> ref )
-//    {
-//        //event driven, and we already checked this ref is not yet handled.
-//        Map<DependencyManager<S, ?>, Map<ServiceReference<?>, RefPair<?>>> dependencyMap = m_componentManager.getDependencyMap();
-//        if ( dependencyMap != null )
-//        {
-//            if ( m_bindMethods == null )
-//            {
-//                m_componentManager.log( LogService.LOG_ERROR,
-//                        "For dependency {0}, bind method not set: component state {1}",
-//                        new Object[]
-//                                {m_dependencyMetadata.getName(), new Integer( m_componentManager.getState() )}, null );
-//
-//            }
-//            Map<ServiceReference<T>, RefPair<T>> deps = (Map)dependencyMap.get( this );
-//            RefPair<T> refPair = new RefPair<T>( ref );
-//            if ( !m_bindMethods.getBind().getServiceObject( refPair, m_componentManager.getActivator().getBundleContext() ) )
-//            {
-//                //reference deactivated while we are processing.
-//                return false;
-//            }
-//            synchronized ( deps )
-//            {
-//                deps.put( ref, refPair );
-//            }
-//            return invokeBindMethod( componentInstance, refPair );
-//        }
-//        return false;
-//    }
 
     public void invokeBindMethodLate( final ServiceReference<T> ref )
     {
@@ -2131,104 +1526,6 @@
         }
 
         registerServiceListener( refMap );
-
-        //TODO deal with changes in what matches filter.
-
-
-//
-//        //wait for events to finish processing
-//        synchronized ( added )
-//        {
-//            while ( !added.isEmpty() )
-//            {
-//                try
-//                {
-//                    added.wait();
-//                }
-//                catch ( InterruptedException e )
-//                {
-//                    //??
-//                }
-//            }
-//        }
-//        synchronized ( removed )
-//        {
-//            while ( !removed.isEmpty() )
-//            {
-//                try
-//                {
-//                    removed.wait();
-//                }
-//                catch ( InterruptedException e )
-//                {
-//                    //??
-//                }
-//            }
-//        }
-//
-//        //we are now done processing all the events received before we removed the listener.
-//        ServiceReference[] boundRefs = getBoundServiceReferences();
-//        if ( boundRefs != null && m_targetFilter != null )
-//        {
-//            for ( ServiceReference boundRef : boundRefs )
-//            {
-//                if ( !m_targetFilter.match( boundRef ) )
-//                {
-//                    serviceRemoved( boundRef );
-//                }
-//            }
-//        }
-//        boolean active = m_componentManager.getDependencyMap() != null;
-//        // register the service listener
-//        registerServiceListener();
-//        Collection<ServiceReference> toAdd = new ArrayList<ServiceReference>();
-//
-//        synchronized ( enableLock )
-//        {
-//            // get the current number of registered services available
-//            ServiceReference[] refArray = getFrameworkServiceReferences();
-//            if ( refArray != null )
-//            {
-//                List<ServiceReference> refs = Arrays.asList( refArray );
-//                m_componentManager.log( LogService.LOG_DEBUG, "Component: {0} dependency: {1} refs: {2}", new Object[]
-//                        {m_componentManager.getName(), getName(), refs}, null );
-//                synchronized ( added )
-//                {
-//                    m_componentManager.log( LogService.LOG_DEBUG, "Component: {0} dependency: {1} added: {2}", new Object[]
-//                            {m_componentManager.getName(), getName(), added}, null );
-//                    added.removeAll( refs );
-//                }
-//                synchronized ( removed )
-//                {
-//                    m_componentManager.log( LogService.LOG_DEBUG, "Component: {0} dependency: {1} removed: {2}", new Object[]
-//                            {m_componentManager.getName(), getName(), removed}, null );
-//                    removed.retainAll( refs );
-//                }
-//                if ( active )
-//                {
-//                    for ( ServiceReference ref : refs )
-//                    {
-//                        if ( getBoundService( ref ) == null )
-//                        {
-//                            toAdd.add( ref );
-//                        }
-//                    }
-//                }
-//            }
-//            else
-//            {
-//                m_componentManager.log( LogService.LOG_DEBUG, "Component: {0} dependency: {1} no services", new Object[]
-//                        {m_componentManager.getName(), getName()}, null );
-//                removed.clear();//retainAll of empty set.
-//            }
-//            m_size.set( ( refArray == null ) ? 0 : refArray.length );
-//        }
-//
-//        for ( ServiceReference ref : toAdd )
-//        {
-//            serviceAdded( ref );
-//        }
-
     }
 
     private void registerServiceListener( SortedMap<ServiceReference<T>, RefPair<T>> refMap ) throws InvalidSyntaxException
