/*
 * 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.security.Permission;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.felix.scr.impl.helper.Coercions;
import org.apache.felix.scr.impl.inject.BindParameters;
import org.apache.felix.scr.impl.inject.MethodResult;
import org.apache.felix.scr.impl.inject.OpenStatus;
import org.apache.felix.scr.impl.inject.RefPair;
import org.apache.felix.scr.impl.inject.ReferenceMethod;
import org.apache.felix.scr.impl.inject.ReferenceMethods;
import org.apache.felix.scr.impl.logger.InternalLogger.Level;
import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
import org.apache.felix.scr.impl.metadata.ReferenceMetadata.ReferenceScope;
import org.apache.felix.scr.impl.metadata.ServiceMetadata.Scope;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServicePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentConstants;
import org.osgi.service.component.ComponentException;

/**
 * The <code>DependencyManager</code> manages the references to services
 * declared by a single <code>&lt;reference&gt;</code element in component
 * descriptor.
 */
public class DependencyManager<S, T> implements ReferenceManager<S, T>
{

    // the component to which this dependency belongs
    private final AbstractComponentManager<S> m_componentManager;

    // Reference to the metadata
    private final ReferenceMetadata m_dependencyMetadata;

    private final int m_index;

    private volatile Customizer<S, T> m_customizer;

    //only set once, but it's not clear there is enough other synchronization to get the correct object before it's used.
    private volatile ReferenceMethods m_bindMethods;

    //reset on filter change
    private volatile ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> m_tracker;

    // the target service filter string
    private volatile String m_target;

    private volatile int m_minCardinality;

