/*******************************************************************************
 * Copyright (c) 2005 IBM Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.ds.resolver;

import java.io.IOException;
import java.util.*;
import org.eclipse.equinox.ds.Activator;
import org.eclipse.equinox.ds.Log;
import org.eclipse.equinox.ds.instance.InstanceProcess;
import org.eclipse.equinox.ds.model.*;
import org.eclipse.equinox.ds.workqueue.WorkDispatcher;
import org.eclipse.equinox.ds.workqueue.WorkQueue;
import org.osgi.framework.*;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.ComponentConstants;
import org.osgi.service.component.ComponentException;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;

/**
 * Resolver - resolves the Service Components.  This includes creating Component 
 * Configurations, resolving the required referenced services, and checking for 
 * circular dependencies.
 * 
 * The Resolver implements AllServiceListener so it can be informed about service
 * changes in the framework.
 * 
 * @version $Revision: 1.1 $
 */
public class Resolver implements AllServiceListener, WorkDispatcher {

	/* set this to true to compile in debug messages */
	private static final boolean DEBUG = false;

	/** 
	 * next free component id.
	 * See OSGi R4 Specification section 112.6 "Component Properties"
	 */
	private static long componentid;

	/* ServiceTracker for configurationAdmin */
	public ServiceTracker configAdminTracker;

	/**
	 * Service Component instances need to be built.
	 */
	private static final int BUILD = 1;

	/**
	 * Service Component instances to bind dynamically
	 */
	public static final int DYNAMICBIND = 3;

	/**
	 * Main class for the SCR
	 */
	private Activator main;

	public InstanceProcess instanceProcess;

	/**
	 * List of {@link ComponentDescriptionProp}s - the currently "enabled" 
	 * Component Configurations.
	 */
	public List enabledCDPs;

	/**
	 * List of {@link ComponentDescriptionProp}s - the currently "satisfied" 
	 * Component Configurations.  Note that to be satisfied a Component 
	 * Configuration must first be enabled, so this list is a subset of 
	 * {@link Resolver#enabledCDPs enabledCDPs}.
	 */
	public List satisfiedCDPs;

	/**
	 * A map of name:Service Component (String):({@link ComponentDescription})
	 */
	public Map enabledCDsByName;

	private WorkQueue workQueue;

	/**
	 * Resolver constructor
	 * 
	 * @param main Main class of SCR
	 */
	public Resolver(Activator main) {
		this.main = main;

		componentid = 1;

		// for now use Main's workqueue
		workQueue = main.workQueue;

		enabledCDPs = new ArrayList();
		satisfiedCDPs = new ArrayList();
		enabledCDsByName = new HashMap();

		configAdminTracker = new ServiceTracker(main.context, ConfigurationAdmin.class.getName(), null);
		configAdminTracker.open();

		instanceProcess = new InstanceProcess(main);

		//start listening to ServiceChanged events
		main.context.addServiceListener(this);

	}

	/**
	 * Clean up the SCR is shutting down
	 */
	public void dispose() {

		//stop listening to ServiceChanged events
		main.context.removeServiceListener(this);

		instanceProcess.dispose();
		instanceProcess = null;

		configAdminTracker.close();
		configAdminTracker = null;

		enabledCDPs = null;
		satisfiedCDPs = null;
		enabledCDsByName = null;

	}

