/*
 * 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.dm.impl;

import static org.apache.felix.dm.ComponentState.INACTIVE;
import static org.apache.felix.dm.ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED;
import static org.apache.felix.dm.ComponentState.STARTED;
import static org.apache.felix.dm.ComponentState.STARTING;
import static org.apache.felix.dm.ComponentState.STOPPED;
import static org.apache.felix.dm.ComponentState.STOPPING;
import static org.apache.felix.dm.ComponentState.TRACKING_OPTIONAL;
import static org.apache.felix.dm.ComponentState.WAITING_FOR_REQUIRED;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.apache.felix.dm.Component;
import org.apache.felix.dm.ComponentDeclaration;
import org.apache.felix.dm.ComponentDependencyDeclaration;
import org.apache.felix.dm.ComponentExecutorFactory;
import org.apache.felix.dm.ComponentState;
import org.apache.felix.dm.ComponentStateListener;
import org.apache.felix.dm.Dependency;
import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.Logger;
import org.apache.felix.dm.context.ComponentContext;
import org.apache.felix.dm.context.DependencyContext;
import org.apache.felix.dm.context.Event;
import org.apache.felix.dm.context.EventType;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.PrototypeServiceFactory;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.log.LogService;

/**
 * Dependency Manager Component implementation.
 * 
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class ComponentImpl implements Component, ComponentContext, ComponentDeclaration {
    /**
     * NullObject ServiceRegistration that is injected in components that don't provide any services. 
     */
	private static final ServiceRegistration<?> NULL_REGISTRATION = (ServiceRegistration<?>) Proxy
			.newProxyInstance(ComponentImpl.class.getClassLoader(),
					new Class[] { ServiceRegistration.class },
					new DefaultNullObject());
	        	
    /**
	 * Constant Used to get empty constructor by reflection. 
     */
    private static final CallbackTypeDef VOID = new CallbackTypeDef(new Class[][] {{}}, new Object[][] {{}});

    /**
     * Default Component Executor, which is by default single threaded. The first thread which schedules a task
     * is the master thread and will execute all tasks that are scheduled by other threads at the time the master
     * thread is executing. Internal tasks scheduled by the master thread are executed immediately (inline execution).
     * 
     * If a ComponentExecutorFactory is provided in the OSGI registry, then this executor will be replaced by the
     * executor returned by the ComponentExecutorFactory (however, the same semantic of the default executor is used: 
     * all tasks are serially executed).
     * 
     * @see @link {@link ComponentExecutorFactory}
     */
	private volatile Executor m_executor;
	
	/**
	 * The current state of the component state machine.
	 */
	private ComponentState m_state = ComponentState.INACTIVE;
	
    /**
     * Indicates that the handleChange method is currently being executed.
     */
    private boolean m_handlingChange;
    
    /**
     * List of dependencies. We use a COW list in order to avoid ConcurrentModificationException while iterating on the 
     * list and while a component synchronously add more dependencies from one of its callback method.
     */
	private final CopyOnWriteArrayList<DependencyContext> m_dependencies = new CopyOnWriteArrayList<>();
	
	/**
	 * List of Component state listeners. We use a COW list in order to avoid ConcurrentModificationException while iterating on the 
     * list and while a component synchronously adds more listeners from one of its callback method.
	 */
	private final List<ComponentStateListener> m_listeners = new CopyOnWriteArrayList<>();
	
	/**
	 * Is the component active ?
	 */
	private boolean m_isStarted;
	
	/**
	 * The Component logger.
	 */
    private final Logger m_logger;
    
    /**
     * The Component bundle context.
     */
    private final BundleContext m_context;
    
    /**
     * The DependencyManager object that has created this component.
     */
    private final DependencyManager m_manager;
    
    /**
     * The object used to create the component. Can be a class name, or the component implementation instance.
     */
    private volatile Object m_componentDefinition;
    
    /**
     * The component instance.
     */
	private Object m_componentInstance;
	
	/**
	 * The service(s) provided by this component. Can be a String, or a String array.
	 */
    private volatile Object m_serviceName;
    
    /**
     * The service properties, if this component is providing a service.
     */
    private volatile Dictionary<Object, Object> m_serviceProperties;
    
    /**
     * The component service registration. Can be a NullObject in case the component does not provide a service.
     */
    private volatile ServiceRegistration<?> m_registration;
    
    /**
     * The component name as it must be returned by getName.
     */
    private volatile String m_componentName;
    
    /**
     * Map of auto configured fields (BundleContext, ServiceRegistration, DependencyManager, or Component).
     * By default, all fields mentioned above are auto configured (injected in class fields having the same type).
     */
    private final Map<Class<?>, Boolean> m_autoConfig = new ConcurrentHashMap<>();
    
    /**
     * Map of auto configured instance fields that will be used when injected auto configured fields.
     * @see #m_autoConfig
     */
    private final Map<Class<?>, String> m_autoConfigInstance = new ConcurrentHashMap<>();
    
    /**
     * Data structure used to record the elapsed time used by component lifecycle callbacks.
     * Key = callback name ("init", "start", "stop", "destroy").
     * Value = elapsed time in nanos.
     */
    private final Map<String, Long> m_stopwatch = new ConcurrentHashMap<>();
    
    /**
     * Unique component id.
     */
    private final long m_id;
    
    /**
     * Unique ID generator.
     */
    private final static AtomicLong m_idGenerator = new AtomicLong();
    
    /**
     * Holds all the services of a given dependency context. Caution: the last entry in the skiplist is the highest 
     * ranked service.
     */
    private final Map<DependencyContext, ConcurrentSkipListSet<Event>> m_dependencyEvents = new HashMap<>();
    
    /**
     * Flag used to check if this component has been added in a DependencyManager object.
     */
    private final AtomicBoolean m_active = new AtomicBoolean(false);
        
    /**
     * Init lifecycle callback. From that method, component are expected to add more extra dependencies.
     * When this callback is invoked, all required dependencies have been injected. 
     */
    private volatile String m_callbackInit;
    
    /**
     * Start lifecycle callback. When this method is called, all required + all extra required dependencies defined in the
     * init callback have been injected. The component may then perform its initialization.
     */
    private volatile String m_callbackStart;
    
    /**
     * Stop callback. When this method is called, the component has been unregistered (if it provides any services),
     * and all optional dependencies have been unbound.
     */
    private volatile String m_callbackStop;
    
    /**
     * Destroy callback. When this method is called, all required dependencies defined in the init method have been unbound.
     * After this method is called, then all required dependencies defined in the Activator will be unbound.
     */
    private volatile String m_callbackDestroy;
    
    /**
     * By default, the init/start/stop/destroy callbacks are invoked on the component instance(s).
     * But you can specify a separate callback instance.
     */
    private volatile Object m_callbackInstance;
    
    /**
     * Component Factory instance object, that can be used to instantiate the component instance.
     */
	private volatile Object m_instanceFactory;
	
	/**
	 * Name of the Factory method to call.
	 */
	private volatile String m_instanceFactoryCreateMethod;
	
	/**
	 * Composition Manager that can be used to create a graph of objects that are used to implement the component.
	 */
	private volatile Object m_compositionManager;
	
	/**
	 * Name of the method used to invoke in order to get the list of component instance objects.
	 */
	private volatile String m_compositionManagerGetMethod;
	
	/**
	 * The composition manager instance object, if specified.
	 */
	private volatile Object m_compositionManagerInstance;
	
	/**
	 * The Component bundle.
	 */
    private final Bundle m_bundle;
        
    /**
     * Cache of callback invocation used to avoid calling the same callback twice.
     * This situation may sometimes happen when the state machine triggers a lifecycle callback ("bind" call), and
     * when the bind method registers a service which is tracked by another optional component dependency.
     * 
     * @see org.apache.felix.dm.itest.api.FELIX4913_OptionalCallbackInvokedTwiceTest which reproduces the use case.
     */
    private final Map<Event, Event> m_invokeCallbackCache = new IdentityHashMap<>();

    /**
     * Flag used to check if the start callback has been invoked.
     * We use this flag to ensure that we only inject optional dependencies after the start callback has been called. 
     */
	private boolean m_startCalled;
	
    /**
     * Used to track the last state we delivered to any state listeners. 
     */
    private ComponentState m_lastStateDeliveredToListeners = ComponentState.INACTIVE;

    /**
     * Component service scope.
     */
	private volatile ServiceScope m_scope = Component.ServiceScope.SINGLETON;
	
	/**
	 * Indicates if injection of methods or class fields is disabled for this component.
	 */
	private volatile boolean m_injectionDisabled;
	
	/**
	 * Prototype instance used when a component scope is not a singleton when when no init callback is defined.
	 */
    private final static Object PROTOTYPE_INSTANCE = new Object();

    /**
     * Default component declaration implementation.
     */
    static class SCDImpl implements ComponentDependencyDeclaration {
        private final String m_name;
        private final int m_state;
        private final String m_type;

        public SCDImpl(String name, int state, String type) {
            m_name = name;
            m_state = state;
            m_type = type;
        }

        public String getName() {
            return m_name;
        }
        
        public String getSimpleName() {
            return m_name;
        }
        
        public String getFilter() {
            return null;
        }

        public int getState() {
            return m_state;
        }

        public String getType() {
            return m_type;
        }
    }

    class FactoryBase {
        final Map<Object, ComponentImpl> m_clones = new ConcurrentHashMap<>();
        
        public Object getService(Bundle bundle, ServiceRegistration<Object> registration) {
        	// create a clone of the prototype for the consumer
        	ComponentImpl clone = (ComponentImpl) m_manager.createComponent()
                    .setImplementation(m_componentDefinition)
                    .setFactory(m_instanceFactory, m_instanceFactoryCreateMethod) // if not set, no effect
                    .setComposition(m_compositionManager, m_compositionManagerGetMethod) // if not set, no effect
                    .setCallbacks(m_callbackInstance, m_callbackInit, m_callbackStart, m_callbackStop, m_callbackDestroy); // if not set, no effect
        	clone.setThreadPool(m_executor);
        	clone.setAutoConfig(ServiceRegistration.class, false); // don't inject the ServiceRegistration for the moment
        	configureAutoConfigState(clone, ComponentImpl.this);
        	// copy prototype dependencies, except instance bound dependencies
        	getDependencies().stream().filter(dc -> ! dc.isInstanceBound()).map(dc -> dc.createCopy()).forEach(clone::add);
        	clone.setCallbacks(m_callbackInit, m_callbackStart, m_callbackStop, m_callbackDestroy); 
        	m_listeners.forEach(clone::add);        	        	                    	
        	int ctorIndex = clone.instantiateComponent(createScopedComponentConstructorArgs(bundle, registration));  
        	// ctorIndex == -1 means we have used a factory to create the component
        	// if ctorIndex == 0 means we have used the first constructor (the one used to inject service registration and bundles
        	if (ctorIndex != 0) { 
        		// we don't have injected the bundle and service registration in the constructor, so inject them in the class fields
        		autoConfigField(clone, ServiceRegistration.class, registration);
        		autoConfigField(clone, Bundle.class, bundle);
        	}
        	
        	clone.start();
        	Object instance = clone.getInstance();
        	if (instance == null) {
        		// Race condition: the prototype is probably deactivating.
        		throw new IllegalStateException("Can't create prototype instance");
        	}
        	m_clones.put(instance, clone);
        	return instance;
        }

        public void ungetService(Bundle bundle, ServiceRegistration<Object> registration, Object service) {
            ComponentImpl clone = m_clones.remove(service);
            if (clone != null) {
            	clone.stop();
            }
        }       
        
        private void autoConfigField(ComponentImpl clone, Class<?> type, Object autoConfig) {
        	Boolean doAutoConfig = m_autoConfig.get(type);
        	clone.setAutoConfig(type, doAutoConfig == null ? true : doAutoConfig);
        	clone.autoConfigureImplementation(type, autoConfig);
        }
    }
    
    class ComponentServiceFactory extends FactoryBase implements ServiceFactory<Object> {
    }

    class ComponentPrototypeServiceFactory extends FactoryBase implements PrototypeServiceFactory<Object> {
    }

    /**
     * Constructor. Only used for tests.
     */
    public ComponentImpl() {
	    this(null, null, new Logger(null));
	}
	
    /**
     * Constructor
     * @param context the component bundle context 
     * @param manager the manager used to create the component
     * @param logger the logger to use
     */
    public ComponentImpl(BundleContext context, DependencyManager manager, Logger logger) {
        m_context = context;
        m_bundle = context != null ? context.getBundle() : null;
        m_manager = manager;
        m_logger = logger;
        m_executor = new SerialExecutor(m_logger);
        m_autoConfig.put(BundleContext.class, Boolean.TRUE);
        m_autoConfig.put(ServiceRegistration.class, Boolean.TRUE);
        m_autoConfig.put(DependencyManager.class, Boolean.TRUE);
        m_autoConfig.put(Component.class, Boolean.TRUE);
        m_autoConfig.put(Bundle.class, Boolean.TRUE);
        m_callbackInit = "init";
        m_callbackStart = "start";
        m_callbackStop = "stop";
        m_callbackDestroy = "destroy";
        m_id = m_idGenerator.getAndIncrement();
    }

    @Override
    public <T> T createConfigurationType(Class<T> type, Dictionary<?, ?> config) {
    	Dictionary<String, Object> declaredServiceProperties = getDeclaredServiceProperties();
        return Configurable.create(type,  config, declaredServiceProperties);
    }
    
    @Override
    public Executor getExecutor() {
        return m_executor;
    }

    @Override
    public ComponentImpl setDebug(String debugKey) {
        // Force debug level in our logger
        m_logger.setEnabledLevel(LogService.LOG_DEBUG);
        m_logger.setDebugKey(debugKey);
        return this;
    }

	@Override
	public ComponentImpl add(final Dependency ... dependencies) {
		getExecutor().execute(() -> {
            List<DependencyContext> instanceBoundDeps = new ArrayList<>();
            for (Dependency d : dependencies) {
                DependencyContext dc = (DependencyContext) d;
                if (dc.getComponentContext() != null) {
                    m_logger.err("%s can't be added to %s (dependency already added to component %s).", dc, ComponentImpl.this, dc.getComponentContext());
                    continue;
                }
                m_dependencyEvents.put(dc, new ConcurrentSkipListSet<Event>());
                m_dependencies.add(dc);
                generateNameBasedOnServiceAndProperties();
                dc.setComponentContext(ComponentImpl.this);
                if (!(m_state == ComponentState.INACTIVE)) {
                    dc.setInstanceBound(true);
                    instanceBoundDeps.add(dc);
                }
            }
            startDependencies(instanceBoundDeps);
            handleChange();
		});
        return this;
	}

	@Override
	public ComponentImpl remove(final Dependency d) {
		getExecutor().execute(() -> {
		    DependencyContext dc = (DependencyContext) d;
		    // First remove this dependency from the dependency list
		    m_dependencies.remove(d);
		    generateNameBasedOnServiceAndProperties();
		    // Now we can stop the dependency (our component won't be deactivated, it will only be unbound with
		    // the removed dependency).
		    if (!(m_state == ComponentState.INACTIVE)) {
		        dc.stop();
		    }
		    // Finally, cleanup the dependency events.
		    m_dependencyEvents.remove(d);
		    handleChange();
		});
        return this;
	}

	@Override
	public void start() {
		checkParamsConsistency();
	    if (m_active.compareAndSet(false, true)) {
            getExecutor().execute(() -> {
                m_isStarted = true;
                handleChange();
            });
	    }
	}
	
	@Override
	public void stop() {           
	    if (m_active.compareAndSet(true, false)) {
	    	// try to be synchronous, even if a threadpool is used (best effort).
	    	schedule(true /* bypass threadpool if possible */, () -> { 
	    		m_isStarted = false;
	            handleChange();
	    	});
	    }
	}

	@SuppressWarnings("unchecked")
    @Override
	public ComponentImpl setInterface(String serviceName, Dictionary<?, ?> properties) {
		ensureNotActive();
	    m_serviceName = serviceName;
	    m_serviceProperties = (Dictionary<Object, Object>) properties;
	    generateNameBasedOnServiceAndProperties();
        return this;
	}

	@SuppressWarnings("unchecked")
    @Override
	public ComponentImpl setInterface(String[] serviceName, Dictionary<?, ?> properties) {
	    ensureNotActive();
	    m_serviceName = serviceName;
	    m_serviceProperties = (Dictionary<Object, Object>) properties;
	    generateNameBasedOnServiceAndProperties();
        return this;
	}
	
    @Override
	public ComponentImpl setInterface(Class<?> serviceName, Dictionary<?, ?> properties) {
        return setInterface(serviceName.getName(), properties);
	}

    @Override
	public ComponentImpl setInterface(Class<?>[] serviceName, Dictionary<?, ?> properties) {
		String[] serviceNameStr = Stream.of(serviceName).map(clazz -> clazz.getName()).toArray(String[]::new);
        return setInterface(serviceNameStr, properties);
	}

	@Override
    public void handleEvent(final DependencyContext dc, final EventType type, final Event... event) {
        // since this method can be invoked by anyone from any thread, we need to
        // pass on the event to a runnable that we execute using the component's
        // executor. There is one corner case: if this is a REMOVE event, and if we are using a threadpool,
		// then make a best effort to try invoking the component unbind callback synchronously (to make 
		// sure the unbound service is not stopped at the time we call unbind on our component
		// which depends on the removing service).
		// This is just a best effort, and the removed event will be handled asynchronosly if our 
		// queue is currently being run by another thread, or by the threadpool.
		
		boolean bypassThreadPoolIfPossible = (type == EventType.REMOVED);
		schedule(bypassThreadPoolIfPossible, () ->  {
			try {
				switch (type) {
				case ADDED:
					handleAdded(dc, event[0]);
					break;
				case CHANGED:
					handleChanged(dc, event[0]);
					break;
				case REMOVED:
					handleRemoved(dc, event[0]);
					break;
				case SWAPPED:
					handleSwapped(dc, event[0], event[1]);
					break;
				}
			} finally {
				// Clear cache of component callbacks invocation, except if we are currently called from handleChange().
				// (See FELIX-4913).
				clearInvokeCallbackCache();
			}
		});
	}

    @Override
    public Event getDependencyEvent(DependencyContext dc) {
        ConcurrentSkipListSet<Event> events = m_dependencyEvents.get(dc);
        return events.size() > 0 ? events.last() : null;
    }
    
    @Override
    public Set<Event> getDependencyEvents(DependencyContext dc) {
        return m_dependencyEvents.get(dc);
    }

    @Override
    public ComponentImpl setAutoConfig(Class<?> clazz, boolean autoConfig) {
        m_autoConfig.put(clazz, Boolean.valueOf(autoConfig));
        return this;
    }
    
    @Override
    public ComponentImpl setAutoConfig(Class<?> clazz, String instanceName) {
        m_autoConfig.put(clazz, Boolean.valueOf(instanceName != null));
        m_autoConfigInstance.put(clazz, instanceName);
        return this;
    }
    
    @Override
    public boolean getAutoConfig(Class<?> clazz) {
        Boolean result = (Boolean) m_autoConfig.get(clazz);
        return (result != null && result.booleanValue());
    }
    
    @Override
    public String getAutoConfigInstance(Class<?> clazz) {
        return (String) m_autoConfigInstance.get(clazz);
    }

    @SuppressWarnings("unchecked")
    public <T> T getInstance() {     
        Object[] instances  = getCompositionInstances();
        return instances.length == 0 ? null : (T) instances[0]; 
    }

    public Object[] getInstances() {
        return getCompositionInstances();
    }
    
    public void invokeCallbackMethod(Object[] instances, String methodName, Class<?>[][] signatures, Object[][] parameters) {
        invokeCallbackMethod(instances, methodName, signatures, parameters, true);
    }

    public void invokeCallbackMethod(Object[] instances, String methodName, Class<?>[][] signatures, Object[][] parameters, boolean logIfNotFound) {
        boolean callbackFound = false;
        for (int i = 0; i < instances.length; i++) {
            try {
                InvocationUtil.invokeCallbackMethod(instances[i], methodName, signatures, parameters);
                callbackFound |= true;
            }
            catch (NoSuchMethodException e) {
                // if the method does not exist, ignore it
            }
            catch (InvocationTargetException e) {
                // the method itself threw an exception, log that
                m_logger.log(Logger.LOG_ERROR, "Invocation of '" + methodName + "' failed.", e.getCause());
                callbackFound |= true;
            }
            catch (Throwable e) { // IllegalArgumentException (wrong params passed to the method), or IllegalAccessException (method can't be accessed)
                m_logger.log(Logger.LOG_ERROR, "Could not invoke '" + methodName + "'.", e);
            }
        }
        
        // If the callback is not found, we don't log if the method is on an AbstractDecorator.
        // (Aspect or Adapter are not interested in user dependency callbacks)        
        if (logIfNotFound && ! callbackFound && ! (getInstance() instanceof AbstractDecorator)) {
        	m_logger.log(LogService.LOG_ERROR, "\"" + methodName + "\" callback not found on component instances " + Arrays.toString(instances));
        }
    }
    
    public void invokeCallback(Object[] instances, String methodName, Class<?>[][] signatures, Supplier<?>[][] parameters, boolean logIfNotFound) {
        boolean callbackFound = false;
        for (int i = 0; i < instances.length; i++) {
            try {
                InvocationUtil.invokeCallbackMethod(instances[i], methodName, signatures, parameters);
                callbackFound |= true;
            }
            catch (NoSuchMethodException e) {
                // if the method does not exist, ignore it
            }
            catch (InvocationTargetException e) {
                // the method itself threw an exception, log that
                m_logger.log(Logger.LOG_ERROR, "Invocation of '" + methodName + "' failed.", e.getCause());
                callbackFound |= true;
            }
            catch (Throwable e) {
                m_logger.log(Logger.LOG_ERROR, "Could not invoke '" + methodName + "'.", e);
            }
        }
        
        // If the callback is not found, we don't log if the method is on an AbstractDecorator.
        // (Aspect or Adapter are not interested in user dependency callbacks)        
        if (logIfNotFound && ! callbackFound && ! (getInstance() instanceof AbstractDecorator)) {
        	m_logger.log(LogService.LOG_ERROR, "\"" + methodName + "\" callback not found on component instances " + Arrays.toString(instances));
        }    	
    }

    @Override
    public boolean isAvailable() {
        return m_state == TRACKING_OPTIONAL;
    }
    
    @Override
    public boolean isActive() {
        return m_active.get();
    }
    
    @Override
    public ComponentImpl add(ComponentStateListener listener) {
		getExecutor().execute(() -> {
	        m_listeners.add(listener);
            switch (m_lastStateDeliveredToListeners) {
            case STARTING:
                // this new listener missed the starting cb
                listener.changed(ComponentImpl.this, STARTING);
                break;
            case TRACKING_OPTIONAL:
                // this new listener missed the starting/started cb
                listener.changed(ComponentImpl.this, STARTING);
                listener.changed(ComponentImpl.this, TRACKING_OPTIONAL);
                break;
            case STOPPING:
                // this new listener missed the starting/started/stopping cb
                listener.changed(ComponentImpl.this, STARTING);
                listener.changed(ComponentImpl.this, TRACKING_OPTIONAL);
                listener.changed(ComponentImpl.this, STOPPING);
                break;
            case STOPPED:
                // no need to call missed listener callbacks
                break;
            default:
            	break;
            }
		});
        return this;
    }

    @Override
    public ComponentImpl remove(ComponentStateListener listener) {
    	m_listeners.remove(listener);						
        return this;
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<DependencyContext> getDependencies() {
        return (List<DependencyContext>) m_dependencies.clone();
    }

    @Override
    public ComponentImpl setImplementation(Object implementation) {
        m_componentDefinition = implementation;
        return this;
    }
    
    @SuppressWarnings("rawtypes")
	@Override
    public ServiceRegistration getServiceRegistration() {
        return m_registration;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <K,V> Dictionary<K, V> getServiceProperties() {
    	return (Dictionary<K, V>) calculateServiceProperties();
    }

    public <K,V> Dictionary<K, V> getDeclaredServiceProperties() {    	
    	return (m_serviceProperties != null) ? ServiceUtil.toR6Dictionary(m_serviceProperties) : ServiceUtil.toR6Dictionary(ServiceUtil.EMPTY_PROPERTIES);
    	
//    	if (m_serviceProperties != null) {
//    		// Applied patch from FELIX-4304
//    		Hashtable<String, Object> serviceProperties = new Hashtable<>();
//    		addTo(serviceProperties, m_serviceProperties);
//    		return (Dictionary<K, V>) serviceProperties;
//    	}
//    	return (Dictionary<K, V>) ServiceUtil.EMPTY_PROPERTIES;
    }

    @Override
    @SuppressWarnings("unchecked")
    public ComponentImpl setServiceProperties(final Dictionary<?, ?> serviceProperties) {
        getExecutor().execute(() -> {
            Dictionary<String, Object> properties = null;
            m_serviceProperties = (Dictionary<Object, Object>) serviceProperties;
            generateNameBasedOnServiceAndProperties();
            if ((m_registration != null) && (m_serviceName != null)) {
                properties = calculateServiceProperties();
                m_registration.setProperties(properties);
            }
        });
        return this;
    }
    
    public ComponentImpl setCallbacks(String init, String start, String stop, String destroy) {
        ensureNotActive();
        m_callbackInit = init;
        m_callbackStart = start;
        m_callbackStop = stop;
        m_callbackDestroy = destroy;
        return this;
    }
    
    public ComponentImpl setCallbacks(Object instance, String init, String start, String stop, String destroy) {
        ensureNotActive();
        m_callbackInstance = instance;
        m_callbackInit = init;
        m_callbackStart = start;
        m_callbackStop = stop;
        m_callbackDestroy = destroy;
        return this;
    }

    @Override
    public ComponentImpl setFactory(Object factory, String createMethod) {
        ensureNotActive();
        m_instanceFactory = factory;
        m_instanceFactoryCreateMethod = createMethod;
        return this;
    }

    @Override
    public ComponentImpl setFactory(String createMethod) {
        return setFactory(null, createMethod);
    }

    @Override
    public ComponentImpl setComposition(Object instance, String getMethod) {
        ensureNotActive();
        m_compositionManager = instance;
        m_compositionManagerGetMethod = getMethod;
        return this;
    }

    @Override
    public ComponentImpl setComposition(String getMethod) {
        return setComposition(null, getMethod);
    }

    @Override
    public DependencyManager getDependencyManager() {
        return m_manager;
    }
    
	@Override
	public boolean injectionDisabled() {
		return m_injectionDisabled;
	}
	
    public ComponentDependencyDeclaration[] getComponentDependencies() {
        List<DependencyContext> deps = getDependencies();
        if (deps != null) {
            ComponentDependencyDeclaration[] result = new ComponentDependencyDeclaration[deps.size()];
            for (int i = 0; i < result.length; i++) {
                DependencyContext dep = (DependencyContext) deps.get(i);
                if (dep instanceof ComponentDependencyDeclaration) {
                    result[i] = (ComponentDependencyDeclaration) dep;
                }
                else {
                    result[i] = new SCDImpl(dep.toString(), (dep.isAvailable() ? 1 : 0) + (dep.isRequired() ? 2 : 0), dep.getClass().getName());
                }
            }
            return result;
        }
        return null;
    }
    
    public String getName() {
        StringBuilder sb = new StringBuilder();
        Object serviceName = m_serviceName;

        if( (!(serviceName instanceof String[])) && (!(serviceName instanceof String))) {
            // The component does not provide a service, use the component definition as the name.
            Object componentDefinition = m_componentDefinition;
            if (componentDefinition != null) {
                sb.append(toString(componentDefinition));
            } else { 
                // No component definition means we are using a factory. If the component instance is available use it as the component name,
                // alse use teh factory object as the component name.
                Object componentInstance = m_componentInstance;
                if (componentInstance != null) {
                    sb.append(componentInstance.getClass().getName());
                } else {
                    // Check if a factory is set.
                    Object instanceFactory = m_instanceFactory;
                    if (instanceFactory != null) {
                        sb.append(toString(instanceFactory));
                    } else {
                        sb.append(super.toString());
                    }
                }
            }
            m_componentName = sb.toString();
        } 
        return m_componentName;
    }
    
	@Override
	public ComponentImpl setScope(ServiceScope scope) {
	    m_scope = scope;
	    return this;
	}
	
	ServiceScope getScope() {
	    return m_scope;
	}
	
	private void checkParamsConsistency() {
		switch (m_scope) {
		case PROTOTYPE:
		case BUNDLE:
			if (m_serviceName == null) {
				throw new IllegalStateException("No service interface specified for scoped service");
			}

			if ((!(m_componentDefinition instanceof Class)) && m_instanceFactoryCreateMethod == null) {
				throw new IllegalStateException(
						"The component instance must be created using either a class or a factory object when scope is not singleton.");
			}

		}
		
	}

    private void generateNameBasedOnServiceAndProperties() {
    	StringBuilder sb = new StringBuilder();
        Object serviceName = m_serviceName;

        // If the component provides service(s), return the services as the component name.
    	if (serviceName instanceof String[]) {
            String[] names = (String[]) serviceName;
            for (int i = 0; i < names.length; i++) {
                if (i > 0) {
                    sb.append(", ");
                }
                sb.append(names[i]);
            }
            ServiceUtil.appendProperties(sb, calculateServiceProperties());
       } else if(serviceName instanceof String) { 
          	  sb.append(serviceName.toString());
          	  ServiceUtil.appendProperties(sb, calculateServiceProperties());
       }
    	m_componentName = sb.toString();
    }
    
    @Override
    public BundleContext getBundleContext() {
        return m_context;
    }
    
    @Override
    public Bundle getBundle() {
        return m_bundle;
    }

    public long getId() {
        return m_id;
    }
    
    public String getClassName() {
        Object serviceInstance = m_componentInstance;
        if (serviceInstance != null) {
            return serviceInstance.getClass().getName();
        } 
        
        Object implementation = m_componentDefinition;
        if (implementation != null) {
            if (implementation instanceof Class) {
                return ((Class<?>) implementation).getName();
            }
            return implementation.getClass().getName();
        } 
        
        Object instanceFactory = m_instanceFactory;
        if (instanceFactory != null) {
            return toString(instanceFactory);
        } else {
            // unexpected.
            return ComponentImpl.class.getName();
        }
    }
    
    public String[] getServices() {
        if (m_serviceName instanceof String[]) {
            return (String[]) m_serviceName;
        } else if (m_serviceName instanceof String) {
            return new String[] { (String) m_serviceName };
        } else {
            return null;
        }
    }
    
    public int getState() {
        return (isAvailable() ? ComponentDeclaration.STATE_REGISTERED : ComponentDeclaration.STATE_UNREGISTERED);
    }

    public void ensureNotActive() {
        if (m_active.get()) {
            throw new IllegalStateException("Can't modify an already started component.");
        }
    }
    
    public ComponentDeclaration getComponentDeclaration() {
        return this;
    }
    
    @Override
    public String toString() {
        if (m_logger.getDebugKey() != null) {
            return m_logger.getDebugKey();
        }
        return getClassName();
    }
    
    @Override
    public void setThreadPool(Executor threadPool) {
        ensureNotActive();
        m_executor = new DispatchExecutor(threadPool, m_logger);
    }
    
    @Override
    public Logger getLogger() {
        return m_logger;
    }

    @Override
    public Map<String, Long> getCallbacksTime() {
        return m_stopwatch;
    }
        
    @Override
    public ComponentContext instantiateComponent() {
    	CallbackTypeDef ctorArgs = null;
    	
    	switch (m_scope) {
    	case SINGLETON:
    		// When a component scope is singleton, we'll use the following constructor or factory "create" method signatures:
    		ctorArgs = VOID;    			
    		break;
    		    		
    	case PROTOTYPE:
    	case BUNDLE:
    		if (m_injectionDisabled) {    		
    			m_componentInstance = PROTOTYPE_INSTANCE;
    			return this;
    		} else {
        		ctorArgs = createScopedComponentConstructorArgs(null, null);
    		}
    		break;

    	default:
    		throw new IllegalStateException("Invalid scope: " + m_scope);
		}

    	// Create the factory "create" method signatures types
    	instantiateComponent(ctorArgs);
    	return this;
    }    
    
    // ---------------------- Package/Private methods ---------------------------       

    /**
     * Creates a constructor argument descritor for a scoped component (having scope=BUNDLE|PROTOTYPE)
     */
    private CallbackTypeDef createScopedComponentConstructorArgs(Bundle b, ServiceRegistration sr) {
    	return new CallbackTypeDef(
    		new Class[][]  {{Bundle.class, ServiceRegistration.class}, {Bundle.class, ServiceRegistration.class, BundleContext.class}, {}},
            new Object[][] {{b,sr}, {b,sr, m_context}, {}});
    }
    
    /**
     * Creates the component instance.
     * @param ctorArgs the constructor argument signatures
     * @return the index of the constructor argument signatures that was used when creating the component. -1 means the component has been created using a factory "create" method.
     */
    private int instantiateComponent(CallbackTypeDef ctorArgs) {
		m_logger.debug("instantiating component.");
		int ctorArgsUsed = -1;
		
		if (m_componentInstance == null) {
			if (m_componentDefinition instanceof Class) {
				try {
					InvocationUtil.ComponentInstance ci = InvocationUtil.createInstance((Class<?>) m_componentDefinition, ctorArgs);
					m_componentInstance = ci.m_instance;
					ctorArgsUsed = ci.m_ctorIndex;
				} catch (Exception e) {
					m_logger.log(Logger.LOG_ERROR, "Could not instantiate class " + m_componentDefinition, e);
				}
			} else {
				if (m_instanceFactoryCreateMethod != null) {
					Object factory = null;
					if (m_instanceFactory != null) {
						if (m_instanceFactory instanceof Class) {
							try {
								InvocationUtil.ComponentInstance ci = InvocationUtil.createInstance((Class<?>) m_instanceFactory, VOID);
								factory = ci.m_instance;
							} catch (Exception e) {
								m_logger.log(Logger.LOG_ERROR,
										"Could not create factory instance of class " + m_instanceFactory + ".", e);
							}
						} else {
							factory = m_instanceFactory;
						}
					} else {
						// TODO review if we want to try to default to something if not specified
						// for now the JavaDoc of setFactory(method) reflects the fact that we need
						// to review it
					}
					if (factory == null) {
						m_logger.log(Logger.LOG_ERROR, "Factory cannot be null.");
					} else {
						try {
					    	CallbackTypeDef factoryArgs = new CallbackTypeDef(
					    			new Class[][] {{}, {Component.class}}, 
					    			new Object[][] {{}, {this}});
							m_componentInstance = InvocationUtil.invokeMethod(factory, factory.getClass(),
																 m_instanceFactoryCreateMethod, factoryArgs.m_sigs, factoryArgs.m_args, false);
						} catch (Exception e) {
							m_logger.log(Logger.LOG_ERROR, "Could not create service instance using factory " + factory
									+ " method " + m_instanceFactoryCreateMethod + ".", e);
						}
					}
				}
			}
			
			if (m_componentInstance == null) {
				m_componentInstance = m_componentDefinition;
			}

			// configure the bundle context
			autoConfigureImplementation(BundleContext.class, m_context);
			autoConfigureImplementation(ServiceRegistration.class, NULL_REGISTRATION);
			autoConfigureImplementation(DependencyManager.class, m_manager);
			autoConfigureImplementation(Component.class, this);
		}
		return ctorArgsUsed;
    }
         
	private String toString(Object implementation) {
        if (implementation instanceof Class) {
            return (((Class<?>) implementation).getName());
        } else {
            // If the implementation instance does not override "toString", just display
            // the class name, else display the component using its toString method
            try {
            Method m = implementation.getClass().getMethod("toString", new Class[0]);
                if (m.getDeclaringClass().equals(Object.class)) {
                    return implementation.getClass().getName();
                } else {
                    return implementation.toString();
                }
            }  catch (java.lang.NoSuchMethodException e) {
                // Just display the class name
                return implementation.getClass().getName();
            }
        }
    }
    
    /**
     * Runs the state machine, to see if a change event has to trigger some component state transition.
     */
    private void handleChange() {
        if (isHandlingChange()) {
            return;
        }
        m_logger.debug("handleChanged");
    	handlingChange(true);
        try {
            ComponentState oldState;
            ComponentState newState;
            do {
                oldState = m_state;
                newState = calculateNewState(oldState);
                m_logger.debug("%s -> %s", oldState, newState);
                m_state = newState;
            } while (performTransition(oldState, newState));
        } finally {
        	handlingChange(false);
            clearInvokeCallbackCache();
            m_logger.debug("end handling change.");
        }
    }
    
    /** 
     * Based on the current state, calculate the new state. 
     */
    private ComponentState calculateNewState(ComponentState currentState) {
        if (currentState == INACTIVE) {
            if (m_isStarted) {
                return WAITING_FOR_REQUIRED;
            }
        }
        if (currentState == WAITING_FOR_REQUIRED) {
            if (!m_isStarted) {
                return INACTIVE;
            }
            if (allRequiredAvailable()) {
                return INSTANTIATED_AND_WAITING_FOR_REQUIRED;
            }
        }
        if (currentState == INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
            if (m_isStarted && allRequiredAvailable()) {
                if (allInstanceBoundAvailable()) {
                    return TRACKING_OPTIONAL;
                }
                return currentState;
            }
            return WAITING_FOR_REQUIRED;
        }
        if (currentState == TRACKING_OPTIONAL) {
            if (m_isStarted && allRequiredAvailable() && allInstanceBoundAvailable()) {
                return currentState;
            }
            return INSTANTIATED_AND_WAITING_FOR_REQUIRED;
        }
        return currentState;
    }

    /** 
     * Perform all the actions associated with state transitions. 
     * @returns true if a transition was performed.
     **/
    private boolean performTransition(ComponentState oldState, ComponentState newState) {
        if (oldState == ComponentState.INACTIVE && newState == ComponentState.WAITING_FOR_REQUIRED) {
        	initPrototype();
            startDependencies(m_dependencies);
            notifyListeners(newState);
            return true;
        }
        if (oldState == WAITING_FOR_REQUIRED && newState == INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
            instantiateComponent();
            invokeAutoConfigDependencies();
            invokeAddRequiredDependencies();
            invoke(m_callbackInit); 
            notifyListeners(newState);
            return true;
        }
        if (oldState == INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == TRACKING_OPTIONAL) {
            invokeAutoConfigInstanceBoundDependencies();
            invokeAddRequiredInstanceBoundDependencies();
            notifyListeners(STARTING);
            invokeStart();
            notifyListeners(STARTED);
            invokeAddOptionalDependencies();
            registerService();
            notifyListeners(newState);
            return true;
        }
        if (oldState == TRACKING_OPTIONAL && newState == INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
            notifyListeners(STOPPING);
        	unregisterService();
            invokeRemoveOptionalDependencies();
            invokeStop();
            invokeRemoveRequiredInstanceBoundDependencies();
            notifyListeners(newState);
            notifyListeners(STOPPED);
            return true;
        }
        if (oldState == INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == WAITING_FOR_REQUIRED) {
            invoke(m_callbackDestroy);
            removeInstanceBoundDependencies();
            invokeRemoveRequiredDependencies();
            notifyListeners(newState);
            if (! someDependenciesNeedInstance()) {
                destroyComponent();
            }
            return true;
        }
        if (oldState == WAITING_FOR_REQUIRED && newState == INACTIVE) {
            stopDependencies();
            destroyComponent();
            notifyListeners(newState);
            cleanup();
            return true;
        }
        return false;
    }
    
	private void cleanup() {
		m_dependencyEvents.values().forEach(eventList -> {
			eventList.forEach(event -> event.close());
			eventList.clear();
		});
	}
	
	private void invokeStart() {
		// Only invoke start callback for singleton components.
		// We don't invoke start callbacks for components with scope=prototype or bundle because
		// prototypes (bundle/prototype) components are only used to register ServiceFactory (or PrototypeServiceFactory) services. 
		if (m_scope == ServiceScope.SINGLETON) {
			invoke(m_callbackStart);
			m_startCalled = true;
		}
	}

    private void invokeStop() {
		// Only invoke stop callback for singleton components.
		// We don't invoke stop callbacks for components with scope=prototype or bundle because
		// prototypes (bundle/prototype) components are only used to register ServiceFactory (or PrototypeServiceFactory) services. 
		if (m_scope == ServiceScope.SINGLETON) {
			invoke(m_callbackStop);
			m_startCalled = false;
		}
	}
    
    /**
     * Sets the m_handlingChange flag that indicates if the state machine is currently running the handleChange method.
     */
    private void handlingChange(boolean transiting) {
        m_handlingChange = transiting;
    }
    
    /**
     * Are we currently running the handleChange method ?
     */
    private boolean isHandlingChange() {
    	return m_handlingChange;
    }

    /**
     * Then handleEvent calls this method when a dependency service is being added.
     */
    private void handleAdded(DependencyContext dc, Event e) {
        if (! m_isStarted) {
            return;
        }
        m_logger.debug("handleAdded %s", e);
        
        Set<Event> dependencyEvents = m_dependencyEvents.get(dc);
        dependencyEvents.add(e);        
        dc.setAvailable(true);
                  
        // In the following switch block, we sometimes only recalculate state changes 
        // if the dependency is fully started. If the dependency is not started,
        // it means it is actually starting (the service tracker is executing the open method). 
        // And in this case, depending on the state, we don't recalculate state changes now. 
        // 
        // All this is done for two reasons:
        // 1- optimization: it is preferable to recalculate state changes once we know about all currently 
        //    available dependency services (after the tracker has returned from its open method).
        // 2- This also allows to determine the list of currently available dependency services before calling
        //    the component start() callback.
        
        switch (m_state) {
        case WAITING_FOR_REQUIRED:            
            if (dc.isStarted() && dc.isRequired()) {
                handleChange();
            }
            break;
        case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
            if (!dc.isInstanceBound()) {
            	invokeCallback(dc, EventType.ADDED, e);
                updateInstance(dc, e, false, true);
            } else {
                if (dc.isStarted() && dc.isRequired()) {
                    handleChange();
                }
            }
            break;
        case TRACKING_OPTIONAL:
            invokeCallback(dc, EventType.ADDED, e);
            updateInstance(dc, e, false, true);
            break;
        default:
        }
    }       
    
    /**
     * Then handleEvent calls this method when a dependency service is being changed.
     */
    private void handleChanged(final DependencyContext dc, final Event e) {
        if (! m_isStarted) {
            return;
        }
        Set<Event> dependencyEvents = m_dependencyEvents.get(dc);
        dependencyEvents.remove(e);
        dependencyEvents.add(e);
                
        switch (m_state) {
        case TRACKING_OPTIONAL:
            invokeCallback(dc, EventType.CHANGED, e);
            updateInstance(dc, e, true, false);
            break;

        case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
            if (!dc.isInstanceBound()) {
            	invokeCallback(dc, EventType.CHANGED, e);
                updateInstance(dc, e, true, false);
            }
            break;
        default:
            // noop
        }
    }
    
	/**
     * Then handleEvent calls this method when a dependency service is being removed.
     */
    private void handleRemoved(DependencyContext dc, Event e) {
    	try {
    		if (! m_isStarted) {
    			return;
    		}
    		// Check if the dependency is still available.
    		Set<Event> dependencyEvents = m_dependencyEvents.get(dc);
    		int size = dependencyEvents.size();
    		if (dependencyEvents.contains(e)) {
    			size--; // the dependency is currently registered and is about to be removed.
    		}
    		dc.setAvailable(size > 0);
        
    		// If the dependency is now unavailable, we have to recalculate state change. This will result in invoking the
    		// "removed" callback with the removed dependency (which we have not yet removed from our dependency events list.).
    		// But we don't recalculate the state if the dependency is not started (if not started, it means that it is currently starting,
    		// and the tracker is detecting a removed service).
    		if (size == 0 && dc.isStarted()) {
    			handleChange();
    		}
    		
    		// Now, really remove the dependency event.
    		dependencyEvents.remove(e);    
        
    		// Depending on the state, we possible have to invoke the callbacks and update the component instance.        
			switch (m_state) {
			case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
				if (!dc.isInstanceBound()) { 
					invokeCallback(dc, EventType.REMOVED, e);
					updateInstance(dc, e, false, false);
				}
				break;
			case TRACKING_OPTIONAL:
				invokeCallback(dc, EventType.REMOVED, e);
				updateInstance(dc, e, false, false);
				break;
			default:
			}
    	} finally {
    		e.close();
    	}
    }
    
    private void handleSwapped(DependencyContext dc, Event oldEvent, Event newEvent) {
    	try {
    		if (! m_isStarted) {
    			return;
    		}
    		Set<Event> dependencyEvents = m_dependencyEvents.get(dc);        
    		dependencyEvents.remove(oldEvent);
    		dependencyEvents.add(newEvent);
                
    		// Depending on the state, we possible have to invoke the callbacks and update the component instance.        
    		switch (m_state) {
    		case WAITING_FOR_REQUIRED:
    			// No need to swap, we don't have yet injected anything
    			break;
    		case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
    			// Only swap *non* instance-bound dependencies
    			if (!dc.isInstanceBound()) {
    				invokeSwapCallback(dc, oldEvent, newEvent);
    			}
    			break;
    		case TRACKING_OPTIONAL:
    			invokeSwapCallback(dc, oldEvent, newEvent);
    			break;
    		default:
    		}
    	} finally {
    		oldEvent.close();
    	}
    }
        	
    private boolean allRequiredAvailable() {
        boolean available = true;
        for (DependencyContext d : m_dependencies) {
            if (d.isRequired() && !d.isInstanceBound()) {
                if (!d.isAvailable()) {
                    available = false;
                    break;
                }
            }
        }
        return available;
    }

    private boolean allInstanceBoundAvailable() {
        boolean available = true;
        for (DependencyContext d : m_dependencies) {
            if (d.isRequired() && d.isInstanceBound()) {
                if (!d.isAvailable()) {
                    available = false;
                    break;
                }
            }
        }
        return available;
    }

    private boolean someDependenciesNeedInstance() {
        for (DependencyContext d : m_dependencies) {
            if (d.needsInstance()) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * Updates the component instance(s).
     * @param dc the dependency context for the updating dependency service
     * @param event the event holding the updating service (service + properties)
     * @param update true if dependency service properties are updating, false if not. If false, it means
     *        that a dependency service is being added or removed. (see the "add" flag).
     * @param add true if the dependency service has been added, false if it has been removed. This flag is 
     *        ignored if the "update" flag is true (because the dependency properties are just being updated).
     */
    private void updateInstance(DependencyContext dc, Event event, boolean update, boolean add) {
        if (dc.isAutoConfig()) {
        	updateImplementation(dc.getAutoConfigType(), dc, dc.getAutoConfigName(), event, update, add);
        }
        if (dc.isPropagated() && m_registration != null) {
            m_registration.setProperties(calculateServiceProperties());
        }
    }
    
    private void startDependencies(List<DependencyContext> dependencies) {
        // Start first optional dependencies first.
        m_logger.debug("startDependencies.");
        List<DependencyContext> requiredDeps = new ArrayList<>();
        for (DependencyContext d : dependencies) {
            if (d.isRequired()) {
                requiredDeps.add(d);
                continue;
            }
            if (d.needsInstance()) {
                instantiateComponent();
            }
            d.start();
        }
        // now, start required dependencies.
        for (DependencyContext d : requiredDeps) {
            if (d.needsInstance()) {
                instantiateComponent();
            }
            d.start();
        }
    }
    
    private void stopDependencies() {
        for (DependencyContext d : m_dependencies) {
            d.stop();
        }
    }

    private void registerService() {
        if (m_context != null && m_serviceName != null) {
            ServiceRegistrationImpl wrapper = new ServiceRegistrationImpl();
            m_registration = wrapper;
            autoConfigureImplementation(ServiceRegistration.class, m_registration);
            
            // service name can either be a string or an array of strings
            ServiceRegistration<?> registration;

            // determine service properties
            Dictionary<String, Object> properties = calculateServiceProperties();

            // register the service
            try {
                Object componentInstance = null;
                switch (m_scope) {
                   case SINGLETON: componentInstance = m_componentInstance; break;
                   case BUNDLE: componentInstance = new ComponentServiceFactory(); break;
                   case PROTOTYPE: componentInstance = new ComponentPrototypeServiceFactory(); break;
                }

                if (m_serviceName instanceof String) {
                    registration = m_context.registerService((String) m_serviceName, componentInstance, properties);
                }
                else {
                    registration = m_context.registerService((String[]) m_serviceName, componentInstance, properties);
                }
                wrapper.setServiceRegistration(registration);
            }
            catch (IllegalArgumentException iae) {
                m_logger.log(Logger.LOG_ERROR, "Could not register service " + m_componentInstance, iae);
                // set the registration to an illegal state object, which will make all invocations on this
                // wrapper fail with an ISE (which also occurs when the SR becomes invalid)
                wrapper.setIllegalState();
            }
        }
    }

    private void unregisterService() {
        if (m_serviceName != null && m_registration != null) {
            try {
            	if (m_bundle != null && (m_bundle.getState() == Bundle.STARTING || m_bundle.getState() == Bundle.ACTIVE || m_bundle.getState() == Bundle.STOPPING)) {
            		m_registration.unregister();
            	}
            } catch (IllegalStateException e) { /* Should we really log this ? */}
            autoConfigureImplementation(ServiceRegistration.class, NULL_REGISTRATION);
            m_registration = null;
        }
    }
    
    private Dictionary<String, Object> calculateServiceProperties() {
    	Dictionary<String, Object> properties = new Hashtable<>();
    	// First add propagated dependency service properties which don't override our component service properties
    	Predicate<DependencyContext> dependencyPropagated = (dc) -> dc.isPropagated() && dc.isAvailable();
    	
		m_dependencies.stream()
			.filter(dc -> dependencyPropagated.test(dc) && ! dc.overrideServiceProperties())
			.forEach(dc -> addTo(properties, dc.getProperties()));
		
		// Now add our component service properties, which override previously added propagated dependency service properties
		addTo(properties, m_serviceProperties);
		
		// Finally, add dependency service properties which override our component service properties
		m_dependencies.stream()
			.filter(dc -> dependencyPropagated.test(dc) && dc.overrideServiceProperties())
			.forEach(dc -> addTo(properties, dc.getProperties()));

		return properties; // FELIX-5683: now we never return null
	}

    private void addTo(Dictionary<String, Object> properties, Dictionary<?, Object> additional) {
		if (properties == null) {
			throw new IllegalArgumentException("Dictionary to add to cannot be null.");
		}
		if (additional != null) {
			Enumeration<?> e = additional.keys();
			while (e.hasMoreElements()) {
				Object key = e.nextElement();
				properties.put(key.toString(), additional.get(key));
			}
		}
	}

	private void destroyComponent() {
		m_componentInstance = null;
	}
	
	private void invokeAddRequiredDependencies() {
		for (DependencyContext d : m_dependencies) {
			if (d.isRequired() && !d.isInstanceBound()) {
			    for (Event e : m_dependencyEvents.get(d)) {
			        invokeCallback(d, EventType.ADDED, e);
			    }
			}
		}
	}
	
    private void invokeAutoConfigDependencies() {
        for (DependencyContext d : m_dependencies) {
            if (d.isAutoConfig() && !d.isInstanceBound()) {
                configureImplementation(d.getAutoConfigType(), d, d.getAutoConfigName());
            }
        }
    }
    
    private void invokeAutoConfigInstanceBoundDependencies() {
        for (DependencyContext d : m_dependencies) {
            if (d.isAutoConfig() && d.isInstanceBound()) {
                configureImplementation(d.getAutoConfigType(), d, d.getAutoConfigName());
            }
        }
    }
	
	private void invokeAddRequiredInstanceBoundDependencies() {
		for (DependencyContext d : m_dependencies) {
			if (d.isRequired() && d.isInstanceBound()) {
	             for (Event e : m_dependencyEvents.get(d)) {
	                 invokeCallback(d, EventType.ADDED, e);
	             }
			}
		}
	}
	
    private void invokeAddOptionalDependencies() {
        for (DependencyContext d : m_dependencies) {
            if (! d.isRequired()) {
                for (Event e : m_dependencyEvents.get(d)) {
                    invokeCallback(d, EventType.ADDED, e);
                }
            }
        }
    }

    private void invokeRemoveRequiredDependencies() { 
		for (DependencyContext d : m_dependencies) {
			if (!d.isInstanceBound() && d.isRequired()) {
                for (Event e : m_dependencyEvents.get(d)) {
                    invokeCallback(d, EventType.REMOVED, e);
                }
			}
		}
	}

    private void invokeRemoveOptionalDependencies() { 
        for (DependencyContext d : m_dependencies) {
            if (! d.isRequired()) {
                for (Event e : m_dependencyEvents.get(d)) {
                    invokeCallback(d, EventType.REMOVED, e);
                }
            }
        }
    }

	private void invokeRemoveRequiredInstanceBoundDependencies() {
		for (DependencyContext d : m_dependencies) {
			if (d.isInstanceBound() && d.isRequired()) {
                for (Event e : m_dependencyEvents.get(d)) {
                    invokeCallback(d, EventType.REMOVED, e);
                }
			}
		}
	}
	
	/**
	 * This method ensures that a dependency callback is invoked only one time;
	 * It also ensures that if the dependency callback is optional, then we only
	 * invoke the bind method if the component start callback has already been called. 
	 */
	private void invokeCallback(DependencyContext dc, EventType type, Event event) {
    	// don't inject anything if the component instance is a hidden prototype instance
    	if (m_injectionDisabled) {
    		return;
    	}
    	
		if (! dc.isRequired() && ! m_startCalled) {
			return;
		}
		
		// First, check if the callback has not already been called (see FELIX-4913)
		if (m_invokeCallbackCache.put(event, event) == null) {
		    // FELIX-5155: we must not invoke callbacks on our special internal components (adapters/aspects) if the dependency is not the first one, or 
		    // if the internal component is a Factory Pid Adapter.
		    // For aspects/adapters, the first dependency only need to be injected, not the other extra dependencies added by user.
		    // (in fact, we do this because extra dependencies (added by user) may contain a callback instance, and we really don't want to invoke the callbacks twice !		    
		    Object mainComponentImpl = getInstance();
		    if (mainComponentImpl instanceof AbstractDecorator) {
		        if (mainComponentImpl instanceof FactoryConfigurationAdapterImpl.AdapterImpl || dc != m_dependencies.get(0)) {
		            return;
		        }
		    }
			dc.invokeCallback(type, event);
		}		
	}
	
	/**
	 * Invokes a swap callback, except if the dependency is optional and the component is 
	 * not started (optional dependencies are always injected while the component is started). 
	 */
	private void invokeSwapCallback(DependencyContext dc, Event oldEvent, Event newEvent) {
		if (! dc.isRequired() && ! m_startCalled) {
			return;
		}
        dc.invokeCallback(EventType.SWAPPED, oldEvent, newEvent);
	}
	
	/**
	 * Removes and closes all instance bound dependencies.
	 * This method is called when a component is destroyed.
	 */
    private void removeInstanceBoundDependencies() {
    	for (DependencyContext dep : m_dependencies) {
    		if (dep.isInstanceBound()) {
    			m_dependencies.remove(dep);
    			generateNameBasedOnServiceAndProperties();
    			dep.stop();
    		}
    	}
    }

	/**
	 * Clears the cache of invoked components callbacks.
	 * We only clear the cache when the state machine is not running.
	 * The cache is used to avoid calling the same bind callback twice.
	 * See FELIX-4913.
	 */
	private void clearInvokeCallbackCache() {
	    if (! isHandlingChange()) {
	    	m_invokeCallbackCache.clear();
	    }
	}
	
	private void invoke(String name) {
        if (name != null) {
            // if a callback instance was specified, look for the method there, if not,
            // ask the service for its composition instances
            Object[] instances = m_callbackInstance != null ? new Object[] { m_callbackInstance } : getCompositionInstances();

            long t1 = System.nanoTime();
            try {
                invokeCallbackMethod(instances, name, 
                    new Class[][] {{ Component.class }, {}}, 
                    new Object[][] {{ this }, {}},
                    false);
            } finally {
                long t2 = System.nanoTime();
                m_stopwatch.put(name, t2 - t1);
            }
        }
    }
    
	private void notifyListeners(ComponentState state) {
		if (m_scope == ServiceScope.SINGLETON) {
			m_lastStateDeliveredToListeners = state;
			for (ComponentStateListener l : m_listeners) {
				try {
					l.changed(this, state);
				} catch (Exception e) {
					m_logger.log(Logger.LOG_ERROR, "Exception caught while invoking component state listener", e);
				}
			}
		}
	}
	
	void autoConfigureImplementation(Class<?> clazz, Object instance) {
        if (((Boolean) m_autoConfig.get(clazz)).booleanValue()) {
            configureImplementation(clazz, instance, (String) m_autoConfigInstance.get(clazz));
        }
    }
    
   /**
     * Configure a field in the service implementation. The service implementation
     * is searched for fields that have the same type as the class that was specified
     * and for each of these fields, the specified instance is filled in.
     *
     * @param clazz the class to search for
     * @param instance the object to fill in the implementation class(es) field
     * @param instanceName the name of the instance to fill in, or <code>null</code> if not used
     */
    void configureImplementation(Class<?> clazz, Object instance, String fieldName) {
    	// don't inject anything if the component instance is a hidden prototype instance
    	if (m_injectionDisabled) {
    		return;
    	}

        Object[] targets = getInstances();
        if (! FieldUtil.injectField(targets, fieldName, clazz, instance, m_logger) && fieldName != null) {
            // If the target is an abstract decorator (i.e: an adapter, or an aspect), we must not log warnings
            // if field has not been injected.
            if (! (getInstance() instanceof AbstractDecorator)) {
                m_logger.log(Logger.LOG_ERROR, "Could not inject " + instance + " to field \"" + fieldName
                    + "\" at any of the following component instances: " + Arrays.toString(targets));
            }
        }
    }

    private void configureImplementation(Class<?> clazz, DependencyContext dc, String fieldName) {
    	// don't inject anything if the component instance is a hidden prototype instance
    	if (m_injectionDisabled) {
    		return;
    	}

        Object[] targets = getInstances();
        if (! FieldUtil.injectDependencyField(targets, fieldName, clazz, dc, m_logger) && fieldName != null) {
            // If the target is an abstract decorator (i.e: an adapter, or an aspect), we must not log warnings
            // if field has not been injected.
            if (! (getInstance() instanceof AbstractDecorator)) {
                m_logger.log(Logger.LOG_ERROR, "Could not inject dependency " + clazz.getName() + " to field \""
                    + fieldName + "\" at any of the following component instances: " + Arrays.toString(targets));
            }
        }
    }

    /**
     * Update the component instances.
     *
     * @param clazz the class of the dependency service to inject in the component instances
     * @param dc the dependency context for the updating dependency service
     * @param fieldName the component instances fieldname to fill in with the updated dependency service
     * @param event the event holding the updating service (service + properties)
     * @param update true if dependency service properties are updating, false if not. If false, it means
     *        that a dependency service is being added or removed. (see the "add" flag).
     * @param add true if the dependency service has been added, false if it has been removed. This flag is 
     *        ignored if the "update" flag is true (because the dependency properties are just being updated).
     */
    private void updateImplementation(Class<?> clazz, DependencyContext dc, String fieldName, Event event, boolean update, boolean add) {
    	if (! m_injectionDisabled) {
    		Object[] targets = getInstances();
    		FieldUtil.updateDependencyField(targets, fieldName, update, add, clazz, event, dc, m_logger);
    	}
    }

	private Object[] getCompositionInstances() {
        Object[] instances = null;
        if (m_compositionManagerGetMethod != null) {
            if (m_compositionManager != null) {
                m_compositionManagerInstance = m_compositionManager;
            }
            else {
                m_compositionManagerInstance = m_componentInstance;
            }
            if (m_compositionManagerInstance != null) {
                try {
                    instances = (Object[]) InvocationUtil.invokeMethod(m_compositionManagerInstance, m_compositionManagerInstance.getClass(), m_compositionManagerGetMethod, new Class[][] {{}}, new Object[][] {{}}, false);
                }
                catch (Exception e) {
                    m_logger.log(Logger.LOG_ERROR, "Could not obtain instances from the composition manager.", e);
                    instances = m_componentInstance == null ? new Object[] {} : new Object[] { m_componentInstance };
                }
            } else {
            	return new Object[0];
            }
        }
        else {
            instances = m_componentInstance == null ? new Object[] {} : new Object[] { m_componentInstance };
        }
        return instances;
	}
    
    /**
     * Executes a task using our component queue. The queue associated to this component is by default a "SerialExecutor", or 
     * a "DispatchExecutor" if a threadpool is used (that is: if a ComponentExecutorFactory has returned an executor this our 
     * component).
     * 
     * A SerialExecutor always try to execute the task synchronously, except if another master thread is currently 
     * running the SerialExecutor queue.
     * A DispatchExecutor always schedule the task asynchronously in a threadpool, but can optionally try to execute the task synchronously
     * (the threadpool is bypassed only if the queue is not currently being run by the threadpool).
     * 
     * The "bypassThreadPoolIfPossible" argument is only used in case there is a threadpool configured. If no threadpool is used, 
     * this argument is ignored and the task is run synchronously if the serial queue is not concurrently run from another 
     * master threads.
     * 
     * @param bypassThreadPoolIfPossible This argument is only used if a threadpool is configured for this component. if true, 
     * it means that if a threadpool is configured, then we attempt to run the task synchronously and not using the threadpool, 
     * but if the queue is currently run from the threadpool, then the task is scheduled in it. 
     * false means we always use the threadpool and the task is executed asynchronously.
     * @param task the task to execute.
     */
    private void schedule(boolean bypassThreadPoolIfPossible, Runnable task) {
		Executor exec = getExecutor();
		if (exec instanceof DispatchExecutor) {
			// We are using a threadpool. If byPassThreadPoolIsPossible is true, it means we can try to run the task synchronously from the current
			// thread. But if our queue is currently run from the threadpool, then the task will be run from it (asynchronously).
			((DispatchExecutor) exec).execute(task, ! bypassThreadPoolIfPossible);    			
		} else {
			// The queue is a serial queue: the task will be run synchronously, except if another master thread is currently running the queue.
			exec.execute(task);
		}
    }
    
    private void configureAutoConfigState(Component target, ComponentContext source) {
        configureAutoConfigState(target, source, BundleContext.class);
        configureAutoConfigState(target, source, ServiceRegistration.class);
        configureAutoConfigState(target, source, DependencyManager.class);
        configureAutoConfigState(target, source, Component.class);
    }
    
    private void configureAutoConfigState(Component target, ComponentContext source, Class<?> clazz) {
        String name = source.getAutoConfigInstance(clazz);
        if (name != null) {
            target.setAutoConfig(clazz, name);
        }
        else {
            target.setAutoConfig(clazz, source.getAutoConfig(clazz));
        }
    }    
    
	private final static Class[][] INIT_SIGNATUTES = new Class[][] { { Component.class }, {} };
	private final static Class[][] FACTORY_CREATE_SIGNATURES = new Class[][] { {}, { Component.class } };
    
    private boolean hasInitMethodWhenNotSingleton() {
    	if (m_callbackInit == null) {
    		return false;
    	}
		if (m_componentDefinition instanceof Class) {
			if (null != InvocationUtil.getCallbackMethod((Class<?>) m_componentDefinition, m_callbackInit, INIT_SIGNATUTES)) {
				return true;				
			}
		} else if (m_instanceFactoryCreateMethod != null) {
			if (m_instanceFactory != null) {
				Class<?> factoryClass = null;
			
				if (m_instanceFactory instanceof Class) {
					factoryClass = (Class<?>) m_instanceFactory;
				} else if (m_instanceFactory != null) {
					factoryClass = m_instanceFactory.getClass();
				}
				Method create = InvocationUtil.getCallbackMethod(factoryClass, m_instanceFactoryCreateMethod, FACTORY_CREATE_SIGNATURES);
				Class<?> componentType = create.getReturnType();
				if (componentType != null && InvocationUtil.getCallbackMethod(componentType, m_callbackInit, INIT_SIGNATUTES) != null) {
					return true;
				}
			}
		}
		return false;
    }    

    private void initPrototype() {
    	switch (m_scope) {
    	case PROTOTYPE:
    	case BUNDLE:
    		if (m_callbackInit == null || ! hasInitMethodWhenNotSingleton()) {
    			// when no init callback is defined, or if the component implementation does not actually has an init method, we disable injection for the component prototype instance.
    			m_injectionDisabled = true;
    		}
    		break;
    	}
    }
}
