/*
 * 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.TRACKING_OPTIONAL;
import static org.apache.felix.dm.ComponentState.WAITING_FOR_REQUIRED;

import java.lang.reflect.Constructor;
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 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.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 Class<?>[] VOID = new Class[] {};
    
    /**
     * 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 = new SerialExecutor(new Logger(null));
	
	/**
	 * 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 add 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 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;
    
    /**
     * 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;
	
    /**
     * 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;
        }
    }

    /**
     * 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_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_callbackInit = "init";
        m_callbackStart = "start";
        m_callbackStop = "stop";
        m_callbackDestroy = "destroy";
        m_id = m_idGenerator.getAndIncrement();
    }

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

	@Override
	public Component add(final Dependency ... dependencies) {
		getExecutor().execute(new Runnable() {
			@Override
			public void run() {
				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 another component).", dc,
                            ComponentImpl.this);
                        continue;
					}
					m_dependencyEvents.put(dc,  new ConcurrentSkipListSet<Event>());
					m_dependencies.add(dc);
					dc.setComponentContext(ComponentImpl.this);
					if (!(m_state == ComponentState.INACTIVE)) {
						dc.setInstanceBound(true);
						instanceBoundDeps.add(dc);
					}
				}
				startDependencies(instanceBoundDeps);
				handleChange();
			}
		});
		return this;
	}

	@Override
	public Component remove(final Dependency d) {
		getExecutor().execute(new Runnable() {
			@Override
			public void run() {
				DependencyContext dc = (DependencyContext) d;
				// First remove this dependency from the dependency list
                m_dependencies.remove(d);
                // 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() {
	    if (m_active.compareAndSet(false, true)) {
            getExecutor().execute(new Runnable() {
                @Override
                public void run() {
                    m_isStarted = true;
                    handleChange();
                }
            });
	    }
	}
	
	@Override
	public void stop() {           
	    if (m_active.compareAndSet(true, false)) {
	        Executor executor = getExecutor();

	        // First, declare the task that will stop our component in our executor.
	        final Runnable stopTask = new Runnable() {
                @Override
                public void run() {
                	m_isStarted = false;
                	handleChange();
                }
            };
            
            // Now, we have to schedule our stopTask in our component executor. But we have to handle a special case:
            // if the component bundle is stopping *AND* if the executor is a parallel dispatcher, then we want 
            // to invoke our stopTask synchronously, in order to make sure that the bundle context is valid while our 
            // component is being deactivated (if we stop the component asynchronously, the bundle context may be invalidated
            // before our component is stopped, and we don't want to be in this situation).
            
            boolean stopping = m_bundle != null /* null only in tests env */ && m_bundle.getState() == Bundle.STOPPING;
            if (stopping && executor instanceof DispatchExecutor) {
            	((DispatchExecutor) executor).execute(stopTask, false /* try to  execute synchronously, not using threadpool */);
            } else {
            	executor.execute(stopTask);
            }
	    }
	}

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

	@SuppressWarnings("unchecked")
    @Override
	public Component setInterface(String[] serviceName, Dictionary<?, ?> properties) {
	    ensureNotActive();
	    m_serviceName = serviceName;
	    m_serviceProperties = (Dictionary<Object, Object>) properties;
	    return this;
	}
	
	@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
        getExecutor().execute(new Runnable() {
            @Override
            public void run() {
                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 Component setAutoConfig(Class<?> clazz, boolean autoConfig) {
        m_autoConfig.put(clazz, Boolean.valueOf(autoConfig));
        return this;
    }
    
    @Override
    public Component 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());
            }
            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)) {
            if (m_logger == null) {
                System.out.println("Callback \"" + methodName + "\" not found on componnent instances "
                    + Arrays.toString(getInstances()));
            } else {
                m_logger.log(LogService.LOG_ERROR, "Callback \"" + methodName + "\" callback not found on componnent instances "
                    + Arrays.toString(getInstances()));
            }

        }
    }

    @Override
    public boolean isAvailable() {
        return m_state == TRACKING_OPTIONAL;
    }
    
    @Override
    public boolean isActive() {
        return m_active.get();
    }
    
    @Override
    public Component add(final ComponentStateListener l) {
        m_listeners.add(l);
        return this;
    }

    @Override
    public Component remove(ComponentStateListener l) {
        m_listeners.remove(l);
        return this;
    }

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

    @Override
    public Component setImplementation(Object implementation) {
        m_componentDefinition = implementation;
        return this;
    }
    
    @Override
    public ServiceRegistration getServiceRegistration() {
        return m_registration;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <K,V> Dictionary<K, V> getServiceProperties() {
        if (m_serviceProperties != null) {
            // Applied patch from FELIX-4304
            Hashtable<Object, Object> serviceProperties = new Hashtable<>();
            addTo(serviceProperties, m_serviceProperties);
            return (Dictionary<K, V>) serviceProperties;
        }
        return null;
    }

    @Override
    @SuppressWarnings("unchecked")
    public Component setServiceProperties(final Dictionary<?, ?> serviceProperties) {
        getExecutor().execute(new Runnable() {
            @Override
            public void run() {
                Dictionary<Object, Object> properties = null;
                m_serviceProperties = (Dictionary<Object, Object>) serviceProperties;
                if ((m_registration != null) && (m_serviceName != null)) {
                    properties = calculateServiceProperties();
                    m_registration.setProperties(properties);
                }
            }
        });
        return this;
    }
    
    public Component 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 Component 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 Component setFactory(Object factory, String createMethod) {
        ensureNotActive();
        m_instanceFactory = factory;
        m_instanceFactoryCreateMethod = createMethod;
        return this;
    }

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

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

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

    @Override
    public DependencyManager getDependencyManager() {
        return m_manager;
    }
    
    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() {
        StringBuffer sb = new StringBuffer();
        Object serviceName = m_serviceName;
        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]);
            }
            appendProperties(sb);
        } else if (serviceName instanceof String) {
            sb.append(serviceName.toString());
            appendProperties(sb);
        } else {
            Object implementation = m_componentDefinition;
            if (implementation != null) {
                if (implementation instanceof Class) {
                    sb.append(((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)) {
                            sb.append(implementation.getClass().getName());
                        } else {
                            sb.append(implementation.toString());
                        }
                    }  catch (java.lang.NoSuchMethodException e) {
                        // Just display the class name
                        sb.append(implementation.getClass().getName());
                    }
                }
            } else {
                sb.append(super.toString());
            }
        }
        return 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 instanceFactory.getClass().getName();
        } 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;
    }
    
    // ---------------------- Package/Private methods ---------------------------
    
    void instantiateComponent() {
        m_logger.debug("instantiating component.");

        // TODO add more complex factory instantiations of one or more components in a composition here
        if (m_componentInstance == null) {
            if (m_componentDefinition instanceof Class) {
                try {
                    m_componentInstance = createInstance((Class<?>) m_componentDefinition);
                }
                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 {
                                factory = createInstance((Class<?>) m_instanceFactory);
                            }
                            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 {
                            m_componentInstance = InvocationUtil.invokeMethod(factory, 
                                factory.getClass(), m_instanceFactoryCreateMethod, 
                                new Class[][] {{}, {Component.class}}, new Object[][] {{}, {this}}, 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);
        }
    }    
    
    /**
     * Runs the state machine, to see if a change event has to trigger some component state transition.
     */
    private void handleChange() {
        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) {
            startDependencies(m_dependencies);
            notifyListeners(newState);
            return true;
        }
        if (oldState == ComponentState.WAITING_FOR_REQUIRED && newState == ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
            instantiateComponent();
            invokeAutoConfigDependencies();
            invokeAddRequiredDependencies();
			ComponentState stateBeforeCallingInit = m_state;
            invoke(m_callbackInit); 
	        if (stateBeforeCallingInit == m_state) {
	            notifyListeners(newState); // init did not change current state, we can notify about this new state
	        }
            return true;
        }
        if (oldState == ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == ComponentState.TRACKING_OPTIONAL) {
            invokeAutoConfigInstanceBoundDependencies();
            invokeAddRequiredInstanceBoundDependencies();
            invokeStart();
            invokeAddOptionalDependencies();
            registerService();
            notifyListeners(newState);
            return true;
        }
        if (oldState == ComponentState.TRACKING_OPTIONAL && newState == ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
            unregisterService();
            invokeRemoveOptionalDependencies();
            invokeStop();
            invokeRemoveInstanceBoundDependencies();
            notifyListeners(newState);
            return true;
        }
        if (oldState == ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == ComponentState.WAITING_FOR_REQUIRED) {
            invoke(m_callbackDestroy);
            removeInstanceBoundDependencies();
            invokeRemoveRequiredDependencies();
            notifyListeners(newState);
            if (! someDependenciesNeedInstance()) {
                destroyComponent();
            }
            return true;
        }
        if (oldState == ComponentState.WAITING_FOR_REQUIRED && newState == ComponentState.INACTIVE) {
            stopDependencies();
            destroyComponent();
            notifyListeners(newState);
            return true;
        }
        return false;
    }
    
	private void invokeStart() {
        invoke(m_callbackStart);
        m_startCalled = true;
	}

    private void invokeStop() {
        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()) {
                if (dc.isRequired()) {
                    invokeCallbackSafe(dc, EventType.ADDED, e);
                }
                updateInstance(dc, e, false, true);
            } else {
                if (dc.isStarted() && dc.isRequired()) {
                    handleChange();
                }
            }
            break;
        case TRACKING_OPTIONAL:
            invokeCallbackSafe(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:
            invokeCallbackSafe(dc, EventType.CHANGED, e);
            updateInstance(dc, e, true, false);
            break;

        case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
            if (!dc.isInstanceBound()) {
                invokeCallbackSafe(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) {
        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()) {
                if (dc.isRequired()) {
                    invokeCallbackSafe(dc, EventType.REMOVED, e);
                }
                updateInstance(dc, e, false, false);
            }
            break;
        case TRACKING_OPTIONAL:
            invokeCallbackSafe(dc, EventType.REMOVED, e);
            updateInstance(dc, e, false, false);
            break;
        default:
        }
    }
    
    private void handleSwapped(DependencyContext dc, Event oldEvent, Event newEvent) {
        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()) {
                if (dc.isRequired()) {
                    dc.invokeCallback(EventType.SWAPPED, oldEvent, newEvent);
                }
            }
            break;
        case TRACKING_OPTIONAL:
            dc.invokeCallback(EventType.SWAPPED, oldEvent, newEvent);
            break;
        default:
        }
    }
    	
    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<?,?> properties = calculateServiceProperties();

            // register the service
            try {
                if (m_serviceName instanceof String) {
                    registration = m_context.registerService((String) m_serviceName, m_componentInstance, properties);
                }
                else {
                    registration = m_context.registerService((String[]) m_serviceName, m_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.ACTIVE) {
                    m_registration.unregister();
                }
            } catch (IllegalStateException e) { /* Should we really log this ? */}
            autoConfigureImplementation(ServiceRegistration.class, NULL_REGISTRATION);
            m_registration = null;
        }
    }
    
    private Dictionary<Object, Object> calculateServiceProperties() {
		Dictionary<Object, Object> properties = new Hashtable<>();
		for (int i = 0; i < m_dependencies.size(); i++) {
			DependencyContext d = (DependencyContext) m_dependencies.get(i);
			if (d.isPropagated() && d.isAvailable()) {
				Dictionary<Object, Object> dict = d.getProperties();
				addTo(properties, dict);
			}
		}
		// our service properties must not be overriden by propagated dependency properties, so we add our service
		// properties after having added propagated dependency properties.
		addTo(properties, m_serviceProperties);
		if (properties.size() == 0) {
			properties = null;
		}
		return properties;
	}

	private void addTo(Dictionary<Object, Object> properties, Dictionary<Object, Object> additional) {
		if (properties == null) {
			throw new IllegalArgumentException("Dictionary to add to cannot be null.");
		}
		if (additional != null) {
			Enumeration<Object> e = additional.keys();
			while (e.hasMoreElements()) {
				Object key = e.nextElement();
				properties.put(key, 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)) {
			        invokeCallbackSafe(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)) {
	                 invokeCallbackSafe(d, EventType.ADDED, e);
	             }
			}
		}
	}
	
    private void invokeAddOptionalDependencies() {
        for (DependencyContext d : m_dependencies) {
            if (! d.isRequired()) {
                for (Event e : m_dependencyEvents.get(d)) {
                    invokeCallbackSafe(d, EventType.ADDED, e);
                }
            }
        }
    }

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

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

	private void invokeRemoveInstanceBoundDependencies() {
		for (DependencyContext d : m_dependencies) {
			if (d.isInstanceBound()) {
                for (Event e : m_dependencyEvents.get(d)) {
                    invokeCallbackSafe(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 invokeCallbackSafe(DependencyContext dc, EventType type, Event event) {
		if (! dc.isRequired() && ! m_startCalled) {
			return;
		}
		if (m_invokeCallbackCache.put(event, event) == null) {
			dc.invokeCallback(type, event);
		}		
	}
	
	/**
	 * 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);
    			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 Object createInstance(Class<?> clazz) throws SecurityException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Constructor<?> constructor = clazz.getConstructor(VOID);
		constructor.setAccessible(true);
        return constructor.newInstance();
    }

	private void notifyListeners(ComponentState state) {
		for (ComponentStateListener l : m_listeners) {
			l.changed(this, state);
		}
	}
	
    private 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
     */
    private void configureImplementation(Class<?> clazz, Object instance, String fieldName) {
        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) {
        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)
    {
        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 {
            instances = m_componentInstance == null ? new Object[] {} : new Object[] { m_componentInstance };
        }
        return instances;
	}

    private void appendProperties(StringBuffer result) {
        Dictionary<Object, Object> properties = calculateServiceProperties();
        if (properties != null) {
            result.append("(");
            Enumeration<?> enumeration = properties.keys();
            while (enumeration.hasMoreElements()) {
                Object key = enumeration.nextElement();
                result.append(key.toString());
                result.append('=');
                Object value = properties.get(key);
                if (value instanceof String[]) {
                    String[] values = (String[]) value;
                    result.append('{');
                    for (int i = 0; i < values.length; i++) {
                        if (i > 0) {
                            result.append(',');
                        }
                        result.append(values[i].toString());
                    }
                    result.append('}');
                }
                else {
                    result.append(value.toString());
                }
                if (enumeration.hasMoreElements()) {
                    result.append(',');
                }
            }
            result.append(")");
        }
    }
    
    private Executor getExecutor() {
        return m_executor;
    }
}