	/**
	 * Enable Service Components - create Component Configuration(s) for the 
	 * Service Components and try to satisfy their dependencies.
	 * 
	 * <p>
	 * For each Service Component ({@link ComponentDescription}) check 
	 * ConfigurationAdmin for properties and create a Component Configuration 
	 * ({@link ComponentDescriptionProp}).
	 * </p>
	 * 
	 * <p>
	 * If a {@link org.osgi.service.cm.ManagedServiceFactory ManagedServiceFactory}
	 * is registered for the Service Component, we may create multiple Component
	 * Configurations.
	 * </p>
	 * 
	 * <p>
	 * After the Component Configuration(s) are created, call 
	 * {@link Resolver#resolve(ServiceEvent) getEligible(null)} to try to
	 * satisfy them.
	 * </p>
	 * 
	 * @param componentDescriptions - a List of {@link ComponentDescription}s to 
	 *        be enabled 
	 */
	public void enableComponents(List componentDescriptions) throws ComponentException {

		Iterator it = componentDescriptions.iterator();
		while (it.hasNext()) {
			ComponentDescription cd = (ComponentDescription) it.next();

			// add to our enabled lookup list
			enabledCDsByName.put(cd.getName(), cd);

			// check for a Configuration properties for this component
			Configuration config = null;
			try {
				ConfigurationAdmin configurationAdmin = (ConfigurationAdmin) configAdminTracker.getService();
				if (configurationAdmin != null) {
					config = configurationAdmin.getConfiguration(cd.getName(), cd.getBundleContext().getBundle().getLocation());
				}
			} catch (IOException e) {
				// Log it and continue
				Log.log(1, "[SCR] IOException when getting Configuration Properties. ", e);
			}

			// if no Configuration
			if (config == null) {
				// create ComponentDescriptionProp
				map(cd, null);

			} else {

				// if ManagedServiceFactory
				if (config.getFactoryPid() != null) {

					// if ComponentFactory is specified
					if (cd.getFactory() != null) {
						throw new ComponentException("incompatible to specify both ComponentFactory and ManagedServiceFactory are incompatible");
					}

					Configuration[] configs = null;
					try {
						ConfigurationAdmin cm = (ConfigurationAdmin) configAdminTracker.getService();
						configs = cm.listConfigurations("(service.factoryPid=" + config.getFactoryPid() + ")");
					} catch (InvalidSyntaxException e) {
						Log.log(1, "[SCR] InvalidSyntaxException when getting CM Configurations. ", e);
					} catch (IOException e) {
						Log.log(1, "[SCR] IOException when getting CM Configurations. ", e);
					}

					// for each MSF set of properties(P), map(CD,P)
					if (configs != null) {
						for (int i = 0; i < configs.length; i++) {
							map(cd, configs[i].getProperties());
						}
					}
				} else {
					// if Service
					map(cd, config.getProperties());
				}
			}
		}
		// resolve
		resolve(null);
	}

	/**
	 * Combine ConfigAdmin properties with a Service Component 
	 * ({@link ComponentDescription}) to create a Component Configuration 
	 * ({@link ComponentConfiguration}), and add it to our list of enabled 
	 * Component Configurations ({@link Resolver#enabledCDPs}).
	 * 
	 * The ConfigAdmin properties are combined with the properties from the 
	 * Service Component's XML.
	 * 
	 * @param cd Service Component
	 * @param configAdminProps ConfigAdmin properties for this Component
	 *        Configuration 
	 */
	public ComponentDescriptionProp map(ComponentDescription cd, Dictionary configAdminProps) {
		return doMap(cd, configAdminProps, cd.getFactory() != null);
	}

	/**
	 * Create a Component Configuration of a Service Component that has the
	 * "factory" attribute.  
	 * 
	 * @see Resolver#map(ComponentDescription, Dictionary)
	 * @see ComponentDescriptionProp#componentFactory
	 */
	public ComponentDescriptionProp mapFactoryInstance(ComponentDescription cd, Dictionary configAdminProps) {
		return doMap(cd, configAdminProps, false);
	}

	private ComponentDescriptionProp doMap(ComponentDescription cd, Dictionary configAdminProps, boolean componentFactory) {

		// Create CD+P

		// calculate the CDP's properties
		Hashtable properties = initProperties(cd, configAdminProps);

		// for each Reference Description, create a reference object
		List references = new ArrayList();
		Iterator it = cd.getReferenceDescriptions().iterator();
		while (it.hasNext()) {
			ReferenceDescription referenceDesc = (ReferenceDescription) it.next();

			// create new Reference Object
			Reference ref = new Reference(referenceDesc, properties);
			references.add(ref);

		}
		references = !references.isEmpty() ? references : Collections.EMPTY_LIST;

		ComponentDescriptionProp cdp = new ComponentDescriptionProp(cd, references, properties, componentFactory);

		//for each Reference, set it's "parent" (the CDP)
		it = cdp.getReferences().iterator();
		while (it.hasNext()) {
			Reference reference = (Reference) it.next();

			// set parent CDP
			reference.setComponentDescriptionProp(cdp);
		}

		cd.addComponentDescriptionProp(cdp);

		// add CD+P to set
		enabledCDPs.add(cdp);

		return cdp;
	}

