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

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import org.apache.felix.dm.Component;
import org.apache.felix.dm.ComponentDependencyDeclaration;
import org.apache.felix.dm.Dependency;
import org.apache.felix.dm.DependencyService;
import org.apache.felix.dm.InvocationUtil;
import org.apache.felix.dm.ServiceDependency;
import org.apache.felix.dm.ServiceUtil;
import org.apache.felix.dm.impl.DefaultNullObject;
import org.apache.felix.dm.impl.Logger;
import org.apache.felix.dm.tracker.ServiceTracker;
import org.apache.felix.dm.tracker.ServiceTrackerCustomizer;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;

/**
 * Service dependency that can track an OSGi service.
 * 
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class ServiceDependencyImpl extends DependencyBase implements ServiceDependency, ServiceTrackerCustomizer, ComponentDependencyDeclaration {
    protected List m_services = new ArrayList();
    protected volatile ServiceTracker m_tracker;
    protected BundleContext m_context;
    protected volatile Class m_trackedServiceName;
    private Object m_nullObject;
    private volatile String m_trackedServiceFilter;
    private volatile String m_trackedServiceFilterUnmodified;
    private volatile ServiceReference m_trackedServiceReference;
    private Object m_callbackInstance;
    private String m_callbackAdded;
    private String m_callbackChanged;
    private String m_callbackRemoved;
    private String m_callbackSwapped;
    private boolean m_autoConfig;
    protected ServiceReference m_reference;
    protected Object m_serviceInstance;
    private String m_autoConfigInstance;
    private boolean m_autoConfigInvoked;
    private Object m_defaultImplementation;
    private Object m_defaultImplementationInstance;
    private boolean m_isAvailable;
    private boolean m_propagate;
    private Object m_propagateCallbackInstance;
    private String m_propagateCallbackMethod;
    private final Map m_sr = new HashMap(); /* <DependencyService, Set<Tuple<ServiceReference, Object>> */
	private Map m_componentByRank = new HashMap(); /* <Component, Map<Long, Map<Integer, Tuple>>> */
    
    private static final Comparator COMPARATOR = new Comparator() {
        public int getRank(ServiceReference ref) {
            Object ranking = ref.getProperty(Constants.SERVICE_RANKING);
            if (ranking != null && (ranking instanceof Integer)) {
                return ((Integer) ranking).intValue();
            }
            return 0;
        }

        public int compare(Object a, Object b) {
            ServiceReference ra = (ServiceReference) a, rb = (ServiceReference) b;
            int ranka = getRank(ra);
            int rankb = getRank(rb);
            if (ranka < rankb) {
                return -1;
            }
            else if (ranka > rankb) {
                return 1;
            }
            return 0;
        }
    };
    
    private static final class Tuple /* <ServiceReference, Object> */ {
        private final ServiceReference m_serviceReference;
        private final Object m_service;
        
        public Tuple(ServiceReference first, Object last) {
            m_serviceReference = first;
            m_service = last;
        }
        
        public ServiceReference getServiceReference() {
            return m_serviceReference;
        }
        
        public Object getService() {
            return m_service;
        }
        
        public boolean equals(Object obj) {
            return ((Tuple) obj).getServiceReference().equals(getServiceReference());
        }
        
        public int hashCode() {
            return m_serviceReference.hashCode();
        }
    }
    
    /**
     * Entry to wrap service properties behind a Map.
     */
    private static final class ServicePropertiesMapEntry implements Map.Entry {
        private final String m_key;
        private Object m_value;

        public ServicePropertiesMapEntry(String key, Object value) {
            m_key = key;
            m_value = value;
        }

        public Object getKey() {
            return m_key;
        }

        public Object getValue() {
            return m_value;
        }

        public String toString() {
            return m_key + "=" + m_value;
        }

        public Object setValue(Object value) {
            Object oldValue = m_value;
            m_value = value;
            return oldValue;
        }

        public boolean equals(Object o) {
            if (!(o instanceof Map.Entry)) {
                return false;
            }
            Map.Entry e = (Map.Entry) o;
            return eq(m_key, e.getKey()) && eq(m_value, e.getValue());
        }

        public int hashCode() {
            return ((m_key == null) ? 0 : m_key.hashCode()) ^ ((m_value == null) ? 0 : m_value.hashCode());
        }

        private static final boolean eq(Object o1, Object o2) {
            return (o1 == null ? o2 == null : o1.equals(o2));
        }
    }

    /**
     * Wraps service properties behind a Map.
     */
    private final static class ServicePropertiesMap extends AbstractMap {
        private final ServiceReference m_ref;

        public ServicePropertiesMap(ServiceReference ref) {
            m_ref = ref;
        }

        public Object get(Object key) {
            return m_ref.getProperty(key.toString());
        }

        public int size() {
            return m_ref.getPropertyKeys().length;
        }

        public Set entrySet() {
            Set set = new HashSet();
            String[] keys = m_ref.getPropertyKeys();
            for (int i = 0; i < keys.length; i++) {
                set.add(new ServicePropertiesMapEntry(keys[i], m_ref.getProperty(keys[i])));
            }
            return set;
        }
    }
        
    /**
     * Creates a new service dependency.
     * 
     * @param context the bundle context
     * @param logger the logger
     */
    public ServiceDependencyImpl(BundleContext context, Logger logger) {
        super(logger);
        m_context = context;
        m_autoConfig = true;
    }
    
    /** Copying constructor that clones an existing instance. */
    public ServiceDependencyImpl(ServiceDependencyImpl prototype) {
        super(prototype);
        synchronized (prototype) {
            m_context = prototype.m_context;
            m_autoConfig = prototype.m_autoConfig;
            m_trackedServiceName = prototype.m_trackedServiceName;
            m_nullObject = prototype.m_nullObject;
            m_trackedServiceFilter = prototype.m_trackedServiceFilter;
            m_trackedServiceFilterUnmodified = prototype.m_trackedServiceFilterUnmodified;
            m_trackedServiceReference = prototype.m_trackedServiceReference;
            m_callbackInstance = prototype.m_callbackInstance;
            m_callbackAdded = prototype.m_callbackAdded;
            m_callbackChanged = prototype.m_callbackChanged;
            m_callbackRemoved = prototype.m_callbackRemoved;
            m_callbackSwapped = prototype.m_callbackSwapped;
            m_autoConfigInstance = prototype.m_autoConfigInstance;
            m_defaultImplementation = prototype.m_defaultImplementation;
        }
    }
    
    public Dependency createCopy() {
        return new ServiceDependencyImpl(this);
    }
    
    public synchronized boolean isAutoConfig() {
        return m_autoConfig;
    }
    
    public synchronized boolean isAvailable() {
        return m_isAvailable;
    }

    public synchronized Object getService() {
        Object service = null;
        if (m_isStarted) {
            service = m_tracker.getService();
        }
        if (service == null && isAutoConfig()) {
            service = getDefaultImplementation();
            if (service == null) {
                service = getNullObject();
            }
        }
        return service;
    }

    public Object lookupService() {
        Object service = null;
        if (m_isStarted) {
            service = getService();
        }
        else {
            ServiceReference[] refs = null;
            ServiceReference ref = null;
            if (m_trackedServiceName != null) {
                if (m_trackedServiceFilter != null) {
                    try {
                        refs = m_context.getServiceReferences(m_trackedServiceName.getName(), m_trackedServiceFilter);
                        if (refs != null) {
                            Arrays.sort(refs, COMPARATOR);
                            ref = refs[0];
                        }
                    }
                    catch (InvalidSyntaxException e) {
                        throw new IllegalStateException("Invalid filter definition for dependency.");
                    }
                }
                else if (m_trackedServiceReference != null) {
                    ref = m_trackedServiceReference;
                }
                else {
                    ref = m_context.getServiceReference(m_trackedServiceName.getName());
                }
                if (ref != null) {
                    service = m_context.getService(ref);
                }
            }
            else {
                throw new IllegalStateException("Could not lookup dependency, no service name specified.");
            }
        }
        if (service == null && isAutoConfig()) {
            service = getDefaultImplementation();
            if (service == null) {
                service = getNullObject();
            }
        }
        return service;
    }

    // TODO lots of duplication in lookupService()
    public ServiceReference lookupServiceReference() {
        ServiceReference service = null;
        if (m_isStarted) {
            service = m_tracker.getServiceReference();
        }
        else {
            ServiceReference[] refs = null;
            ServiceReference ref = null;
            if (m_trackedServiceName != null) {
                if (m_trackedServiceFilter != null) {
                    try {
                        refs = m_context.getServiceReferences(m_trackedServiceName.getName(), m_trackedServiceFilter);
                        if (refs != null) {
                            Arrays.sort(refs, COMPARATOR);
                            ref = refs[0];
                        }
                    }
                    catch (InvalidSyntaxException e) {
                        throw new IllegalStateException("Invalid filter definition for dependency.");
                    }
                }
                else if (m_trackedServiceReference != null) {
                    ref = m_trackedServiceReference;
                }
                else {
                    ref = m_context.getServiceReference(m_trackedServiceName.getName());
                }
                if (ref != null) {
                    service = ref;
                }
            }
            else {
                throw new IllegalStateException("Could not lookup dependency, no service name specified.");
            }
        }
        return service;
    }

    private Object getNullObject() {
        if (m_nullObject == null) {
            Class trackedServiceName;
            synchronized (this) {
                trackedServiceName = m_trackedServiceName;
            }
            try {
                m_nullObject = Proxy.newProxyInstance(trackedServiceName.getClassLoader(), new Class[] {trackedServiceName}, new DefaultNullObject()); 
            }
            catch (Exception e) {
                m_logger.log(Logger.LOG_ERROR, "Could not create null object for " + trackedServiceName + ".", e);
            }
        }
        return m_nullObject;
    }
    
    private Object getDefaultImplementation() {
        if (m_defaultImplementation != null) {
            if (m_defaultImplementation instanceof Class) {
                try {
                    m_defaultImplementationInstance = ((Class) m_defaultImplementation).newInstance();
                }
                catch (Exception e) {
                    m_logger.log(Logger.LOG_ERROR, "Could not create default implementation instance of class " + m_defaultImplementation + ".", e);
                }
            }
            else {
                m_defaultImplementationInstance = m_defaultImplementation;
            }
        }
        return m_defaultImplementationInstance;
    }
    
    public synchronized Class getInterface() {
        return m_trackedServiceName;
    }

    public void start(DependencyService service) {
        boolean needsStarting = false;
        synchronized (this) {
            m_services.add(service);
            if (!m_isStarted) {
                if (m_trackedServiceName != null) {
                    if (m_trackedServiceFilter != null) {
                        try {
                            m_tracker = new ServiceTracker(m_context, m_context.createFilter(m_trackedServiceFilter), this);
                        }
                        catch (InvalidSyntaxException e) {
                            throw new IllegalStateException("Invalid filter definition for dependency: " + m_trackedServiceFilter);
                        }
                    }
                    else if (m_trackedServiceReference != null) {
                        m_tracker = new ServiceTracker(m_context, m_trackedServiceReference, this);
                    }
                    else {
                        m_tracker = new ServiceTracker(m_context, m_trackedServiceName.getName(), this);
                    }
                }
                else {
                    throw new IllegalStateException("Could not create tracker for dependency, no service name specified.");
                }
                m_isStarted = true;
                needsStarting = true;
            }
        }
        if (needsStarting) {
            m_tracker.open();
        }
    }

    public void stop(DependencyService service) {
        boolean needsStopping = false;
        synchronized (this) {
            if (m_services.size() == 1 && m_services.contains(service)) {
                m_isStarted = false;
                needsStopping = true;
            }
        }
        if (needsStopping) {
            m_tracker.close();
            m_tracker = null;
        }
        //moved this down
        synchronized (this) {
            m_services.remove(service);
        }
    }

    public Object addingService(ServiceReference ref) {
        Object service = m_context.getService(ref);
        // first check to make sure the service is actually an instance of our service
        if (!m_trackedServiceName.isInstance(service)) {
            return null;
        }
        return service;
    }

    public void addedService(ServiceReference ref, Object service) {
        boolean makeAvailable = makeAvailable();
        
        Object[] services;
        synchronized (this) {
            services = m_services.toArray();
        }
        for (int i = 0; i < services.length; i++) {
            DependencyService ds = (DependencyService) services[i];
            if (makeAvailable) {
                if (ds.isInstantiated() && isInstanceBound() && isRequired()) {
                    invokeAdded(ds, ref, service);
                }
                // The dependency callback will be defered until all required dependency are available.
                ds.dependencyAvailable(this);
                if (!isRequired()) {
                    // For optional dependency, we always invoke callback, because at this point, we know
                    // that the service has been started, and the service start method has been called.
                    // (See the ServiceImpl.bindService method, which will activate optional dependencies using 
                    // startTrackingOptional() method). 
                    invokeAdded(ds, ref, service);
                }
            }
            else {
                ds.dependencyChanged(this);
                // At this point, either the dependency is optional (meaning that the service has been started,
                // because if not, then our dependency would not be active); or the dependency is required,
                // meaning that either the service is not yet started, or already started.
                // In all cases, we have to inject the required dependency.
                
                // we only try to invoke the method here if we are really already instantiated
                if (ds.isInstantiated() && ds.getCompositionInstances().length > 0) {
                    invokeAdded(ds, ref, service);
                }
            }
        }
    }

    public void modifiedService(ServiceReference ref, Object service) {
        Object[] services;
        synchronized (this) {
            services = m_services.toArray();
        }
        for (int i = 0; i < services.length; i++) {
            DependencyService ds = (DependencyService) services[i];
            ds.dependencyChanged(this);
            if (ds.isRegistered()) {
                invokeChanged(ds, ref, service);
            }
        }
    }

    public void removedService(ServiceReference ref, Object service) {
        boolean makeUnavailable = makeUnavailable();
        
        Object[] services;
        synchronized (this) {
            services = m_services.toArray();
        }

        for (int i = 0; i < services.length; i++) {
            DependencyService ds = (DependencyService) services[i];
            if (makeUnavailable) {
                ds.dependencyUnavailable(this);
                if (!isRequired() || (ds.isInstantiated() && isInstanceBound())) {
                    invokeRemoved(ds, ref, service);
                }
            }
            else {
                ds.dependencyChanged(this);
                invokeRemoved(ds, ref, service);
            }
        }
        // unget what we got in addingService (see ServiceTracker 701.4.1)
        m_context.ungetService(ref);

    }
    
    public void invokeAdded(DependencyService dependencyService, ServiceReference reference, Object service) {
        boolean added = false;
        synchronized (m_sr) {
            Set set = (Set) m_sr.get(dependencyService);
            if (set == null) {
                set = new HashSet();
                m_sr.put(dependencyService, set);
            }
            added = set.add(new Tuple(reference, service));
        }
        if (added) { 
        	// when a changed callback is specified we might not call the added callback just yet
        	if (m_callbackSwapped != null) {
        		handleAspectAwareAdded(dependencyService, reference, service);
        	}
        	else {
        		invoke(dependencyService, reference, service, m_callbackAdded);
        	}
        }
    }
    
    private void handleAspectAwareAdded(DependencyService dependencyService, ServiceReference reference, Object service) {
		if (componentIsDependencyManagerFactory(dependencyService)) {
			// component is either aspect or adapter factory instance, these must be ignored.
			return;
		}
		boolean invokeAdded = false;
		Integer ranking = ServiceUtil.getRankingAsInteger(reference);
		Tuple highestRankedService = null;
		synchronized (m_componentByRank) {
			Long originalServiceId = ServiceUtil.getServiceIdAsLong(reference);
			Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
			if (componentMap == null) {
				// create new componentMap
				componentMap = new HashMap(); /* <Long, Map<Integer, Tuple>> */
				m_componentByRank.put(dependencyService, componentMap);
			}
			Map rankings = (Map) componentMap.get(originalServiceId); /* <Integer, Tuple> */
			if (rankings == null) {
				// new component added
				rankings = new HashMap(); /* <Integer, Tuple> */
				componentMap.put(originalServiceId, rankings);
				rankings.put(ranking, new Tuple(reference, service));
				invokeAdded = true;
			} 
			
			if (!invokeAdded) {
				highestRankedService = swapHighestRankedService(dependencyService, originalServiceId, reference, service, ranking);
			}
		}
		if (invokeAdded) {
			invoke(dependencyService, reference, service, m_callbackAdded);
		} else {
			invokeSwappedCallback(dependencyService, highestRankedService.getServiceReference(), highestRankedService.getService(), reference, service);
		}    	
    }
    
    private boolean componentIsDependencyManagerFactory(DependencyService dependencyService) {
        Object component = dependencyService.getService();
        if (component != null) {
            String className = component.getClass().getName();
            return className.startsWith("org.apache.felix.dm")
                && !className.startsWith("org.apache.felix.dm.impl.AdapterServiceImpl$AdapterImpl")
                && !className.startsWith("org.apache.felix.dm.test");
        }
        return false;
    }
    
	private Tuple swapHighestRankedService(DependencyService dependencyService, Long serviceId, ServiceReference newReference, Object newService, Integer newRanking) {
		// does a component with a higher ranking exists
		synchronized (m_componentByRank) {
			Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
			Map rankings = (Map) componentMap.get(serviceId); /* <Integer, Tuple> */
			Entry highestEntry = getHighestRankedService(dependencyService, serviceId); /* <Integer, Tuple> */
			rankings.remove(highestEntry.getKey());
			rankings.put(newRanking, new Tuple(newReference, newService));
			return (Tuple) highestEntry.getValue();
		}
	}
	
	private Entry getHighestRankedService(DependencyService dependencyService, Long serviceId) { /* <Integer, Tuple> */
		Entry highestEntry = null; /* <Integer, Tuple> */
		Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
		Map rankings = (Map) componentMap.get(serviceId); /* <Integer, Tuple> */
		if (rankings != null) {
			for (Iterator entryIterator = rankings.entrySet().iterator(); entryIterator.hasNext(); ) { /* <Integer, Tuple> */
				Entry mapEntry = (Entry) entryIterator.next();
				if (highestEntry == null) {
					highestEntry = mapEntry;
				} else {
					if (((Integer)mapEntry.getKey()).intValue() > ((Integer)highestEntry.getKey()).intValue()) {
						highestEntry = mapEntry;
					}
				}
			}
		}
		return highestEntry;
	}



	private boolean isLastService(DependencyService dependencyService, ServiceReference reference, Object object, Long serviceId) {
		// get the collection of rankings
		Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
		
		Map rankings = null; /* <Integer, Tuple> */
		if (componentMap != null) {
			rankings = (Map) componentMap.get(serviceId);
		}
		// if there is only one element left in the collection of rankings
		// and this last element has the same ranking as the supplied service (in other words, it is the same)
		// then this is the last service
		// NOTE: it is possible that there is only one element, but that it's not equal to the supplied service,
		// because an aspect on top of the original service is being removed (but the original service is still
		// there). That in turn triggers:
		// 1) a call to added(original-service)
		// 2) that causes a swap
		// 3) a call to removed(aspect-service) <-- that's what we're talking about
		return (componentMap != null && rankings != null && rankings.size() == 1 && ((Entry)rankings.entrySet().iterator().next()).getKey()
				.equals(ServiceUtil.getRankingAsInteger(reference)));
	}
	
	
    public void invokeChanged(DependencyService dependencyService, ServiceReference reference, Object service) {
        invoke(dependencyService, reference, service, m_callbackChanged);
    }

    public void invokeRemoved(DependencyService dependencyService, ServiceReference reference, Object service) {
        boolean removed = false;
        synchronized (m_sr) {
            Set set = (Set) m_sr.get(dependencyService);
            removed = (set != null && set.remove(new Tuple(reference, service)));
        }
        if (removed) {
        	if (m_callbackSwapped != null) {
        		handleAspectAwareRemoved(dependencyService, reference, service);
        	}
        	else {
        		invoke(dependencyService, reference, service, m_callbackRemoved);
        	}
        }
    }
    
	private void handleAspectAwareRemoved(DependencyService dependencyService, ServiceReference reference, Object service) {
		if (componentIsDependencyManagerFactory(dependencyService)) {
			// component is either aspect or adapter factory instance, these must be ignored.
			return;
		}
		Long serviceId = ServiceUtil.getServiceIdAsLong(reference);
			synchronized (m_componentByRank) {
				if (isLastService(dependencyService, reference, service, serviceId)) {
					invoke(dependencyService, reference, service, m_callbackRemoved);
				}
				Long originalServiceId = ServiceUtil.getServiceIdAsLong(reference);
				Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
				if (componentMap != null) {
					Map rankings = (Map) componentMap.get(originalServiceId); /* <Integer, Tuple> */
					for (Iterator entryIterator = rankings.entrySet().iterator(); entryIterator.hasNext(); ) {
						Entry mapEntry = (Entry) entryIterator.next();
						if (((Tuple)mapEntry.getValue()).getServiceReference().equals(reference)) {
							// remove the reference
							rankings.remove(mapEntry.getKey());
						}
					}
					if (rankings.size() == 0) {
						componentMap.remove(originalServiceId);
					}
					if (componentMap.size() == 0) {
						m_componentByRank.remove(dependencyService);
					}
				}
			}
	}    

    public void invoke(DependencyService dependencyService, ServiceReference reference, Object service, String name) {
        if (name != null) {
            dependencyService.invokeCallbackMethod(getCallbackInstances(dependencyService), name, 
                new Class[][] {
                    {Component.class, ServiceReference.class, m_trackedServiceName}, {Component.class, ServiceReference.class, Object.class}, {Component.class, ServiceReference.class}, {Component.class, m_trackedServiceName}, {Component.class, Object.class}, {Component.class}, {Component.class, Map.class, m_trackedServiceName},
                    {ServiceReference.class, m_trackedServiceName}, {ServiceReference.class, Object.class}, {ServiceReference.class}, {m_trackedServiceName}, {Object.class}, {}, {Map.class, m_trackedServiceName}
                },
                new Object[][] {
                    {dependencyService, reference, service}, {dependencyService, reference, service}, {dependencyService, reference}, {dependencyService, service}, {dependencyService, service}, {dependencyService}, {dependencyService, new ServicePropertiesMap(reference), service},
                    {reference, service}, {reference, service}, {reference}, {service}, {service}, {}, {new ServicePropertiesMap(reference), service}
                }    
            );
        }
    }
    
	private void invokeSwappedCallback(DependencyService component, ServiceReference previousReference, Object previous, ServiceReference currentServiceReference,
			Object current) {
		// sanity check on the service references
		Integer oldRank = (Integer) previousReference.getProperty(Constants.SERVICE_RANKING);
		Integer newRank = (Integer) currentServiceReference.getProperty(Constants.SERVICE_RANKING);
		
		if (oldRank != null && newRank != null && oldRank.equals(newRank)) {
			throw new IllegalStateException("Attempt to swap a service for a service with the same rank! previousReference: " + previousReference + ", currentReference: " + currentServiceReference);
		}
		
		component.invokeCallbackMethod(getCallbackInstances(component), m_callbackSwapped, new Class[][] { { m_trackedServiceName, m_trackedServiceName },
				{ Object.class, Object.class }, { ServiceReference.class, m_trackedServiceName, ServiceReference.class, m_trackedServiceName },
				{ ServiceReference.class, Object.class, ServiceReference.class, Object.class } }, new Object[][] { { previous, current },
				{ previous, current }, { previousReference, previous, currentServiceReference, current },
				{ previousReference, previous, currentServiceReference, current } });
	}    

    protected synchronized boolean makeAvailable() {
        if (!isAvailable()) {
            m_isAvailable = true;
            return true;
        }
        return false;
    }
    
    private synchronized boolean makeUnavailable() {
        if ((isAvailable()) && (m_tracker.getServiceReference() == null)) {
            m_isAvailable = false;
            return true;
        }
        return false;
    }
    
    private synchronized Object[] getCallbackInstances(DependencyService dependencyService) {
        if (m_callbackInstance == null) {
            return dependencyService.getCompositionInstances();
        }
        else {
            return new Object[] { m_callbackInstance };
        }
    }
    
    // ----- CREATION

    /**
     * Sets the name of the service that should be tracked. 
     * 
     * @param serviceName the name of the service
     * @return this service dependency
     */
    public synchronized ServiceDependency setService(Class serviceName) {
        setService(serviceName, null, null);
        return this;
    }
    
    /**
     * Sets the name of the service that should be tracked. You can either specify
     * only the name, only the filter, or the name and a filter.
     * <p>
     * If you specify name and filter, the filter is used
     * to track the service and should only return services of the type that was specified
     * in the name. To make sure of this, the filter is actually extended internally to
     * filter on the correct name.
     * <p>
     * If you specify only the filter, the name is assumed to be a service of type
     * <code>Object</code> which means that, when auto configuration is on, instances
     * of that service will be injected in any field of type <code>Object</code>.
     * 
     * @param serviceName the name of the service
     * @param serviceFilter the filter condition
     * @return this service dependency
     */
    public synchronized ServiceDependency setService(Class serviceName, String serviceFilter) {
        setService(serviceName, null, serviceFilter);
        return this;
    }
    
    /**
     * Sets the name of the service that should be tracked. The name is assumed to be 
     * a service of type <code>Object</code> which means that, when auto configuration 
     * is on, instances of that service will be injected in any field of type 
     * <code>Object</code>.
     * 
     * @param serviceFilter the filter condition
     * @return this service dependency
     */
    public synchronized ServiceDependency setService(String serviceFilter) {
        if (serviceFilter == null) {
            throw new IllegalArgumentException("Service filter cannot be null.");
        }
        setService(null, null, serviceFilter);
        return this;
    }

    /**
     * Sets the name of the service that should be tracked. By specifying the service
     * reference of the service you want to track, you can directly track a single
     * service. The name you use must match the type of service referred to by the
     * service reference and it is up to you to make sure that is the case.
     * 
     * @param serviceName the name of the service
     * @param serviceReference the service reference to track
     * @return this service dependency
     */
    public synchronized ServiceDependency setService(Class serviceName, ServiceReference serviceReference) {
        setService(serviceName, serviceReference, null);
        return this;
    }

    /** Internal method to set the name, service reference and/or filter. */
    private void setService(Class serviceName, ServiceReference serviceReference, String serviceFilter) {
        ensureNotActive();
        if (serviceName == null) {
            m_trackedServiceName = Object.class;
        }
        else {
            m_trackedServiceName = serviceName;
        }
        if (serviceFilter != null) {
            m_trackedServiceFilterUnmodified = serviceFilter;
            if (serviceName == null) {
                m_trackedServiceFilter = serviceFilter;
            }
            else {
                m_trackedServiceFilter ="(&(" + Constants.OBJECTCLASS + "=" + serviceName.getName() + ")" + serviceFilter + ")";
            }
        }
        else {
            m_trackedServiceFilterUnmodified = null;
            m_trackedServiceFilter = null;
        }
        if (serviceReference != null) {
            m_trackedServiceReference = serviceReference;
            if (serviceFilter != null) {
                throw new IllegalArgumentException("Cannot specify both a filter and a service reference.");
            }
        }
        else {
            m_trackedServiceReference = null;
        }
    }
    
    /**
     * Sets the default implementation for this service dependency. You can use this to supply
     * your own implementation that will be used instead of a Null Object when the dependency is
     * not available. This is also convenient if the service dependency is not an interface
     * (which would cause the Null Object creation to fail) but a class.
     * 
     * @param implementation the instance to use or the class to instantiate if you want to lazily
     *     instantiate this implementation
     * @return this service dependency
     */
    public synchronized ServiceDependency setDefaultImplementation(Object implementation) {
        ensureNotActive();
        m_defaultImplementation = implementation;
        return this;
    }

    /**
     * Sets the required flag which determines if this service is required or not.
     * 
     * @param required the required flag
     * @return this service dependency
     */
    public synchronized ServiceDependency setRequired(boolean required) {
        ensureNotActive();
        setIsRequired(required);
        return this;
    }
    
    public ServiceDependency setInstanceBound(boolean isInstanceBound) {
        setIsInstanceBound(isInstanceBound);
        return this;
    }

    /**
     * Sets auto configuration for this service. Auto configuration allows the
     * dependency to fill in any attributes in the service implementation that
     * are of the same type as this dependency. Default is on.
     * 
     * @param autoConfig the value of auto config
     * @return this service dependency
     */
    public synchronized ServiceDependency setAutoConfig(boolean autoConfig) {
        ensureNotActive();
        m_autoConfig = autoConfig;
        m_autoConfigInvoked = true;
        return this;
    }
    
    /**
     * Sets auto configuration for this service. Auto configuration allows the
     * dependency to fill in the attribute in the service implementation that
     * has the same type and instance name.
     * 
     * @param instanceName the name of attribute to auto config
     * @return this service dependency
     */
    public synchronized ServiceDependency setAutoConfig(String instanceName) {
        ensureNotActive();
        m_autoConfig = (instanceName != null);
        m_autoConfigInstance = instanceName;
        m_autoConfigInvoked = true;
        return this;
    }
    
    /**
     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
     * dependency is added or removed. When you specify callbacks, the auto configuration 
     * feature is automatically turned off, because we're assuming you don't need it in this 
     * case.
     * 
     * @param added the method to call when a service was added
     * @param removed the method to call when a service was removed
     * @return this service dependency
     */
    public synchronized ServiceDependency setCallbacks(String added, String removed) {
        return setCallbacks((Object) null, added, null, removed);
    }

    /**
     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
     * dependency is added, changed or removed. When you specify callbacks, the auto 
     * configuration feature is automatically turned off, because we're assuming you don't 
     * need it in this case.
     * 
     * @param added the method to call when a service was added
     * @param changed the method to call when a service was changed
     * @param removed the method to call when a service was removed
     * @return this service dependency
     */
    public synchronized ServiceDependency setCallbacks(String added, String changed, String removed) {
        return setCallbacks((Object) null, added, changed, removed);
    }
    
    /**
     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
     * dependency is added, changed or removed. When you specify callbacks, the auto 
     * configuration feature is automatically turned off, because we're assuming you don't 
     * need it in this case.
     * @param added the method to call when a service was added
     * @param changed the method to call when a service was changed
     * @param removed the method to call when a service was removed
     * @param swapped the method to call when the service was swapped due to addition or 
     * removal of an aspect
     * @return this service dependency
     */
    public synchronized ServiceDependency setCallbacks(String added, String changed, String removed, String swapped) {
    	return setCallbacks((Object) null, added, changed, removed, swapped);
    }

    /**
     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
     * dependency is added or removed. They are called on the instance you provide. When you
     * specify callbacks, the auto configuration feature is automatically turned off, because
     * we're assuming you don't need it in this case.
     * 
     * @param instance the instance to call the callbacks on
     * @param added the method to call when a service was added
     * @param removed the method to call when a service was removed
     * @return this service dependency
     */
    public synchronized ServiceDependency setCallbacks(Object instance, String added, String removed) {
        return setCallbacks(instance, added, (String) null, removed);
    }
    
    /**
     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
     * dependency is added, changed or removed. They are called on the instance you provide. When you
     * specify callbacks, the auto configuration feature is automatically turned off, because
     * we're assuming you don't need it in this case.
     * 
     * @param instance the instance to call the callbacks on
     * @param added the method to call when a service was added
     * @param changed the method to call when a service was changed
     * @param removed the method to call when a service was removed
     * @return this service dependency
     */
    public synchronized ServiceDependency setCallbacks(Object instance, String added, String changed, String removed) {
    	return setCallbacks(instance, added, changed, removed, null);
    }
    
    /**
     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
     * dependency is added, changed or removed. When you specify callbacks, the auto 
     * configuration feature is automatically turned off, because we're assuming you don't 
     * need it in this case.
     * @param instance the instance to call the callbacks on
     * @param added the method to call when a service was added
     * @param changed the method to call when a service was changed
     * @param removed the method to call when a service was removed
     * @param swapped the method to call when the service was swapped due to addition or 
     * removal of an aspect
     * @return this service dependency
     */    
    public synchronized ServiceDependency setCallbacks(Object instance, String added, String changed, String removed, String swapped) {
        ensureNotActive();
        // if at least one valid callback is specified, we turn off auto configuration, unless
        // someone already explicitly invoked autoConfig
        if ((added != null || removed != null || changed != null || swapped != null) && ! m_autoConfigInvoked) {
            setAutoConfig(false);
        }
    	m_callbackInstance = instance;
        m_callbackAdded = added;
        m_callbackChanged = changed;
        m_callbackRemoved = removed;    
        m_callbackSwapped = swapped;
    	return this;
    }
    
    private void ensureNotActive() {
        if (m_tracker != null) {
            throw new IllegalStateException("Cannot modify state while active.");
        }
    }
    
    public synchronized String toString() {
        return "ServiceDependency[" + m_trackedServiceName + " " + m_trackedServiceFilterUnmodified + "]";
    }

    public String getAutoConfigName() {
        return m_autoConfigInstance;
    }
    
    public Object getAutoConfigInstance() {
        return lookupService();
    }
    
    public Class getAutoConfigType() {
        return getInterface();
    }

    public String getName() {
        StringBuilder sb = new StringBuilder();
        if (m_trackedServiceName != null) {
            sb.append(m_trackedServiceName.getName());
            if (m_trackedServiceFilterUnmodified != null) {
                sb.append(' ');
                sb.append(m_trackedServiceFilterUnmodified);
            }
        }
        if (m_trackedServiceReference != null) {
            sb.append("{service.id=" + m_trackedServiceReference.getProperty(Constants.SERVICE_ID)+"}");
        }
        return sb.toString();
    }

    public String getType() {
        return "service";
    }

    public void invokeAdded(DependencyService service) {
        ServiceReference[] refs = m_tracker.getServiceReferences();
        if (refs != null) {
            for (int i = 0; i < refs.length; i++) {
                ServiceReference sr = refs[i];
                Object svc = m_context.getService(sr);
                invokeAdded(service, sr, svc);
            }
        }
    }
    
    public void invokeRemoved(DependencyService service) {
        Set references = null;
        synchronized (m_sr) {
            references = (Set) m_sr.get(service);
        }
        Tuple[] refs = (Tuple[]) (references != null ? references.toArray(new Tuple[references.size()]) : new Tuple[0]);
    
        for (int i = 0; i < refs.length; i++) {
            ServiceReference sr = refs[i].getServiceReference();
            Object svc = refs[i].getService();
            invokeRemoved(service, sr, svc);
        }
        if (references != null) {
            references.clear();
        }
    }

    public Dictionary getProperties() {
        ServiceReference reference = lookupServiceReference();
        Object service = lookupService();
        if (reference != null) {
            if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
                try {
                    return (Dictionary) InvocationUtil.invokeCallbackMethod(m_propagateCallbackInstance, m_propagateCallbackMethod, new Class[][] {{ ServiceReference.class, Object.class }, { ServiceReference.class }}, new Object[][] {{ reference, service }, { reference }});
                }
                catch (InvocationTargetException e) {
                    m_logger.log(LogService.LOG_WARNING, "Exception while invoking callback method", e.getCause());
                }
                catch (Exception e) {
                    m_logger.log(LogService.LOG_WARNING, "Exception while trying to invoke callback method", e);
                }
                throw new IllegalStateException("Could not invoke callback");
            }
            else {
                Properties props = new Properties();
                String[] keys = reference.getPropertyKeys();
                for (int i = 0; i < keys.length; i++) {
                    if (!(keys[i].equals(Constants.SERVICE_ID) || keys[i].equals(Constants.SERVICE_PID))) {
                        props.put(keys[i], reference.getProperty(keys[i]));
                    }
                }
                return props;
            }
        }
        else {
            throw new IllegalStateException("cannot find service reference");
        }
    }

    public boolean isPropagated() {
        return m_propagate;
    }
    
    public ServiceDependency setPropagate(boolean propagate) {
        ensureNotActive();
        m_propagate = propagate;
        return this;
    }
    
    public ServiceDependency setPropagate(Object instance, String method) {
        setPropagate(instance != null && method != null);
        m_propagateCallbackInstance = instance;
        m_propagateCallbackMethod = method;
        return this;
    }
   
}