    /**
     * Constructor that receives several parameters.
     * @param dependency An object that contains data about the dependency
     * @param index index of the dependency manager in the metadata
     */
    DependencyManager(AbstractComponentManager<S> componentManager, ReferenceMetadata dependency, int index)
    {
        m_componentManager = componentManager;
        m_dependencyMetadata = dependency;
        m_index = index;
        m_customizer = newCustomizer();

        m_minCardinality = defaultMinimumCardinality(dependency);

        // dump the reference information if DEBUG is enabled
        if (m_componentManager.getLogger().isLogEnabled(Level.DEBUG))
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "Dependency Manager created {0}",
                null, dependency.getDebugInfo());
        }
    }

    private static int defaultMinimumCardinality(ReferenceMetadata dependency)
    {
        return dependency.isOptional() ? 0 : 1;
    }

    int getIndex()
    {
        return m_index;
    }

    /**
     * Initialize binding methods.
     */
    void initBindingMethods(ReferenceMethods bindMethods)
    {
        m_bindMethods = bindMethods;
    }

    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
         * before activation.
         * @param key TODO
         * @return true if there are enough services for activation.
         */
        boolean prebind(ComponentContextImpl<S> key);

        void close();

        Collection<RefPair<S, T>> getRefs(AtomicInteger trackingCount);

        boolean isSatisfied();

        void setTracker(ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker);

        void setTrackerOpened();

        void setPreviousRefMap(Map<ServiceReference<T>, RefPair<S, T>> previousRefMap);
    }

    private abstract class AbstractCustomizer implements Customizer<S, T>
    {
        private final Map<ServiceReference<T>, RefPair<S, T>> EMPTY_REF_MAP = Collections.emptyMap();

        private volatile boolean trackerOpened;

        private volatile Map<ServiceReference<T>, RefPair<S, T>> previousRefMap = EMPTY_REF_MAP;

        @Override
        public void setTracker(ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker)
        {
            m_tracker = tracker;
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracker reset (closed)", null, getName());
            trackerOpened = false;
        }

        @Override
        public boolean isSatisfied()
        {
            return cardinalitySatisfied();
        }

        protected ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> getTracker()
        {
            return m_tracker;
        }

        /**
         *
         * @return whether the tracker
         */
        protected boolean isActive()
        {
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            return tracker != null && tracker.isActive();
        }

        protected boolean isTrackerOpened()
        {
            return trackerOpened;
        }

        @Override
        public void setTrackerOpened()
        {
            trackerOpened = true;
            m_componentManager.getLogger().log(Level.DEBUG, "dm {0} tracker opened",
                null, getName());
        }

        protected void deactivateTracker()
        {
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            if (tracker != null)
            {
                tracker.deactivate();
            }
        }

        protected Map<ServiceReference<T>, RefPair<S, T>> getPreviousRefMap()
        {
            return previousRefMap;
        }

        @Override
        public void setPreviousRefMap(Map<ServiceReference<T>, RefPair<S, T>> previousRefMap)
        {
            if (previousRefMap != null)
            {
                this.previousRefMap = previousRefMap;
            }
            else
            {
                this.previousRefMap = EMPTY_REF_MAP;
            }

        }

        protected void ungetService(RefPair<S, T> ref)
        {
            ref.ungetServiceObjects(m_componentManager.getBundleContext());
        }

        protected void tracked(int trackingCount)
        {
            m_componentManager.tracked(trackingCount);
        }

    }

    private class FactoryCustomizer extends AbstractCustomizer
    {

        @Override
        public RefPair<S, T> addingService(ServiceReference<T> serviceReference)
        {
            RefPair<S, T> refPair = newRefPair(serviceReference);
            return refPair;
        }

        @Override
        public void addedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            int serviceCount, ExtendedServiceEvent event)
        {
            if (cardinalityJustSatisfied(serviceCount))
            {
                m_componentManager.activateInternal();
            }
        }

        @Override
        public void modifiedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            ExtendedServiceEvent event)
        {
        }

        @Override
        public void removedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            ExtendedServiceEvent event)
        {
            refPair.markDeleted();
            if (!cardinalitySatisfied())
            {
                deactivateComponentManager();
            }
        }

        @Override
        public boolean prebind(ComponentContextImpl<S> key)
        {
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            if (tracker == null)
            {
                return false;
            }
            AtomicInteger trackingCount = new AtomicInteger();
            int serviceCount = tracker.getTracked(true, trackingCount).size();
            return cardinalitySatisfied(serviceCount);
        }

        @Override
        public void close()
        {
            deactivateTracker();
        }

        @Override
        public Collection<RefPair<S, T>> getRefs(AtomicInteger trackingCount)
        {
            return Collections.emptyList();
        }
    }

    private class MultipleDynamicCustomizer extends AbstractCustomizer
    {

        private RefPair<S, T> lastRefPair;
        private int lastRefPairTrackingCount;

        @Override
        public RefPair<S, T> addingService(ServiceReference<T> serviceReference)
        {
            RefPair<S, T> refPair = getPreviousRefMap().get(serviceReference);
            if (refPair == null)
            {
                refPair = newRefPair(serviceReference);
            }
            return refPair;
        }

        @Override
        public void addedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            int serviceCount, ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleDynamic added {2} (enter)",
                    null, getName(), trackingCount, serviceReference );
            boolean tracked = false;
            if (getPreviousRefMap().remove(serviceReference) == null)
            {
                if (isActive())
                {
                    m_componentManager.getLogger().log(Level.DEBUG,
                        "dm {0} tracking {1} MultipleDynamic already active, binding {2}",
                        null, getName(), trackingCount, serviceReference );
                    m_componentManager.invokeBindMethod(DependencyManager.this, refPair, trackingCount);
                    if (refPair.isFailed())
                    {
                        m_componentManager.registerMissingDependency(DependencyManager.this, serviceReference,
                            trackingCount);
                    }
                }
                else if (isTrackerOpened() && cardinalityJustSatisfied(serviceCount))
                {
                    m_componentManager.getLogger().log(Level.DEBUG,
                        "dm {0} tracking {1} MultipleDynamic, activating",
                            null, getName(), trackingCount);
                    tracked(trackingCount);
                    tracked = true;
                    m_componentManager.activateInternal();
                }
                else
                {
                    m_componentManager.getLogger().log(Level.DEBUG,
                        "dm {0} tracking {1} MultipleDynamic, inactive, doing nothing: tracker opened: {2}, optional: {3}",
                        null, getName(), trackingCount, isTrackerOpened(), isOptional() );
                }
            }
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleDynamic added {2} (exit)",
                    null, getName(), trackingCount, serviceReference );
            if (!tracked)
            {
                tracked(trackingCount);
            }
        }

        @Override
        public void modifiedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleDynamic modified {2} (enter)",
                    null, getName(), trackingCount, serviceReference );
            if (isActive())
            {
                m_componentManager.invokeUpdatedMethod(DependencyManager.this, refPair, trackingCount);
            }
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleDynamic modified {2} (exit)",
                    null, getName(), trackingCount, serviceReference );
            tracked(trackingCount);
        }

        @Override
        public void removedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleDynamic removed {2} (enter)",
                    null, getName(), trackingCount, serviceReference );
            refPair.markDeleted();
            boolean unbind = cardinalitySatisfied();
            if (unbind)
            {
                if (isActive())
                {
                    m_componentManager.invokeUnbindMethod(DependencyManager.this, refPair, trackingCount);
                }
                m_componentManager.getLogger().log(Level.DEBUG,
                    "dm {0} tracking {1} MultipleDynamic removed (unbind) {2}",
                        null, getName(), trackingCount, serviceReference );
                tracked(trackingCount);
            }
            else
            {
                lastRefPair = refPair;
                lastRefPairTrackingCount = trackingCount;
                tracked(trackingCount);
                deactivateComponentManager();
                lastRefPair = null;
                m_componentManager.getLogger().log(Level.DEBUG,
                    "dm {0} tracking {1} MultipleDynamic removed (deactivate) {2}",
                    null, getName(), trackingCount, serviceReference );
            }
            ungetService(refPair);
        }

        @Override
        public boolean prebind(ComponentContextImpl<S> key)
        {
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            if (tracker == null)
            {
                return false;
            }
            int serviceCount = 0;
            AtomicInteger trackingCount = new AtomicInteger();
            SortedMap<ServiceReference<T>, RefPair<S, T>> tracked = tracker.getTracked(
                true, trackingCount);
            List<RefPair<S, T>> failed = new ArrayList<>();
            for (RefPair<S, T> refPair : tracked.values())
            {
                if (getServiceObject(key, m_bindMethods.getBind(), refPair))
                {
                    serviceCount++;
                }
                else
                {
                    failed.add(refPair);
                }
            }
            if (cardinalitySatisfied(serviceCount))
            {
                for (RefPair<S, T> refPair : failed)
                {
                    m_componentManager.registerMissingDependency(DependencyManager.this, refPair.getRef(),
                        trackingCount.get());
                }
                return true;
            }
            return false;
        }

        @Override
        public void close()
        {
            AtomicInteger trackingCount = new AtomicInteger();
            for (RefPair<S, T> ref : getRefs(trackingCount))
            {
                ungetService(ref);
            }
            deactivateTracker();
        }

        @Override
        public Collection<RefPair<S, T>> getRefs(AtomicInteger trackingCount)
        {
            if (lastRefPair == null)
            {
                ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
                if (tracker == null)
                {
                    trackingCount.set(lastRefPairTrackingCount);
                    return Collections.emptyList();
                }
                return tracker.getTracked(null, trackingCount).values();
            }
            else
            {
                trackingCount.set(lastRefPairTrackingCount);
                return Collections.singletonList(lastRefPair);
            }
        }
    }

    private class MultipleStaticGreedyCustomizer extends AbstractCustomizer
    {

        @Override
        public RefPair<S, T> addingService(ServiceReference<T> serviceReference)
        {
            RefPair<S, T> refPair = newRefPair(serviceReference);
            return refPair;
        }

        @Override
        public void addedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            int serviceCount, ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleStaticGreedy added {2} (enter)",
                    null, getName(), trackingCount, serviceReference );
            tracked(trackingCount);
            if (isActive())
            {
                m_componentManager.getLogger().log(Level.DEBUG,
                    "Dependency Manager: Static dependency on {0}/{1} is broken",
                    null, getName(), m_dependencyMetadata.getInterface() );
                deactivateComponentManager();
                //event may be null during initial operations.
                if (event != null)
                {
                    event.addComponentManager(m_componentManager);
                }

            }
            else if (isTrackerOpened() && cardinalityJustSatisfied(serviceCount))
            {
                m_componentManager.activateInternal();
            }
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleStaticGreedy added {2} (exit)",
                    null, getName(), trackingCount, serviceReference );
        }

        @Override
        public void modifiedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleStaticGreedy modified {2} (enter)",
                null, getName(), trackingCount, serviceReference );
            boolean reactivate = false;
            if (isActive())
            {
                reactivate = m_componentManager.invokeUpdatedMethod(DependencyManager.this, refPair, trackingCount);
            }
            tracked(trackingCount);
            if (reactivate)
            {
                deactivateComponentManager();
                if (event != null)
                {
                    event.addComponentManager(m_componentManager);
                }
            }
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleStaticGreedy modified {2} (exit)",
                    null, getName(), trackingCount, serviceReference );
        }

        @Override
        public void removedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleStaticGreedy removed {2} (enter)",
                    null, getName(), trackingCount, serviceReference );
            refPair.markDeleted();
            tracked(trackingCount);
            if (isActive())
            {
                //deactivate while ref is still tracked
                m_componentManager.getLogger().log(Level.DEBUG,
                    "Dependency Manager: Static dependency on {0}/{1} is broken",
                    null, getName(), m_dependencyMetadata.getInterface() );
                deactivateComponentManager();
                //try to reactivate after ref is no longer tracked.
                if (event != null)
                {
                    event.addComponentManager(m_componentManager);
                }
            }
            else if (!cardinalitySatisfied()) //may be called from an old tracker, so getTracker() may give a different answer
            {
                m_componentManager.getLogger().log(Level.DEBUG,
                    "Dependency Manager: Static dependency on {0}/{1} is broken",
                    null, getName(), m_dependencyMetadata.getInterface() );
                deactivateComponentManager();
            }
            //This is unlikely
            ungetService(refPair);
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleStaticGreedy removed {2} (exit)",
                    null, getName(), trackingCount, serviceReference );
        }

        @Override
        public boolean prebind(ComponentContextImpl<S> key)
        {
            final ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            if (tracker == null)
            {
                return false;
            }
            int serviceCount = 0;
            AtomicInteger trackingCount = new AtomicInteger();
            SortedMap<ServiceReference<T>, RefPair<S, T>> tracked = tracker.getTracked(
                cardinalitySatisfied(tracker.getServiceCount()), trackingCount);
            for (RefPair<S, T> refPair : tracked.values())
            {
                if (getServiceObject(key, m_bindMethods.getBind(), refPair))
                {
                    serviceCount++;
                }
            }
            return cardinalitySatisfied(serviceCount);
        }

        @Override
        public void close()
        {
            AtomicInteger trackingCount = new AtomicInteger();
            for (RefPair<S, T> ref : getRefs(trackingCount))
            {
                ungetService(ref);
            }
            deactivateTracker();
        }

        @Override
        public Collection<RefPair<S, T>> getRefs(AtomicInteger trackingCount)
        {
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            if (tracker == null)
            {
                return Collections.emptyList();
            }
            return tracker.getTracked(null, trackingCount).values();
        }
    }

    private class MultipleStaticReluctantCustomizer extends AbstractCustomizer
    {

        private final AtomicReference<Collection<RefPair<S, T>>> refs = new AtomicReference<>();
        private int trackingCount;

        @Override
        public RefPair<S, T> addingService(ServiceReference<T> serviceReference)
        {
            RefPair<S, T> refPair = newRefPair(serviceReference);
            return refPair;
        }

        @Override
        public void addedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            int serviceCount, ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleStaticReluctant added {2} (enter)",
                null, getName(), trackingCount, serviceReference );
            tracked(trackingCount);
            if (isTrackerOpened() && cardinalityJustSatisfied(serviceCount) && !isActive())
            {
                m_componentManager.activateInternal();
            }
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleStaticReluctant added {2} (exit)",
                    null, getName(), trackingCount, serviceReference );
        }

        @Override
        public void modifiedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleStaticReluctant modified {2} (enter)",
                null, getName(), trackingCount, serviceReference );
            boolean reactivate = false;
            Collection<RefPair<S, T>> refs = this.refs.get();
            if (isActive() && refs.contains(refPair))
            {
                reactivate = m_componentManager.invokeUpdatedMethod(DependencyManager.this, refPair, trackingCount);
            }
            tracked(trackingCount);
            if (reactivate)
            {
                deactivateComponentManager();
                if (event != null)
                {
                    event.addComponentManager(m_componentManager);
                }
            }
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleStaticReluctant modified {2} (exit)",
                null, getName(), trackingCount, serviceReference );
        }

        @Override
        public void removedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleStaticReluctant removed {2} (enter)",
                null, getName(), trackingCount, serviceReference );
            refPair.markDeleted();
            tracked(trackingCount);
            Collection<RefPair<S, T>> refs = this.refs.get();
            if (isActive() && refs != null)
            {
                if (refs.contains(refPair))
                {
                    //we are tracking the used refs, so we can deactivate here.
                    m_componentManager.getLogger().log(Level.DEBUG,
                        "Dependency Manager: Static dependency on {0}/{1} is broken",
                        null, getName(), m_dependencyMetadata.getInterface() );
                    deactivateComponentManager();

                    // FELIX-2368: immediately try to reactivate
                    if (event != null)
                    {
                        event.addComponentManager(m_componentManager);
                    }

                }
            }
            else if (!cardinalitySatisfied())
            {
                m_componentManager.getLogger().log(Level.DEBUG,
                    "Dependency Manager: Static dependency on {0}/{1} is broken",
                    null, getName(), m_dependencyMetadata.getInterface() );
                deactivateComponentManager();
            }
            ungetService(refPair);
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} MultipleStaticReluctant removed {2} (exit)",
                null, getName(), trackingCount, serviceReference );
        }

        @Override
        public boolean prebind(ComponentContextImpl<S> key)
        {
            int serviceCount = 0;
            Collection<RefPair<S, T>> refs = this.refs.get();
            if (refs != null)
            {
                //another thread is concurrently opening, and it got done already
                for (RefPair<S, T> refPair : refs)
                {
                    if (getServiceObject(key, m_bindMethods.getBind(), refPair))
                    {
                        serviceCount++;
                    }
                }
                return cardinalitySatisfied(serviceCount);
            }
            refs = new ArrayList<>();
            AtomicInteger trackingCount = new AtomicInteger();
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            Map<ServiceReference<T>, RefPair<S, T>> tracked;
            if (tracker == null)
            {
                tracked = Collections.emptyMap();
            }
            else
            {
                tracked = tracker.getTracked(true, trackingCount);
            }
            for (RefPair<S, T> refPair : tracked.values())
            {
                if (getServiceObject(key, m_bindMethods.getBind(), refPair))
                {
                    serviceCount++;
                }
                refs.add(refPair);
            }
            if (this.refs.compareAndSet(null, refs))
            {
                this.trackingCount = trackingCount.get();
            }
            else
            {
                //some other thread got done first.  If we have more refPairs, we might need to unget some services.
                Collection<RefPair<S, T>> actualRefs = this.refs.get();
                refs.removeAll(actualRefs);
                for (RefPair<S, T> ref : refs)
                {
                    ungetService(ref);
                }
            }
            return cardinalitySatisfied(serviceCount);
        }

        @Override
        public void close()
        {
            Collection<RefPair<S, T>> refs = this.refs.getAndSet(null);
            if (refs != null)
            {
                for (RefPair<S, T> ref : refs)
                {
                    ungetService(ref);
                }
            }
            deactivateTracker();
        }

        @Override
        public Collection<RefPair<S, T>> getRefs(AtomicInteger trackingCount)
        {
            trackingCount.set(this.trackingCount);
            Collection<RefPair<S, T>> refs = this.refs.get();
            return refs == null ? Collections.<RefPair<S, T>> emptyList() : refs;
        }
    }

    private class SingleDynamicCustomizer extends AbstractCustomizer
    {

        private RefPair<S, T> refPair;
        private int trackingCount;

        @Override
        public RefPair<S, T> addingService(ServiceReference<T> serviceReference)
        {
            RefPair<S, T> refPair = getPreviousRefMap().get(serviceReference);
            if (refPair == null)
            {
                refPair = newRefPair(serviceReference);
            }
            return refPair;
        }

        @Override
        public void addedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            int serviceCount, ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} SingleDynamic added {2} (enter)",
                    null, getName(), trackingCount, serviceReference );
            boolean tracked = false;
            if (getPreviousRefMap().remove(serviceReference) == null)
            {
                if (isActive())
                {
                    boolean invokeBind = false;
                    ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
                    Object monitor = tracker == null ? null : tracker.tracked();
                    if (monitor != null)
                    {
                        synchronized (monitor)
                        {
                            invokeBind = this.refPair == null || (!isReluctant()
                                && refPair.getRef().compareTo(this.refPair.getRef()) > 0);
                        }
                    }
                    if (invokeBind)
                    {
                        m_componentManager.invokeBindMethod(DependencyManager.this, refPair, trackingCount);
                        if (!refPair.isFailed())
                        {
                            if (this.refPair != null)
                            {
                                m_componentManager.invokeUnbindMethod(DependencyManager.this, this.refPair,
                                    trackingCount);
                                closeRefPair();
                            }
                        }
                        else if (cardinalitySatisfied(0))
                        {
                            m_componentManager.registerMissingDependency(DependencyManager.this, serviceReference,
                                trackingCount);
                        }
                        this.refPair = refPair;
                    }
                }
                else if (isTrackerOpened() && cardinalityJustSatisfied(serviceCount))
                {
                    tracked(trackingCount);
                    tracked = true;
                    m_componentManager.activateInternal();
                }
            }
            this.trackingCount = trackingCount;
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} SingleDynamic added {2} (exit)",
                    null, getName(), trackingCount, serviceReference );
            if (!tracked)
            {
                tracked(trackingCount);
            }
        }

        @Override
        public void modifiedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} SingleDynamic modified {2} (enter)",
                    null, getName(), trackingCount, serviceReference );
            boolean invokeUpdated = false;
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            Object monitor = tracker == null ? null : tracker.tracked();
            if (monitor != null)
            {
                synchronized (monitor)
                {
                    invokeUpdated = isActive() && refPair == this.refPair;
                }
            }
            if (invokeUpdated)
            {
                m_componentManager.invokeUpdatedMethod(DependencyManager.this, refPair, trackingCount);
            }
            this.trackingCount = trackingCount;
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} SingleDynamic modified {2} (exit)",
                    null, getName(), trackingCount, serviceReference );
            tracked(trackingCount);
        }

        @Override
        public void removedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} SingleDynamic removed {2} (enter)",
                    null, getName(), trackingCount, serviceReference );
            refPair.markDeleted();
            boolean deactivate = false;
            boolean untracked = true;
            RefPair<S, T> oldRefPair = null;
            RefPair<S, T> nextRefPair = null;
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            Object monitor = tracker == null ? null : tracker.tracked();
            if (monitor != null)
            {
                synchronized (monitor)
                {
                    if (refPair == this.refPair && isActive())
                    {
                        if (!getTracker().isEmpty())
                        {
                            AtomicInteger trackingCount2 = new AtomicInteger();
                            SortedMap<ServiceReference<T>, RefPair<S, T>> tracked = getTracker().getTracked(
                                true, //TODO true here looks odd.
                                trackingCount2);
                            nextRefPair = tracked.values().iterator().next();
                        }

                        //n.b. we cannot use cardinalitySatisfied( serviceCount ) here as the call may come from an old tracker during target change.
                        if (isEffectivelyOptional() || nextRefPair != null)
                        {
                            oldRefPair = this.refPair;
                            this.refPair = null;
                        }
                        else
                        {
                            deactivate = true; //required and no replacement service, deactivate
                        }
                    }
                    else if (!cardinalitySatisfied() && this.refPair == null)
                    {
                        deactivate = true;
                    }
                }
            }
            if (nextRefPair != null)
            {
                m_componentManager.invokeBindMethod(DependencyManager.this, nextRefPair, trackingCount);
            }

            if (oldRefPair != null)
            {
                this.trackingCount = trackingCount;
                m_componentManager.invokeUnbindMethod(DependencyManager.this, oldRefPair, trackingCount);
                synchronized (getTracker().tracked())
                {
                    this.refPair = nextRefPair;
                }
                tracked(trackingCount);
                untracked = false;
            }
            else if (deactivate)
            {
                this.trackingCount = trackingCount;
                tracked(trackingCount);
                untracked = false;
                deactivateComponentManager();
            }
            if (oldRefPair != null)
            {
                ungetService(oldRefPair);
            }
            if (untracked) // not ours
            {
                this.trackingCount = trackingCount;
                tracked(trackingCount);
            }
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} SingleDynamic removed {2} (exit)",
                    null, getName(), trackingCount, serviceReference );
        }

        @Override
        public boolean prebind(ComponentContextImpl<S> key)
        {
            RefPair<S, T> refPair = null;
            boolean success = cardinalitySatisfied(0);
            AtomicInteger trackingCount = new AtomicInteger();
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            Object monitor = tracker == null ? null : tracker.tracked();
            if (monitor != null)
            {
                synchronized (monitor)
                {
                    if (success || !tracker.isEmpty())
                    {
                        SortedMap<ServiceReference<T>, RefPair<S, T>> tracked = tracker.getTracked(
                            true, trackingCount);
                        if (!tracked.isEmpty())
                        {
                            refPair = tracked.values().iterator().next();
                            this.refPair = refPair;
                        }
                    }
                }
            }
            if (refPair != null)
            {
                success |= getServiceObject(key, m_bindMethods.getBind(), refPair);
                if (refPair.isFailed() && cardinalitySatisfied(0))
                {
                    m_componentManager.registerMissingDependency(DependencyManager.this, refPair.getRef(),
                        trackingCount.get());
                }
            }
            return success;
        }

        @Override
        public void close()
        {
            closeRefPair();
            deactivateTracker();
        }

        private void closeRefPair()
        {
            if (refPair != null)
            {
                ungetService(refPair);
            }
            refPair = null;
        }

        @Override
        public Collection<RefPair<S, T>> getRefs(AtomicInteger trackingCount)
        {
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            Object monitor = tracker == null ? null : tracker.tracked();
            if (monitor != null)
            {
                synchronized (monitor)
                {
                    trackingCount.set(this.trackingCount);
                    return refPair == null ? Collections.<RefPair<S, T>> emptyList() : Collections.singleton(refPair);
                }
            }
            else
            {
                return Collections.<RefPair<S, T>> emptyList();
            }
        }
    }

    private class SingleStaticCustomizer extends AbstractCustomizer
    {

        private RefPair<S, T> refPair;
        private int trackingCount;

        @Override
        public RefPair<S, T> addingService(ServiceReference<T> serviceReference)
        {
            RefPair<S, T> refPair = newRefPair(serviceReference);
            return refPair;
        }

        @Override
        public void addedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            int serviceCount, ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} SingleStatic added {2} (enter)",
                    null, getName(), trackingCount, serviceReference);
            this.trackingCount = trackingCount;
            tracked(trackingCount);
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            Object monitor = tracker == null ? null : tracker.tracked();
            if (monitor != null && isActive())
            {
                boolean reactivate;
                synchronized (monitor)
                {
                    reactivate = !isReluctant()
                        && (this.refPair == null || refPair.getRef().compareTo(this.refPair.getRef()) > 0);
                }
                if (reactivate)
                {
                    deactivateComponentManager();
                    if (event != null)
                    {
                        event.addComponentManager(m_componentManager);
                    }
                }
                else
                {
                    m_componentManager.getLogger().log(Level.DEBUG,
                        "dm {0} tracking {1} SingleStatic active but new {2} is worse match than old {3}",
                        null, getName(), trackingCount, refPair, this.refPair);
                }
            }
            else if (isTrackerOpened() && cardinalityJustSatisfied(serviceCount))
            {
                m_componentManager.activateInternal();
            }
            else
            {
                m_componentManager.getLogger().log(Level.DEBUG,
                    "dm {0} tracking {1} SingleStatic active: {2} trackerOpened: {3} optional: {4}",
                    null, getName(), trackingCount, isActive(), isTrackerOpened(), isOptional() );
            }
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} SingleStatic added {2} (exit)",
                    null, getName(), trackingCount, serviceReference );
        }

        @Override
        public void modifiedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} SingleStatic modified {2} (enter)",
                    null, getName(), trackingCount, serviceReference );
            boolean invokeUpdated;
            final Object sync = getTracker().tracked();
            synchronized (sync)
            {
                invokeUpdated = isActive() && refPair == this.refPair;
            }
            boolean reactivate = false;
            if (invokeUpdated)
            {
                reactivate = m_componentManager.invokeUpdatedMethod(DependencyManager.this, refPair, trackingCount);
            }
            this.trackingCount = trackingCount;
            tracked(trackingCount);
            if (reactivate)
            {
                deactivateComponentManager();
                synchronized (sync)
                {
                    if (refPair == this.refPair)
                    {
                        this.refPair = null;
                    }
                }
                if (event != null)
                {
                    event.addComponentManager(m_componentManager);
                }
            }
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} SingleStatic modified {2} (exit)",
                    null, getName(), trackingCount, serviceReference );
        }

        @Override
        public void removedService(ServiceReference<T> serviceReference, RefPair<S, T> refPair, int trackingCount,
            ExtendedServiceEvent event)
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} SingleStatic removed {2} (enter)",
                    null, getName(), trackingCount, serviceReference );
            refPair.markDeleted();
            this.trackingCount = trackingCount;
            tracked(trackingCount);
            boolean reactivate;
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            Object monitor = tracker == null ? null : tracker.tracked();
            if (monitor != null)
            {
                synchronized (monitor)
                {
                    reactivate = (isActive() && refPair == this.refPair)
                        || (!cardinalitySatisfied(tracker.getServiceCount()));
                    if (!reactivate && refPair == this.refPair)
                    {
                        this.refPair = null;
                    }
                }
                if (reactivate)
                {
                    deactivateComponentManager();
                    synchronized (monitor)
                    {
                        if (refPair == this.refPair)
                        {
                            this.refPair = null;
                        }
                    }
                    if (event != null)
                    {
                        event.addComponentManager(m_componentManager);
                    }
                }
            }
            m_componentManager.getLogger().log(Level.DEBUG,
                "dm {0} tracking {1} SingleStatic removed {2} (exit)",
                    null, getName(), trackingCount, serviceReference );
        }

        @Override
        public boolean prebind(ComponentContextImpl<S> key)
        {
            boolean success = cardinalitySatisfied(0);
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            Object monitor = tracker == null ? null : tracker.tracked();
            if (success || (tracker != null && !tracker.isEmpty()))
            {
                RefPair<S, T> refPair = null;
                AtomicInteger trackingCount = new AtomicInteger();
                synchronized (monitor)
                {
                    SortedMap<ServiceReference<T>, RefPair<S, T>> tracked = tracker.getTracked(
                        true,
                        trackingCount);
                    if (!tracked.isEmpty())
                    {
                        refPair = tracked.values().iterator().next();
                        this.refPair = refPair;
                    }
                }
                if (refPair != null)
                {
                    success |= getServiceObject(key, m_bindMethods.getBind(), refPair);
                    if (refPair.isFailed())
                    {
                        m_componentManager.registerMissingDependency(DependencyManager.this, refPair.getRef(),
                            trackingCount.get());
                    }
                }
            }
            return success;
        }

        @Override
        public void close()
        {
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            Object monitor = tracker == null ? null : tracker.tracked();
            if (monitor != null)
            {
                RefPair<S, T> ref;
                synchronized (monitor)
                {
                    ref = refPair;
                    refPair = null;
                }
                if (ref != null)
                {
                    ungetService(ref);
                }
                tracker.deactivate();
            }
        }

        @Override
        public Collection<RefPair<S, T>> getRefs(AtomicInteger trackingCount)
        {
            ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = getTracker();
            Object monitor = tracker == null ? null : tracker.tracked();
            if (monitor != null)
            {
                synchronized (monitor)
                {
                    trackingCount.set(this.trackingCount);
                    return refPair == null ? Collections.<RefPair<S, T>> emptyList() : Collections.singleton(refPair);
                }
            }
            else
            {
                return Collections.<RefPair<S, T>> emptyList();
            }
        }
    }

    private class NoPermissionsCustomizer implements Customizer<S, T>
    {

        @Override
        public boolean prebind(ComponentContextImpl<S> key)
        {
            return false;
        }

        @Override
        public void close()
        {
        }

        @Override
        public Collection<RefPair<S, T>> getRefs(AtomicInteger trackingCount)
        {
            return Collections.emptyList();
        }

        @Override
        public boolean isSatisfied()
        {
            return isOptional();
        }

        @Override
        public void setTracker(ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tRefPairServiceTracker)
        {
        }

        @Override
        public void setTrackerOpened()
        {
        }

        @Override
        public void setPreviousRefMap(Map<ServiceReference<T>, RefPair<S, T>> previousRefMap)
        {
        }

        @Override
        public RefPair<S, T> addingService(ServiceReference<T> tServiceReference)
        {
            return null;
        }

        @Override
        public void addedService(ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount,
            int serviceCount, ExtendedServiceEvent event)
        {
        }

        @Override
        public void modifiedService(ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount,
            ExtendedServiceEvent event)
        {
        }

        @Override
        public void removedService(ServiceReference<T> tServiceReference, RefPair<S, T> service, int trackingCount,
            ExtendedServiceEvent event)
        {
        }
    }

    private String getServiceName()
    {
        return m_dependencyMetadata.getInterface();
    }

    boolean isOptional()
    {
        return m_dependencyMetadata.isOptional();
    }

    private boolean isEffectivelyOptional()
    {
        return m_minCardinality == 0;
    }

    boolean cardinalitySatisfied()
    {
        final ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = m_tracker;
        return cardinalitySatisfied(tracker == null ? 0 : tracker.getServiceCount());
    }

    public boolean cardinalitySatisfied(int serviceCount)
    {
        return m_minCardinality <= serviceCount;
    }

    private boolean cardinalityJustSatisfied(int serviceCount)
    {
        return m_minCardinality == serviceCount;
    }

    private boolean isMultiple()
    {
        return m_dependencyMetadata.isMultiple();
    }

    private boolean isStatic()
    {
        return m_dependencyMetadata.isStatic();
    }

    private boolean isReluctant()
    {
        return m_dependencyMetadata.isReluctant();
    }

    //---------- Service tracking support -------------------------------------

    void deactivate()
    {
        m_customizer.close();
    }

    /**
     * Returns the number of services currently registered in the system,
     * which match the service criteria (interface and optional target filter)
     * configured for this dependency. The number returned by this method has
     * no correlation to the number of services bound to this dependency
     * manager. It is actually the maximum number of services which may be
     * bound to this dependency manager.
     *
     * @see #isSatisfied()
     */
    int size()
    {
        AtomicInteger trackingCount = new AtomicInteger();
        final ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = m_tracker;
        if (tracker == null)
        {
            return 0;
        }
        return m_tracker.getTracked(null, trackingCount).size();
    }

    private ServiceReference<T>[] getFrameworkServiceReferences(String targetFilter)
    {
        if (hasGetPermission())
        {
            // get bundle context, may be null if component deactivated since getting bca
            BundleContext bc = m_componentManager.getActivator().getBundleContext();
            if (bc == null)
            {
                return null;
            }

            try
            {
                return (ServiceReference<T>[]) bc.getServiceReferences(m_dependencyMetadata.getInterface(),
                    targetFilter);
            }
            catch (IllegalStateException ise)
            {
                // bundle context is not valid any longer, cannot log
            }
            catch (InvalidSyntaxException ise)
            {
                m_componentManager.getLogger().log(Level.ERROR,
                    "Unexpected problem with filter ''{0}''",
                    ise, targetFilter );
                return null;
            }
        }

        m_componentManager.getLogger().log(Level.DEBUG,
            "No permission to access the services", null);
        return null;
    }

    /**
     * Returns a <code>ServiceReference</code> instances for a service
     * implementing the interface and complying to the (optional) target filter
     * declared for this dependency. If no matching service can be found
     * <code>null</code> is returned. If the configured target filter is
     * syntactically incorrect an error message is logged with the LogService
     * and <code>null</code> is returned. If multiple matching services are
     * registered the service with the highest service.ranking value is
     * returned. If multiple matching services have the same service.ranking
     * value, the service with the lowest service.id is returned.
     * <p>
     */
    private RefPair<S, T> getBestRefPair()
    {
        Collection<RefPair<S, T>> refs = m_customizer.getRefs(new AtomicInteger());
        if (refs.isEmpty())
        {
            return null;
        }
        return refs.iterator().next();
    }

    /**
     * Returns the service instance for the service reference returned by the
     * {@link #getBestRefPair()} method. If this returns a
     * non-<code>null</code> service instance the service is then considered
     * bound to this instance.
     * @param key TODO
     */
    T getService(ComponentContextImpl<S> key)
    {
        RefPair<S, T> sr = getBestRefPair();
        return getService(key, sr);
    }

    /**
     * Returns an array of service instances for the service references returned
     * by the customizer. If no services
     * match the criteria configured for this dependency <code>null</code> is
     * returned. All services returned by this method will be considered bound
     * after this method returns.
     * @param key TODO
     */
    T[] getServices(ComponentContextImpl<S> key)
    {
        Collection<RefPair<S, T>> refs = m_customizer.getRefs(new AtomicInteger());
        List<T> services = new ArrayList<>(refs.size());
        for (RefPair<S, T> ref : refs)
        {
            T service = getService(key, ref);
            if (service != null)
            {
                services.add(service);
            }
        }
        return services.isEmpty() ? null : (T[]) services.toArray(new Object[services.size()]);
    }

    //---------- bound services maintenance -----------------------------------

    /* (non-Javadoc)
     * @see org.apache.felix.scr.impl.manager.ReferenceManager#getServiceReferences()
     */
    @Override
    public List<ServiceReference<?>> getServiceReferences()
    {
        Collection<RefPair<S, T>> bound = m_customizer.getRefs(new AtomicInteger());
        List<ServiceReference<?>> result = new ArrayList<>(bound.size());
        for (RefPair<S, T> ref : bound)
        {
            result.add(ref.getRef());
        }
        return result;
    }

    /**
     * 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.
     *
     * @param serviceReference The reference to the bound service
     *
     * @return RefPair the reference and service for the reference
     *      if the service is bound or <code>null</code> if the service is not
     *      bound.
     */
    private RefPair<S, T> getRefPair(ServiceReference<T> serviceReference)
    {
        final ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = m_tracker;
        if (tracker != null)
        {
            AtomicInteger trackingCount = new AtomicInteger();
            return tracker.getTracked(null, trackingCount).get(serviceReference);
        }
        return null;
    }

    /**
     * Returns the service described by the ServiceReference. If this instance
     * is already bound the given service, that bound service instance is
     * returned. Otherwise the service retrieved from the service registry
     * and kept as a bound service for future use.
     * @param key TODO
     * @param serviceReference The reference to the service to be returned
     *
     * @return The requested service or <code>null</code> if no service is
     *      registered for the service reference (any more).
     */
    T getService(ComponentContextImpl<S> key, ServiceReference<T> serviceReference)
    {
        // check whether we already have the service and return that one
        RefPair<S, T> refPair = getRefPair(serviceReference);
        return getService(key, refPair);
    }

    private T getService(ComponentContextImpl<S> key, RefPair<S, T> refPair)
    {
        if (refPair == null)
        {
            //we don't know about this reference
            return null;
        }
        T serviceObject;
        if ((serviceObject = refPair.getServiceObject(key)) != null)
        {
            return serviceObject;
        }
        // otherwise acquire the service
        final BundleContext bundleContext = m_componentManager.getBundleContext();
        if (bundleContext == null)
        {
            m_componentManager.getLogger().log(Level.ERROR,
                "Bundle shut down while getting service {0} ({1}/{2,number,#})", null, getName(),
                        m_dependencyMetadata.getInterface(), refPair.getRef().getProperty(Constants.SERVICE_ID) );
            return null;
        }
        try
        {
            refPair.getServiceObject(key, bundleContext);
            serviceObject = refPair.getServiceObject(key);
        }
        catch (Exception e)
        {
            // caused by getService() called on invalid bundle context
            // or if there is a service reference cycle involving service
            // factories !
            m_componentManager.getLogger().log(Level.ERROR,
                "Failed getting service {0} ({1}/{2,number,#})",
                e, getName(), m_dependencyMetadata.getInterface(),
                        refPair.getRef().getProperty(Constants.SERVICE_ID) );
            return null;
        }

        // return the acquired service (may be null of course)
        //even if we did not set the service object, all the getService are for the same bundle so will have the same object.
        return serviceObject;
    }

    //---------- DependencyManager core ---------------------------------------

    /* (non-Javadoc)
     * @see org.apache.felix.scr.impl.manager.ReferenceManager#getName()
     */
    @Override
    public String getName()
    {
        return m_dependencyMetadata.getName();
    }

    public ReferenceMetadata getReferenceMetadata()
    {
        return m_dependencyMetadata;
    }

    /**
     * Returns <code>true</code> if this dependency manager is satisfied, that
     * is if either the dependency is optional or the number of services
     * registered in the framework and available to this dependency manager is
     * not zero.
     */
    @Override
    public boolean isSatisfied()
    {
        return m_customizer.isSatisfied();
    }

    /**
     * Returns <code>true</code> if the component providing bundle has permission
     * to get the service described by this reference.
     */
    public boolean hasGetPermission()
    {
        if (System.getSecurityManager() != null)
        {
            Permission perm = new ServicePermission(getServiceName(), ServicePermission.GET);
            return m_componentManager.getBundle().hasPermission(perm);
        }

        // no security manager, hence permission given
        return true;
    }

    boolean prebind(ComponentContextImpl<S> key)
    {
        return m_customizer.prebind(key);
    }

    public static final class OpenStatusImpl<S, T> implements OpenStatus<S, T> {
        private final DependencyManager<S, T> dm;

        OpenStatusImpl(DependencyManager<S, T> dm) {
            this.dm = dm;
        }
        @Override
        public Collection<RefPair<S, T>> getRefs(AtomicInteger trackingCount) {
            return dm.m_customizer.getRefs(trackingCount);
        }
    }

    /**
     * initializes a dependency. This method binds all of the service
     * occurrences to the instance object
     * @param edgeInfo Edge info for the combination of this component instance and this dependency manager.
     *
     * @return true if the dependency is satisfied and at least the minimum
     *      number of services could be bound. Otherwise false is returned.
     */
    OpenStatus<S, T> open(ComponentContextImpl<S> componentContext, EdgeInfo edgeInfo)
    {
        int serviceCount = 0;
        final OpenStatus<S, T> status = new OpenStatusImpl<>(this);
        Collection<RefPair<S, T>> refs;
        AtomicInteger trackingCount = new AtomicInteger();
        CountDownLatch openLatch;
        synchronized (m_tracker.tracked())
        {
            refs = m_customizer.getRefs(trackingCount);
            edgeInfo.setOpen(trackingCount.get());
            openLatch = edgeInfo.getOpenLatch();
        }
        m_componentManager.getLogger().log(Level.DEBUG,
            "For dependency {0}, optional: {1}; to bind: {2}",
                null, getName(), isOptional(), refs);
        for (RefPair<S, T> refPair : refs)
        {
            if (!refPair.isDeleted() && !refPair.isFailed())
            {
                serviceCount++;
            }
        }
        openLatch.countDown();
        return (cardinalitySatisfied(serviceCount) ? status : null);
    }

    boolean bind(final ComponentContextImpl<S> componentContext, final OpenStatus<S, T> status)
    {
        if (!invokeInitMethod(componentContext))
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "For dependency {0}, failed to initialize object",
                    null, getName());
            return false;
        }
        final ReferenceMethod bindMethod = m_bindMethods.getBind();
        return this.bindDependency(componentContext, bindMethod, status);
    }

    boolean bindDependency(final ComponentContextImpl<S> componentContext,
            final ReferenceMethod bindMethod,
            final OpenStatus<S, T> status)
    {
        int serviceCount = 0;
        AtomicInteger trackingCount = new AtomicInteger();
        for (final RefPair<S, T> refPair : status.getRefs(trackingCount))
        {
            if (!refPair.isDeleted() && !refPair.isFailed())
            {
                if (!doInvokeBindMethod(componentContext, bindMethod, refPair, trackingCount.get()))
                {
                    m_componentManager.getLogger().log(Level.DEBUG,
                        "For dependency {0}, failed to invoke bind method on object {1}",
                        null, getName(), refPair );

                }
                serviceCount++;
            }
        }
        return cardinalitySatisfied(serviceCount);
    }

    /**
     * Revoke the given bindings. This method cannot throw an exception since
     * it must try to complete all that it can
     * @param componentContext instance we are unbinding from.
     * @param edgeInfo EdgeInfo for the combination of this component instance and this dependency manager.
     */
    void close(ComponentContextImpl<S> componentContext, EdgeInfo edgeInfo)
    {
        // only invoke the unbind method if there is an instance (might be null
        // in the delayed component situation) and the unbind method is declared.
        boolean doUnbind =
            componentContext != null &&
                (m_dependencyMetadata.getField() != null || m_dependencyMetadata.getUnbind() != null);

        AtomicInteger trackingCount = new AtomicInteger();
        Collection<RefPair<S, T>> refPairs;
        CountDownLatch latch;
        synchronized (m_tracker.tracked())
        {
            refPairs = m_customizer.getRefs(trackingCount);
            edgeInfo.setClose(trackingCount.get());
            latch = edgeInfo.getCloseLatch();
        }

        m_componentManager.getLogger().log(Level.DEBUG,
            "DependencyManager: {0} close component unbinding from {1} at tracking count {2} refpairs: {3}",
            null, getName(), componentContext, trackingCount.get(), refPairs );
        m_componentManager.waitForTracked(trackingCount.get());
        for (RefPair<S, T> boundRef : refPairs)
        {
            if (doUnbind && !boundRef.isFailed())
            {
                invokeUnbindMethod(componentContext, boundRef, trackingCount.get(), edgeInfo);
            }

            boundRef.ungetServiceObject(componentContext);

        }
        latch.countDown();
    }

    public void invokeBindMethodLate(final ServiceReference<T> ref, int trackingCount)
    {
        final ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = m_tracker;
        if (tracker == null || !tracker.isActive())
        {
            m_componentManager.notifyWaiters();
            return;
        }
        if ( !isSatisfied() )
        {
            return;
        }
        if (!isMultiple())
        {
            Collection<RefPair<S, T>> refs = m_customizer.getRefs(new AtomicInteger());
            if (refs.isEmpty())
            {
                return;
            }
            RefPair<S, T> test = refs.iterator().next();
            if (ref != test.getRef())
            {
                //another ref is now better
                return;
            }
        }
        //TODO dynamic reluctant
        RefPair<S, T> refPair = tracker.getService(ref);
        if (refPair == null)
        {
            return; // The service is no longer available, probably because the tracker has been closed
        }
        //TODO this check is no longer correct, fix it!
        //        if (refPair.getServiceObject(key) != null)
        //        {
        //            m_componentManager.getLogger().log( LogLevel.DEBUG,
        //                    "DependencyManager : late binding of service reference {1} skipped as service has already been located",
        //                    new Object[] {ref}, null );
        //            //something else got the reference and may be binding it.
        //            return;
        //        }
        m_componentManager.invokeBindMethod(this, refPair, trackingCount);
    }

    /**
     * Calls the optional init reference method.
     */
    boolean invokeInitMethod(final ComponentContextImpl<S> componentContext)
    {
        // The bind method is only invoked if the implementation object is not
        // null. This is valid for both immediate and delayed components
        if (m_bindMethods.getInit() != null)
        {
            final Object componentInstance = componentContext.getImplementationObject(false);
            if (componentInstance != null)
            {
                return m_bindMethods.getInit().init(componentInstance, componentContext.getLogger());
            }
        }
        return true;
    }

    /**
     * Calls the bind method. In case there is an exception while calling the
     * bind method, the service is not considered to be bound to the instance
     * object
     * <p>
     * If the reference is singular and a service has already been bound to the
     * component this method has no effect and just returns <code>true</code>.
     *
     *
     *
     * @param componentContext instance we are binding to
     * @param refPair the service reference, service object tuple.
     * @param trackingCount service event counter for this service.
     * @param edgeInfo EdgeInfo for the combination of this instance and this dependency manager.
     * @return true if the service should be considered bound. If no bind
     *      method is found or the method call fails, <code>true</code> is
     *      returned. <code>false</code> is only returned if the service must
     *      be handed over to the bind method but the service cannot be
     *      retrieved using the service reference.
     */
    boolean invokeBindMethod(ComponentContextImpl<S> componentContext, RefPair<S, T> refPair, int trackingCount,
        EdgeInfo info)
    {
        // The bind method is only invoked if the implementation object is not
        // null. This is valid for both immediate and delayed components
        if (componentContext.getImplementationObject(false) != null)
        {
            synchronized (m_tracker.tracked())
            {
                if (info.outOfRange(trackingCount))
                {
                    //ignore events before open started or we will have duplicate binds.
                    return true;
                }
            }
            //edgeInfo open has been set, so binding has started.
            return doInvokeBindMethod(componentContext, m_bindMethods.getBind(), refPair, trackingCount);

        }
        else
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "DependencyManager : component not yet created, assuming bind method call succeeded", null);

            return true;
        }
    }

    private boolean doInvokeBindMethod(ComponentContextImpl<S> componentContext,
            final ReferenceMethod bindMethod,
            RefPair<S, T> refPair,
        int trackingCount)
    {
        if (!getServiceObject(componentContext, bindMethod, refPair))
        {
            m_componentManager.getLogger().log(Level.WARN,
                "DependencyManager : invokeBindMethod : Service not available from service registry for ServiceReference {0} for reference {1}",
                null, refPair.getRef(), getName() );
            return false;

        }
        MethodResult result = bindMethod.invoke(componentContext.getImplementationObject(false),
            new BindParameters(componentContext, refPair), MethodResult.VOID);
        if (result == null)
        {
            return false;
        }
        m_componentManager.setServiceProperties(result, trackingCount);
        return true;
    }

    /**
     * Calls the updated method.
     *
     * @param componentContext instance we are calling updated on.
     * @param refPair A service reference corresponding to the service whose service
     * @param edgeInfo EdgeInfo for the combination of this instance and this dependency manager.
     * @return {@code true} if reactivation is required.
     */
    boolean invokeUpdatedMethod(ComponentContextImpl<S> componentContext, final RefPair<S, T> refPair,
        int trackingCount, EdgeInfo info)
    {
        final ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = m_tracker;
        final Object monitor = tracker == null ? null : tracker.tracked();
        if (monitor == null)
        {
            return false;
        }
        if (m_dependencyMetadata.getUpdated() == null && m_dependencyMetadata.getField() == null)
        {
            return false;
        }
        // The updated method is only invoked if the implementation object is not
        // null. This is valid for both immediate and delayed components
        if (componentContext != null)
        {
            synchronized (monitor)
            {
                if (info.outOfRange(trackingCount))
                {
                    //ignore events after close started or we will have duplicate unbinds.
                    return false;
                }
            }
            info.waitForOpen(m_componentManager, getName(), "invokeUpdatedMethod");
            if (!getServiceObject(componentContext, m_bindMethods.getUpdated(), refPair))
            {
                m_componentManager.getLogger().log(Level.WARN,
                    "DependencyManager : invokeUpdatedMethod : Service not available from service registry for ServiceReference {0} for reference {1}",
                    null, refPair.getRef(), getName() );
                return false;

            }
            final MethodResult methodResult = m_bindMethods.getUpdated().invoke(
                componentContext.getImplementationObject(false), new BindParameters(componentContext, refPair), MethodResult.VOID);
            if (methodResult != null)
            {
                m_componentManager.setServiceProperties(methodResult, trackingCount);
            }
            return methodResult == MethodResult.REACTIVATE;
        }
        else
        {
            // don't care whether we can or cannot call the updated method
            // if the component instance has already been cleared by the
            // close() method
            m_componentManager.getLogger().log(Level.DEBUG,
                "DependencyManager : Component not set, no need to call updated method", null);
        }
        return false;
    }

    /**
     * Calls the unbind method.
     * <p>
     * If the reference is singular and the given service is not the one bound
     * to the component this method has no effect and just returns
     * <code>true</code>.
     *
     * @param componentContext instance we are unbinding from
     * @param refPair A service reference, service pair that will be unbound
     * @param trackingCount service event count for this reference
     * @param info EdgeInfo for the combination of this instance and this dependency manager
     */
    void invokeUnbindMethod(ComponentContextImpl<S> componentContext, final RefPair<S, T> refPair, int trackingCount,
        EdgeInfo info)
    {
        final ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = m_tracker;
        Object monitor = tracker == null ? null : tracker.tracked();
        if (monitor == null)
        {
            return;
        }
        // The unbind method is only invoked if the implementation object is not
        // null. This is valid for both immediate and delayed components
        if (componentContext != null)
        {
            synchronized (monitor)
            {
                if (info.beforeRange(trackingCount))
                {
                    //never bound
                    return;
                }
            }
            info.waitForOpen(m_componentManager, getName(), "invokeUnbindMethod");
            boolean outOfRange;
            synchronized (monitor)
            {
                outOfRange = info.afterRange(trackingCount);
            }
            if (outOfRange)
            {
                //wait for unbinds to complete
                info.waitForClose(m_componentManager, getName(), "invokeUnbindMethod");
                //ignore events after close started or we will have duplicate unbinds.
                return;
            }

            if (!getServiceObject(componentContext, m_bindMethods.getUnbind(), refPair))
            {
                m_componentManager.getLogger().log(Level.WARN,
                    "DependencyManager : invokeUnbindMethod : Service not available from service registry for ServiceReference {0} for reference {1}",
                    null, refPair.getRef(), getName() );
                return;

            }
            MethodResult methodResult = m_bindMethods.getUnbind().invoke(
                componentContext.getImplementationObject(false), new BindParameters(componentContext, refPair), MethodResult.VOID);
            if (methodResult != null)
            {
                m_componentManager.setServiceProperties(methodResult, trackingCount);
            }
            componentContext.getComponentServiceObjectsHelper().closeServiceObjects(refPair.getRef());
        }
        else
        {
            // don't care whether we can or cannot call the unbind method
            // if the component instance has already been cleared by the
            // close() method
            m_componentManager.getLogger().log(Level.DEBUG,
                "DependencyManager : Component not set, no need to call unbind method", null);
        }
    }

    //------------- Service target filter support -----------------------------

    /**
     * Returns <code>true</code> if the <code>properties</code> can be
     * dynamically applied to the component to which the dependency manager
     * belongs.
     * <p>
     * This method applies the following heuristics (in the given order):
     * <ol>
     * <li>If there is no change in the target filter for this dependency, the
     * properties can be applied</li>
     * <li>If the dependency is static and there are changes in the target
     * filter we cannot dynamically apply the configuration because the filter
     * may (assume they do for simplicity here) cause the bindings to change.</li>
     * <li>If there is still at least one service matching the new target filter
     * we can apply the configuration because the depdency is dynamic.</li>
     * <li>If there are no more services matching the filter, we can still
     * apply the configuration if the dependency is optional.</li>
     * <li>Ultimately, if all other checks do not apply we cannot dynamically
     * apply.</li>
     * </ol>
     */
    boolean canUpdateDynamically(Map<String, Object> properties)
    {
        // 1. no target filter change
        final String newTarget = (String) properties.get(m_dependencyMetadata.getTargetPropertyName());
        final String currentTarget = getTarget();
        int newMinimumCardinality = getMinimumCardinality(properties);
        if (m_minCardinality == newMinimumCardinality && ((currentTarget == null && newTarget == null)
            || (currentTarget != null && currentTarget.equals(newTarget))))
        {
            // can update if target filter is not changed, since there is
            // no change is service binding
            return true;
        }
        // invariant: target filter change

        // 2. if static policy, cannot update dynamically
        // (for simplicity assuming change in target service binding)
        if (m_dependencyMetadata.isStatic())
        {
            // cannot update if services are statically bound and the target
            // filter is modified, since there is (potentially at least)
            // a change is service bindings
            return false;
        }
        // invariant: target filter change + dynamic policy

        // 3. check optionality
        if (newMinimumCardinality == 0)
        {
            // can update since even if no service matches the new filter, this
            // makes no difference because the dependency is optional
            return true;
        }
        // invariant: target filter change + mandatory + dynamic policy

        // 4. check target services matching the new filter
        ServiceReference<T>[] refs = getFrameworkServiceReferences(newTarget);
        if (refs != null)
        {
            // Return whether there are enough target services
            return newMinimumCardinality <= refs.length;
        }
        // invariant: target filter change + dynamic policy + no more matching service + required

        // 5. There are no services, and some are required.
        return false;
    }

    /**
     * Sets the target filter from target filter property contained in the
     * properties. The filter is taken from a property whose name is derived
     * from the dependency name and the suffix <code>.target</code> as defined
     * for target properties on page 302 of the Declarative Services
     * Specification, section 112.6.
     *
     * @param properties The properties containing the optional target service
     *      filter property
     */
    void setTargetFilter(Map<String, Object> properties)
    {
        Integer minimumCardinality = getMinimumCardinality(properties);
        setTargetFilter((String) properties.get(m_dependencyMetadata.getTargetPropertyName()), minimumCardinality);
    }

    private int getMinimumCardinality(Map<String, Object> properties)
    {
        Integer minimumCardinality = null;
        try
        {
            minimumCardinality = Coercions.coerceToInteger(
                properties.get(m_dependencyMetadata.getMinCardinalityName()));
        }
        catch (ComponentException e)
        {
            m_componentManager.getLogger().log(Level.WARN,
                "Invalid minimum cardinality property for dependency {0}: {1}",
                null, getName(), e.getMessage());
        }
        if (minimumCardinality != null && (minimumCardinality < defaultMinimumCardinality(m_dependencyMetadata)
            || (!m_dependencyMetadata.isMultiple() && minimumCardinality > 1)))
        {
            minimumCardinality = null;
        }
        if (minimumCardinality == null)
        {
            minimumCardinality = defaultMinimumCardinality(m_dependencyMetadata);
        }
        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
     * new target filter is the same as the old target filter, this method has
     * not effect. Otherwise any services currently bound but not matching the
     * new filter are unbound. Likewise any registered services not currently
     * bound but matching the new filter are bound.
     *
     * @param target The new target filter to be set. This may be
     *      <code>null</code> if no target filtering is to be used.
     */
    private void setTargetFilter(String target, int minimumCardinality)
    {
        // if configuration does not set filter, use the value from metadata
        if (target == null)
        {
            target = m_dependencyMetadata.getTarget();
        }
        // do nothing if target filter does not change
        if ((m_target == null && target == null) || (m_target != null && m_target.equals(target)))
        {
            m_componentManager.getLogger().log(Level.DEBUG,
                "No change in target property for dependency {0}: currently registered: {1}",
                null, getName(), m_tracker != null );
            if (m_tracker != null)
            {
                m_minCardinality = minimumCardinality;
                return;
            }
        }
        if (target != null)
        {
            try
            {
                FrameworkUtil.createFilter(target);
            }
            catch (InvalidSyntaxException e)
            {
                m_componentManager.getLogger().log(Level.ERROR,
                        "Invalid syntax in target property for dependency {0} to {1}", null,
                        getName(), target);

                //create a filter that will never be satisfied
                target = "(&(invalid.target.cannot.resolve=*)(!(invalid.target.cannot.resolve=*)))";
            }
        }
        m_target = target;

        // two filters are created:
        // classFilter = filters only on the service interface
        // initialReferenceFilter = classFilter & eventFilter

        // classFilter
        // "(" + Constants.OBJECTCLASS + "=" + m_dependencyMetadata.getInterface() + ")"
        final StringBuilder classFilterSB = new StringBuilder();
        classFilterSB.append(OBJECTCLASS_CLAUSE);
        classFilterSB.append(m_dependencyMetadata.getInterface());
        classFilterSB.append(')');
        final String classFilterString = classFilterSB.toString();

        // initialReferenceFilter
        final boolean multipleExpr = m_target != null
                || m_dependencyMetadata.getScope() == ReferenceScope.prototype_required;
        final StringBuilder initialReferenceFilterSB = new StringBuilder();
        if (multipleExpr)
        {
            initialReferenceFilterSB.append("(&");
        }
        initialReferenceFilterSB.append(classFilterString);

        // if reference scope is prototype_required, we simply add
        // (service.scope=prototype) to the filter
        if (m_dependencyMetadata.getScope() == ReferenceScope.prototype_required)
        {
            initialReferenceFilterSB.append(PROTOTYPE_SCOPE_CLAUSE);
        }

        // append target
        if (m_target != null)
        {
            initialReferenceFilterSB.append(m_target);
        }
        if (multipleExpr)
        {
            initialReferenceFilterSB.append(')');
        }
        String initialReferenceFilterString = initialReferenceFilterSB.toString();

        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)
        {
            //wait for service events to complete before processing initial set from new tracker.
            m_componentManager.waitForTracked(trackingCount.get());
        }
        m_componentManager.getLogger().log(Level.DEBUG,
            "Setting target property for dependency {0} to {1}",
                null, getName(), target );
        BundleContext bundleContext = m_componentManager.getBundleContext();

        m_customizer.setPreviousRefMap(refMap);
        boolean initialActive = oldTracker != null && oldTracker.isActive();
        m_componentManager.getLogger().log(Level.DEBUG,
            "New service tracker for {0}, initial active: {1}, previous references: {2}, classFilter: {3}, initialReferenceFilter {4}",
            null, getName(), initialActive, refMap, classFilterString,
                    initialReferenceFilterString );
        ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = new ServiceTracker<>(
            bundleContext, m_customizer, initialActive, m_componentManager.getActivator(),
            initialReferenceFilterString);
        m_customizer.setTracker(tracker);
        //set minimum cardinality
        m_minCardinality = minimumCardinality;

        tracker.open(m_componentManager.getTrackingCount());
        m_customizer.setTrackerOpened();
        if (oldTracker != null)
        {
            oldTracker.completeClose(refMap);
        }
        m_componentManager.getLogger().log(Level.DEBUG,
            "registering service listener for dependency {0}",
                null, getName());
    }

    private Customizer<S, T> newCustomizer()
    {
        Customizer<S, T> customizer;
        if (!hasGetPermission())
        {
            customizer = new NoPermissionsCustomizer();
            m_componentManager.getLogger().log(Level.INFO,
                "No permission to get services for {0}",
                    null, getName());
        }
        else if (m_componentManager.isFactory())
        {
            customizer = new FactoryCustomizer();
        }
        else if (isMultiple())
        {
            if (isStatic())
            {
                if (isReluctant())
                {
                    customizer = new MultipleStaticReluctantCustomizer();
                }
                else
                {
                    customizer = new MultipleStaticGreedyCustomizer();
                }
            }
            else
            {
                customizer = new MultipleDynamicCustomizer();
            }
        }
        else
        {
            if (isStatic())
            {
                customizer = new SingleStaticCustomizer();
            }
            else
            {
                customizer = new SingleDynamicCustomizer();
            }
        }
        return customizer;
    }

    SortedMap<ServiceReference<T>, RefPair<S, T>> unregisterServiceListener(AtomicInteger trackingCount)
    {
        SortedMap<ServiceReference<T>, RefPair<S, T>> refMap;
        ServiceTracker<T, RefPair<S, T>, ExtendedServiceEvent> tracker = m_tracker;
        if (tracker != null)
        {
            refMap = tracker.close(trackingCount);
            m_tracker = null;
            m_componentManager.getLogger().log(Level.DEBUG,
                "unregistering service listener for dependency {0}",
                    null, getName());
        }
        else
        {
            refMap = new TreeMap<>(Collections.reverseOrder());
            m_componentManager.getLogger().log(Level.DEBUG,
                " No existing service listener to unregister for dependency {0}", null, getName());
            trackingCount.set(-1);
        }
        //        m_registered = false;
        return refMap;
    }

    /* (non-Javadoc)
     * @see org.apache.felix.scr.impl.manager.ReferenceManager#getTarget()
     */
    @Override
    public String getTarget()
    {
        return m_target;
    }

    @Override
    public String toString()
    {
        return "DependencyManager: Component [" + m_componentManager + "] reference [" + getName() + "]";
    }

    boolean getServiceObject(ComponentContextImpl<S> key, ReferenceMethod bindMethod, RefPair<S, T> refPair)
    {
        BundleContext bundleContext = m_componentManager.getBundleContext();
        if (bundleContext != null)
        {
            return bindMethod.getServiceObject(new BindParameters(key, refPair), bundleContext);
        }
        else
        {
            refPair.markFailed();
            return false;
        }
    }

    RefPair<S, T> newRefPair(ServiceReference<T> serviceReference)
    {
        if (m_dependencyMetadata.getScope() == ReferenceScope.bundle)
        {
            return new SingleRefPair<>(serviceReference);
        }
        if (m_componentManager.getComponentMetadata().getServiceScope() == Scope.singleton)
        {
            return new SinglePrototypeRefPair<>(serviceReference);
        }
        return new MultiplePrototypeRefPair<>(serviceReference);
    }

    private void deactivateComponentManager()
    {
        m_componentManager.deactivateInternal(ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, false);
    }

}