	/**
	 * Initialize Properties for a CD+P
	 * 
	 * The property elements provide default or supplemental property values if
	 * not overridden by the properties retrieved from Configuration Admin.
	 * 
	 * The property and properties elements are processed in top to bottom
	 * order. This allows later elements to override property values defined by
	 * earlier elements. There can be many property and properties elements and
	 * they may be interleaved.
	 * 
	 * @return Dictionary properties
	 */
	private Hashtable initProperties(ComponentDescription cd, Dictionary configAdminProps) {

		Hashtable properties = new Hashtable();

		// 0) add Reference target properties
		Iterator it = cd.getReferenceDescriptions().iterator();
		while (it.hasNext()) {
			ReferenceDescription referenceDesc = (ReferenceDescription) it.next();
			if (referenceDesc.getTarget() != null) {
				properties.put(referenceDesc.getName() + ".target", referenceDesc.getTarget());
			}
		}

		// 1) get properties from Service Component XML, in parse order
		properties.putAll(cd.getProperties());

		// 2) Add configAdmin properties
		if (configAdminProps != null) {
			Enumeration keys = configAdminProps.keys();
			while (keys.hasMoreElements()) {
				Object key = keys.nextElement();
				properties.put(key, configAdminProps.get(key));
			}
		}

		// add component.name and component.id (cannot be overridden)
		properties.put(ComponentConstants.COMPONENT_NAME, cd.getName());
		properties.put(ComponentConstants.COMPONENT_ID, new Long(getNextComponentId()));

		// add component.factory if it's a factory
		if (cd.getFactory() != null) {
			properties.put(ComponentConstants.COMPONENT_FACTORY, cd.getFactory());
		}

		// add ObjectClass so we can match target filters before actually being
		// registered
		List servicesProvided = cd.getServicesProvided();
		if (!servicesProvided.isEmpty()) {
			properties.put(Constants.OBJECTCLASS, servicesProvided.toArray(new String[servicesProvided.size()]));
		}

		return properties;
	}

	/**
	 * Disable Service Components.
	 * 
	 * For each Service Component ({@link ComponentDescription}),
	 * dispose of all of it's Component Configurations 
	 * ({@link ComponentDescriptionProp}s).
	 * 
	 * @see Resolver#disposeComponentConfigs(List)
	 * 
	 * @param componentDescriptions List of {@link ComponentDescriptionProp}s to
	 *        disable
	 */
	public void disableComponents(List componentDescriptions) {

		// Received list of CDs to disable
		Iterator it = componentDescriptions.iterator();
		while (it.hasNext()) {

			// get the CD
			ComponentDescription cd = (ComponentDescription) it.next();

			disposeComponentConfigs((List) ((ArrayList) cd.getComponentDescriptionProps()).clone());

			cd.clearComponentDescriptionProps();

			enabledCDsByName.remove(cd.getName());
		}

	}

	/**
	 * Dispose of Component Configurations ({@link ComponentDescriptionProp}s).
	 * 
	 * Remove Component Configurations from satisfied and enabled lists, and send
	 * to InstanceProcess to be unregistered, deactivated, and unbound.
	 * 
	 * @see InstanceProcess#disposeComponentConfigs(List)
	 * 
	 * @param cdps List of {@link ComponentDescriptionProp}s
	 */
	public void disposeComponentConfigs(List cdps) {
		// unregister, deactivate, and unbind
		satisfiedCDPs.removeAll(cdps);
		enabledCDPs.removeAll(cdps);
		instanceProcess.disposeComponentConfigs(cdps);
	}

	/**
	 * Process a service change
	 * <p>
	 * A change has happened in the OSGi service environment, or new
	 * Component Configurations have been added to the system.
	 * </p>
	 * Depending on the change, take the following actions:
	 * <p>
	 * If new Component Configurations were added (param event is null):
	 *  <ol>
	 *     <li>Check for circularity and mark cycles</li>
	 *     <li>Send newly satisfied Component Configurations to Instance 
	 *     process</li>
	 *  </ol>
	 *  </p>
	 *  <p>
	 * If a service was registered:
	 * <ol>
	 *    <li>Put "Dynamic Bind" events on the queue for any Component 
	 *    Configurations which should be bound to the new service</li>
	 *    <li>Send newly satisfied Component Configurations to Instance 
	 *    process</li>
	 * </ol>
	 * </p>
	 * <p>
	 * If a service was modified:
	 * <ol>
	 *    <li>Synchronously dispose of all Component Configurations that 
	 *    become unsatisfied</li>
	 *    <li>Put "Dynamic Unbind Bind" events on the queue for any remaining 
	 *    Component Configurations which should be unbound from the service</li>
	 *    <li>Put "Dynamic Bind" events on the queue for any Component 
	 *    Configurations which should be bound to the modified service</li>
	 *    <li>Send newly satisfied Component Configurations to Instance 
	 *    process</li>
	 * </ol>
	 * </p>
	 * <p>
	 * If a service was unregistered:
	 * <ol>
	 *    <li>Synchronously dispose of all Component Configurations that 
	 *    become unsatisfied</li>
	 *    <li>Put "Dynamic Unbind Bind" events on the queue for any remaining 
	 *    Component Configurations which should be unbound from the service</li>
	 * </ol>
	 * </p>
	 * 
	 * @param event the service event or null if new cdps were added to the enabled list
	 */
	private void resolve(ServiceEvent event) {

		// if added CDPs
		if (event == null) {
			// we added a CDP, so check for circularity and mark
			// cycles
			resolveCycles();

			// get list of newly satisfied CDPs and build them
			List newlySatisfiedCDPs = resolveSatisfied();
			newlySatisfiedCDPs.removeAll(satisfiedCDPs);

			if (!newlySatisfiedCDPs.isEmpty()) {
				satisfiedCDPs.addAll(newlySatisfiedCDPs); // add to satisfiedCDPs before dispatch
				workQueue.enqueueWork(this, BUILD, newlySatisfiedCDPs);
			}

		}
		// if service registered
		else if (event.getType() == ServiceEvent.REGISTERED) {

			// dynamic bind
			List dynamicBind = selectDynamicBind(event.getServiceReference());
			if (!dynamicBind.isEmpty()) {
				workQueue.enqueueWork(this, DYNAMICBIND, dynamicBind);
			}

			// get list of newly satisfied CDPs and build them
			List newlySatisfiedCDPs = resolveSatisfied();
			newlySatisfiedCDPs.removeAll(satisfiedCDPs);
			if (!newlySatisfiedCDPs.isEmpty()) {
				satisfiedCDPs.addAll(newlySatisfiedCDPs); // add to satisfiedCDPs before dispatch
				workQueue.enqueueWork(this, BUILD, newlySatisfiedCDPs);
			}

		}
		// if service modified
		else if (event.getType() == ServiceEvent.MODIFIED) {

			// check for newly unsatisfied components and synchronously
			// dispose them
			List newlyUnsatisfiedCDPs = (List) ((ArrayList) satisfiedCDPs).clone();
			newlyUnsatisfiedCDPs.removeAll(resolveSatisfied());
			if (!newlyUnsatisfiedCDPs.isEmpty()) {
				satisfiedCDPs.removeAll(newlyUnsatisfiedCDPs);

				instanceProcess.disposeComponentConfigs(newlyUnsatisfiedCDPs);
			}

			// dynamic unbind
			// check each satisfied cdp - do we need to unbind
			Map dynamicUnBind = selectDynamicUnBind(event.getServiceReference());
			if (!dynamicUnBind.isEmpty()) {
				instanceProcess.dynamicUnBind(dynamicUnBind);
			}

			// dynamic bind
			List dynamicBind = selectDynamicBind(event.getServiceReference());
			if (!dynamicBind.isEmpty()) {
				workQueue.enqueueWork(this, DYNAMICBIND, dynamicBind);
			}

			// get list of newly satisfied CDPs and build them
			List newlySatisfiedCDPs = resolveSatisfied();
			newlySatisfiedCDPs.removeAll(satisfiedCDPs);
			if (!newlySatisfiedCDPs.isEmpty()) {
				satisfiedCDPs.addAll(newlySatisfiedCDPs); // add to satisfiedCDPs before dispatch
				workQueue.enqueueWork(this, BUILD, newlySatisfiedCDPs);
			}

		}
		// if service unregistering
		else if (event.getType() == ServiceEvent.UNREGISTERING) {

			// check for newly unsatisfied components and
			// synchronously dispose them
			List newlyUnsatisfiedCDPs = (List) ((ArrayList) satisfiedCDPs).clone();
			newlyUnsatisfiedCDPs.removeAll(resolveSatisfied());
			if (!newlyUnsatisfiedCDPs.isEmpty()) {
				satisfiedCDPs.removeAll(newlyUnsatisfiedCDPs);

				instanceProcess.disposeComponentConfigs(newlyUnsatisfiedCDPs);
			}

			// dynamic unbind
			Map dynamicUnBind = selectDynamicUnBind(event.getServiceReference());
			if (!dynamicUnBind.isEmpty()) {
				instanceProcess.dynamicUnBind(dynamicUnBind);
			}

		}

	}

	/**
	 * Check if a particular CDP is satisfied. Also checks for circularity. If
	 * cdp is satisfied it is added to satisfiedCDPs list, but not sent to
	 * instance process
	 * 
	 * @param cdp
	 * @return
	 */
	public boolean justResolve(ComponentDescriptionProp cdp) {

		// we added a CDP, so check for circularity and mark
		// cycles
		resolveCycles();

		// get list of newly satisfied CDPs and build them
		List newlySatisfiedCDPs = resolveSatisfied();
		newlySatisfiedCDPs.removeAll(satisfiedCDPs);

		if (!newlySatisfiedCDPs.contains(cdp)) {
			return false;
		}
		satisfiedCDPs.add(cdp);
		return true;

	}

	/**
	 * Calculate which of the currently enabled Component Configurations 
	 * ({@link Resolver#enabledCDPs}) are "satisfied".  
	 * 
	 * <p>
	 * An "enabled" Component 
	 * Configuration is "satisfied" if there is at least one OSGi Service
	 * registered that has the correct interface and matches the target filter 
	 * for each of it's required (cardinality = "1..1" or "1..n") references.
	 * </p>
	 * <p>
	 * If a Component Configuration will register a service and security is 
	 * enabled, check if the bundle it comes from has 
	 * {@link ServicePermission#REGISTER} for that service.  If the Component
	 * Configuration does not have the necessary permission it is not "satisfied".
	 * </p>
	 * @return List of {@link ComponentDescriptionProp}s that are "satisfied"
	 */
	private List resolveSatisfied() {
		List resolvedSatisfiedCDPs = new ArrayList();

		Iterator it = enabledCDPs.iterator();
		while (it.hasNext()) {
			ComponentDescriptionProp cdp = (ComponentDescriptionProp) it.next();
			ComponentDescription cd = cdp.getComponentDescription();

			// check if all the services needed by the CDP are available
			List refs = cdp.getReferences();
			Iterator iterator = refs.iterator();
			boolean hasProviders = true;
			while (iterator.hasNext()) {
				Reference reference = (Reference) iterator.next();
				if (reference != null) {
					if (reference.getReferenceDescription().isRequired() && !reference.hasProvider(cdp.getComponentDescription().getBundleContext())) {
						hasProviders = false;
						break;
					}
				}
			}
			if (!hasProviders)
				continue;

			// check if the bundle providing the service has permission to
			// register the provided interface(s)
			// if a service is provided
			// TODO we can cache the ServicePermission objects
			if (cd.getService() != null && System.getSecurityManager() != null) {
				ProvideDescription[] provides = cd.getService().getProvides();
				Bundle bundle = cd.getBundleContext().getBundle();
				boolean hasPermission = true;
				for (int i = 0; i < provides.length; i++) {
					// make sure bundle has permission to register the service
					if (!bundle.hasPermission(new ServicePermission(provides[i].getInterfacename(), ServicePermission.REGISTER))) {
						hasPermission = false;
						break;
					}
				}
				if (!hasPermission)
					continue;
			}

			// we have providers and permission - this CDP is satisfied
			resolvedSatisfiedCDPs.add(cdp);
		} // end while (more enabled CDPs)
		return resolvedSatisfiedCDPs.isEmpty() ? Collections.EMPTY_LIST : resolvedSatisfiedCDPs;
	}

	/**
	 * Listen for service change events
	 * 
	 * @param event
	 */
	public void serviceChanged(ServiceEvent event) {

		ServiceReference reference = event.getServiceReference();
		int eventType = event.getType();

		if (DEBUG) {
			System.out.println("ServiceChanged: serviceReference = " + reference);
			System.out.println("ServiceChanged: Event type = " + eventType + " , reference.getBundle() = " + reference.getBundle());
		}

		// if ((reference.getProperty(ComponentConstants.COMPONENT_ID) == null)

		switch (eventType) {
			case ServiceEvent.MODIFIED :
			case ServiceEvent.REGISTERED :
			case ServiceEvent.UNREGISTERING :

				resolve(event);
				break;
		}

	}

	/**
	 * Called asynchronously by the work queue thread to perform work.
	 * <p>
	 * There are two possible work actions:
	 * <ul>
	 *    <li>BUILD - workObject is a list of Component Configurations to be
	 *    sent to the Instance process.  The Component Configurations have become
	 *    satisfied.  Check that the Component Configurations are still satisfied 
	 *    (system state may have changed while they were waiting on the work 
	 *    queue) and send them to the instance process 
	 *    ({@link InstanceProcess#registerComponentConfigs(List)}).
	 *    </li>
	 *    <li>DYNAMICBIND - workObject is a List of References that need to be 
	 *    dynamically bound.  Check that the Component Configurations are still 
	 *    satisfied (system state may have changed while they were waiting on 
	 *    the work queue) and send them to the instance process 
	 *    ({@link InstanceProcess#dynamicBind(List)}).
	 * </ul>
	 * </p>
	 * @param workAction {@link Resolver#BUILD} or {@link Resolver#DYNAMICBIND}
	 * @param workObject a List of {@link ComponentDescriptionProp}s if workAction
	 *        is {@link Resolver#BUILD} or a List of {@link Reference}s if workAction 
	 *        is {@link Resolver#DYNAMICBIND} 
	 * @see org.eclipse.equinox.ds.workqueue.WorkDispatcher#dispatchWork(int,
	 *      java.lang.Object)
	 */
	public void dispatchWork(int workAction, Object workObject) {
		Iterator it;
		switch (workAction) {
			case BUILD :
				// only build if cdps are still satisfied
				List queueCDPs = (List) workObject;
				List cdps = new ArrayList(queueCDPs.size());
				it = queueCDPs.iterator();
				while (it.hasNext()) {
					ComponentDescriptionProp cdp = (ComponentDescriptionProp) it.next();
					if (this.satisfiedCDPs.contains(cdp)) {
						cdps.add(cdp);
					}
				}
				if (!cdps.isEmpty()) {
					instanceProcess.registerComponentConfigs(cdps);
				}
				break;
			case DYNAMICBIND :
				// only dynamicBind if cdps are still satisfied
				List references = (List) workObject;
				it = references.iterator();
				while (it.hasNext()) {
					if (!this.satisfiedCDPs.contains(((Reference) it.next()).getComponentDescriptionProp())) {
						// modifies underlying list
						it.remove();
					}
				}
				if (!references.isEmpty()) {
					instanceProcess.dynamicBind(references);
				}
				break;
		}
	}

	/**
	 * Calculate which of the currently satisfied CDPs 
	 * ({@link Resolver#satisfiedCDPs}) need to be dynamically bound to an OSGi
	 * service.
	 * 
	 * @param serviceReference the service
	 * @return a List of {@link Reference}s that need to be dynamically bound 
	 *         to this service
	 */
	private List selectDynamicBind(ServiceReference serviceReference) {
		List bindList = new ArrayList();
		Iterator it = satisfiedCDPs.iterator();
		while (it.hasNext()) {
			ComponentDescriptionProp cdp = (ComponentDescriptionProp) it.next();
			List references = cdp.getReferences();
			Iterator refIt = references.iterator();
			while (refIt.hasNext()) {
				Reference reference = (Reference) refIt.next();
				if (reference.dynamicBindReference(serviceReference)) {
					bindList.add(reference);
				}
			}
		}
		return bindList;
	}

	/**
	 * An OSGi service is unregistering, calculate which of the satisfied 
	 * Component Configurations need to dynamically unbind from it.
	 * <p>
	 *  A Component Configuration needs to dynamically unbind from a service
	 *  if it was bound to the service and the reference it was policy="dynamic".
	 *  </p>
	 * @param serviceReference
	 * @return a Map of {@link Reference}:{@link ServiceReference} to unbind
	 */
	private Map selectDynamicUnBind(ServiceReference serviceReference) {

		Map unbindJobs = new Hashtable();

		Iterator it = satisfiedCDPs.iterator();
		while (it.hasNext()) {
			ComponentDescriptionProp cdp = (ComponentDescriptionProp) it.next();
			List references = cdp.getReferences();
			Iterator it_ = references.iterator();
			while (it_.hasNext()) {
				Reference reference = (Reference) it_.next();
				// Is reference dynamic and bound to this service? - must unbind
				if (reference.dynamicUnbindReference(serviceReference)) {
					unbindJobs.put(reference, serviceReference);
				}
			}
		}
		return unbindJobs.isEmpty() ? Collections.EMPTY_MAP : unbindJobs;
	}

	/**
	 * Doubly-linked node used to traverse the dependency tree in order to
	 * find cycles.
	 *  
	 * @version $Revision: 1.1 $
	 */
	static private class ReferenceCDP {
		public Reference ref;
		public ComponentDescriptionProp producer;

		protected ReferenceCDP(Reference ref, ComponentDescriptionProp producer) {
			this.ref = ref;
			this.producer = producer;
		}
	}

	/**
	 * Check through the enabled list for cycles. Cycles can only exist if every
	 * service is provided by a Service Component (not legacy OSGi). If the cycle 
	 * has no optional dependencies, log an error and disable a Component 
	 * Configuration in the cycle. If cycle can be "broken" by an optional 
	 * dependency, make a note (stored in the 
	 * {@link ComponentDescriptionProp#delayActivateCDPNames} List).
	 * 
	 * @throws CircularityException if cycle exists with no optional
	 *         dependencies
	 */
	private void resolveCycles() {

		try {
			// find the CDPs that resolve using other CDPs and record their
			// dependencies
			Hashtable dependencies = new Hashtable();
			Iterator it = enabledCDPs.iterator();
			while (it.hasNext()) {
				ComponentDescriptionProp enabledCDP = (ComponentDescriptionProp) it.next();
				List dependencyList = new ArrayList();
				Iterator refIt = enabledCDP.getReferences().iterator();
				while (refIt.hasNext()) {
					Reference reference = (Reference) refIt.next();

					// see if it resolves to one of the other enabled CDPs
					ComponentDescriptionProp providerCDP = reference.findProviderCDP(enabledCDPs);
					if (providerCDP != null) {
						dependencyList.add(new ReferenceCDP(reference, providerCDP));
					}
				} // end while(more references)

				if (!dependencyList.isEmpty()) {
					// CDP resolves using some other CDPs, could be a cycle
					dependencies.put(enabledCDP, dependencyList);
				} else {
					dependencies.put(enabledCDP, Collections.EMPTY_LIST);
				}
			} // end while (more enabled CDPs)

			//traverse dependency tree and look for cycles
			Set visited = new HashSet();
			it = dependencies.keySet().iterator();
			while (it.hasNext()) {
				ComponentDescriptionProp cdp = (ComponentDescriptionProp) it.next();
				if (!visited.contains(cdp)) {
					List currentStack = new ArrayList();
					traverseDependencies(cdp, visited, dependencies, currentStack);
				}
			}
		} catch (CircularityException e) {
			// log the error
			Log.log(LogService.LOG_ERROR, "[SCR] Circularity Exception.", e);

			// disable offending CDP
			enabledCDPs.remove(e.getCircularDependency());

			// try again
			resolveCycles();
		}
	}

	/**
	 * Recursively do a depth-first traversal of a dependency tree, looking for 
	 * cycles.
	 * <p>
	 * If a cycle is found, calls 
	 * {@link Resolver#handleDependencyCycle(ReferenceCDP, List)}.
	 * </p>
	 * 
	 * @param cdp current node in dependency tree
	 * @param visited Set of {@link ComponentDescriptionProp} that are visited 
	 *        nodes
	 * @param dependencies Dependency tree - a Hashtable of 
	 * ({@link ComponentDescriptionProp}):(List of {@link ReferenceCDP}s)
	 * @param currentStack List of {@link ReferenceCDP}s - the history of our
	 *        traversal so far (the path back to the root of the tree)
	 * @throws CircularityException if an cycle with no optional dependencies is
	 * found.
	 */
	private void traverseDependencies(ComponentDescriptionProp cdp, Set visited, Hashtable dependencies, List currentStack) throws CircularityException {

		// the component has already been visited and it's dependencies checked
		// for cycles
		if (visited.contains(cdp)) {
			return;
		}

		List refCDPs = (List) dependencies.get(cdp);
		Iterator it = refCDPs.iterator();
		// first, add the CDP's dependencies
		while (it.hasNext()) {

			ReferenceCDP refCDP = (ReferenceCDP) it.next();

			if (currentStack.contains(refCDP)) {
				// may throw circularity exception
				handleDependencyCycle(refCDP, currentStack);
				return;
			}
			currentStack.add(refCDP);

			traverseDependencies(refCDP.producer, visited, dependencies, currentStack);

			currentStack.remove(refCDP);
		}
		// finally write the cdp
		visited.add(cdp);

	}

	/**
	 * A cycle was detected. CDP is referenced by the last element in
	 * currentStack. Throws CircularityException if the cycle does not contain
	 * an optional dependency, else choses a point at which to
	 * "break" the cycle (the break point must be immediately after an
	 * optional dependency) and adds a "cycle note".
	 * 
	 * @see ComponentDescriptionProp#delayActivateCDPNames
	 */
	private void handleDependencyCycle(ReferenceCDP refCDP, List currentStack) throws CircularityException {
		ListIterator cycleIterator = currentStack.listIterator(currentStack.indexOf(refCDP));

		// find an optional dependency
		ReferenceCDP optionalRefCDP = null;
		while (cycleIterator.hasNext()) {
			ReferenceCDP cycleRefCDP = (ReferenceCDP) cycleIterator.next();
			if (!cycleRefCDP.ref.getReferenceDescription().isRequired()) {
				optionalRefCDP = cycleRefCDP;
				break;
			}
		}

		if (optionalRefCDP == null) {
			// no optional dependency
			throw new CircularityException(refCDP.ref.getComponentDescriptionProp());
		}

		// add note not to initiate activation of next dependency
		optionalRefCDP.ref.getComponentDescriptionProp().setDelayActivateCDPName(optionalRefCDP.producer.getComponentDescription().getName());
	}

	/**
	 * Method to return the next available component id.
	 * 
	 * @return next component id.
	 */
	private long getNextComponentId() {
		synchronized (this) {
			return componentid++;
		}
	}

}
