/*******************************************************************************
 * Copyright (c) 2010 Composent, Inc. and others. 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:
 *   Composent, Inc. - initial API and implementation
 ******************************************************************************/
package org.eclipse.ecf.internal.osgi.services.distribution;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.ecf.core.ContainerConnectException;
import org.eclipse.ecf.core.ContainerTypeDescription;
import org.eclipse.ecf.core.IContainer;
import org.eclipse.ecf.core.IContainerManager;
import org.eclipse.ecf.core.identity.ID;
import org.eclipse.ecf.osgi.services.discovery.DiscoveredServiceNotification;
import org.eclipse.ecf.osgi.services.discovery.DiscoveredServiceTracker;
import org.eclipse.ecf.osgi.services.discovery.IRemoteServiceEndpointDescription;
import org.eclipse.ecf.osgi.services.discovery.RemoteServiceEndpointDescription;
import org.eclipse.ecf.osgi.services.discovery.RemoteServicePublication;
import org.eclipse.ecf.osgi.services.discovery.ServiceEndpointDescription;
import org.eclipse.ecf.osgi.services.discovery.ServicePublication;
import org.eclipse.ecf.osgi.services.distribution.IDistributionConstants;
import org.eclipse.ecf.osgi.services.distribution.IProxyContainerFinder;
import org.eclipse.ecf.osgi.services.distribution.IProxyDistributionListener;
import org.eclipse.ecf.remoteservice.Constants;
import org.eclipse.ecf.remoteservice.IRemoteService;
import org.eclipse.ecf.remoteservice.IRemoteServiceContainer;
import org.eclipse.ecf.remoteservice.IRemoteServiceListener;
import org.eclipse.ecf.remoteservice.IRemoteServiceReference;
import org.eclipse.ecf.remoteservice.events.IRemoteServiceEvent;
import org.eclipse.ecf.remoteservice.events.IRemoteServiceUnregisteredEvent;
import org.eclipse.osgi.framework.eventmgr.CopyOnWriteIdentityMap;
import org.eclipse.osgi.framework.eventmgr.EventDispatcher;
import org.eclipse.osgi.framework.eventmgr.EventManager;
import org.eclipse.osgi.framework.eventmgr.ListenerQueue;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceRegistration;

public class DiscoveredServiceTrackerImpl implements DiscoveredServiceTracker {

	private DistributionProviderImpl distributionProvider;
	private List serviceLocations = new ArrayList();
	// <Map<containerID><RemoteServiceRegistration>
	private Map discoveredRemoteServiceRegistrations = new HashMap();
	private List ecfRemoteServiceProperties = Arrays.asList(new String[] {
			Constants.SERVICE_ID, Constants.OBJECTCLASS,
			org.eclipse.ecf.remoteservice.Constants.SERVICE_ID,
			org.eclipse.ecf.remoteservice.Constants.SERVICE_CONTAINER_ID,
			org.eclipse.ecf.remoteservice.Constants.SERVICE_RANKING,
			IDistributionConstants.SERVICE_EXPORTED_CONFIGS,
			RemoteServicePublication.ENDPOINT_ID,
			RemoteServicePublication.ENDPOINT_INTERFACE_NAME,
			RemoteServicePublication.ENDPOINT_LOCATION,
			RemoteServicePublication.SERVICE_INTERFACE_NAME,
			RemoteServicePublication.SERVICE_INTERFACE_VERSION,
			RemoteServicePublication.SERVICE_PROPERTIES, "service.uri" }); //$NON-NLS-1$
	// queue for incoming remote service available events
	private ListenerQueue queue;
	private EventManager eventManager;

	// This class is to hold the discovered endpoint available events
	class DiscoveredEndpointEvent {
		private RemoteServiceEndpointDescription rsEndpointDescription;

		public DiscoveredEndpointEvent(
				RemoteServiceEndpointDescription rsEndpointDescription) {
			this.rsEndpointDescription = rsEndpointDescription;
		}

		public RemoteServiceEndpointDescription getEndpointDescription() {
			return rsEndpointDescription;
		}
	}

	public DiscoveredServiceTrackerImpl(DistributionProviderImpl dp) {
		this.distributionProvider = dp;
		ThreadGroup eventGroup = new ThreadGroup("Remote Service Dispatcher"); //$NON-NLS-1$
		eventGroup.setDaemon(true);
		eventManager = new EventManager("Remote Service Dispatcher", eventGroup); //$NON-NLS-1$
		queue = new ListenerQueue(eventManager);
		CopyOnWriteIdentityMap listeners = new CopyOnWriteIdentityMap();
		listeners.put(this, this);
		queue.queueListeners(listeners.entrySet(), new EventDispatcher() {
			public void dispatchEvent(Object eventListener,
					Object listenerObject, int eventAction, Object eventObject) {
				RemoteServiceEndpointDescription rsEndpointDescription = ((DiscoveredEndpointEvent) eventObject)
						.getEndpointDescription();
				try {
					handleDiscoveredServiceAvailable(rsEndpointDescription);
				} catch (Exception e) {
					logError("handleDiscoveredServiceAvailble", //$NON-NLS-1$
							"Unexpected exception with rsEndpointDescription=" //$NON-NLS-1$
									+ rsEndpointDescription, e);
					throw new RuntimeException(
							"Unexpected exception with rsEndpointDescription=" //$NON-NLS-1$
									+ rsEndpointDescription, e);
				}
			}
		});
	}

	public void close() {
		if (eventManager != null) {
			eventManager.close();
			eventManager = null;
			queue = null;
		}
		serviceLocations.clear();
		discoveredRemoteServiceRegistrations.clear();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.osgi.service.discovery.DiscoveredServiceTracker#serviceChanged(org
	 * .osgi.service.discovery.DiscoveredServiceNotification)
	 */
	public void serviceChanged(final DiscoveredServiceNotification notification) {
		if (notification == null)
			return;
		int notificationType = notification.getType();
		switch (notificationType) {
		case DiscoveredServiceNotification.AVAILABLE:
			RemoteServiceEndpointDescription adesc = null;
			try {
				// If the service endpoint description is not ECF's then we
				// don't process it
				adesc = getECFDescription(notification
						.getServiceEndpointDescription());
			} catch (Exception e) {
				logError("serviceChanged.AVAILABLE", //$NON-NLS-1$
						"Error creating ECF endpoint description", e); //$NON-NLS-1$
				return;
			}
			// If it's not for us then return
			if (adesc == null)
				return;

			if (!isValidDescription(adesc)) {
				trace("serviceChanged.AVAILABLE", //$NON-NLS-1$
						"Duplicate or invalid description=" + adesc); //$NON-NLS-1$
				return;
			}
			final RemoteServiceEndpointDescription rsEndpointDescription = adesc;

			// put in queue and execute asynchronously
			queue.dispatchEventAsynchronous(0, new DiscoveredEndpointEvent(
					rsEndpointDescription));
			break;
		case DiscoveredServiceNotification.UNAVAILABLE:
			try {
				RemoteServiceEndpointDescription udesc = getECFDescription(notification
						.getServiceEndpointDescription());
				// If it's not for us then return
				if (udesc == null)
					return;

				// Remove existing proxy service registrations that correspond
				// to the
				// given serviceID
				synchronized (serviceLocations) {
					ServiceRegistration[] proxyServiceRegistrations = removeProxyServiceRegistrations(udesc);
					// Then unregister them
					if (proxyServiceRegistrations != null) {
						for (int i = 0; i < proxyServiceRegistrations.length; i++) {
							trace("handleDiscoveredServiceUnavailable", //$NON-NLS-1$
									"proxyServiceRegistrations=" //$NON-NLS-1$
											+ proxyServiceRegistrations[i]
											+ ",serviceEndpointDesc=" + udesc); //$NON-NLS-1$
							unregisterProxyServiceRegistration(udesc,
									proxyServiceRegistrations[i]);
						}
						removeDiscoveredServiceID(udesc);
					}
				}
			} catch (Exception e) {
				logError("serviceChanged", "UNAVAILABLE", e); //$NON-NLS-1$ //$NON-NLS-2$
			}
			break;
		case DiscoveredServiceNotification.MODIFIED:
			// Do nothing for now
			break;
		case DiscoveredServiceNotification.MODIFIED_ENDMATCH:
			// Do nothing for now
			break;
		default:
			logWarning("serviceChanged", "DiscoveredServiceNotification type=" //$NON-NLS-1$ //$NON-NLS-2$
					+ notificationType + " not found.  Ignoring"); //$NON-NLS-1$
			break;
		}
	}

	private void handleDiscoveredServiceAvailable(
			RemoteServiceEndpointDescription endpointDescription) {
		// Find IRemoteServiceContainers for the given
		// RemoteServiceEndpointDescription via registered services
		IRemoteServiceContainer[] rsContainers = findProxyContainers(endpointDescription);
		// If none found, we have nothing to do
		if (rsContainers == null || rsContainers.length == 0) {
			logWarning("handleDiscoveredServiceAvailable", //$NON-NLS-1$
					"No local RemoteServiceContainers found for endpoint description=" //$NON-NLS-1$
							+ endpointDescription);
			return;
		}
		// Get endpoint ID
		ID endpointID = endpointDescription.getEndpointAsID();
		// Get remote service filter from the service endpoint description
		// if it exists.
		String remoteServiceFilter = getFullRemoteServicesFilter(
				endpointDescription.getRemoteServicesFilter(),
				endpointDescription.getRemoteServiceId());
		// Get provided interfaces as collection
		Collection providedInterfaces = endpointDescription
				.getProvidedInterfaces();
		// Now for all remote service containers
		for (int i = 0; i < rsContainers.length; i++) {
			for (Iterator j = providedInterfaces.iterator(); j.hasNext();) {
				String providedInterface = (String) j.next();
				IRemoteServiceReference[] remoteReferences = null;
				// fire IProxyDistributionListeners pre get references
				firePreGetRemoteServiceReferences(endpointDescription,
						rsContainers[i]);
				try {
					// Get remote remote references for each container
					remoteReferences = rsContainers[i].getContainerAdapter()
							.getRemoteServiceReferences(endpointID,
									new ID[] { endpointID }, providedInterface,
									remoteServiceFilter);
				} catch (ContainerConnectException e) {
					logError("handleDiscoveredServiceAvailable", "rsca=" //$NON-NLS-1$ //$NON-NLS-2$
							+ rsContainers[i] + ",endpointId=" + endpointID //$NON-NLS-1$
							+ ",intf=" + providedInterface //$NON-NLS-1$
							+ ". Connect error in getRemoteServiceReferences", //$NON-NLS-1$
							e);
					continue;
				} catch (InvalidSyntaxException e) {
					logError(
							"handleDiscoveredServiceAvailable", //$NON-NLS-1$
							"rsca=" //$NON-NLS-1$
									+ rsContainers[i]
									+ ",endpointId=" //$NON-NLS-1$
									+ endpointID
									+ ",intf=" //$NON-NLS-1$
									+ providedInterface
									+ " Filter syntax error in getRemoteServiceReferences", //$NON-NLS-1$
							e);
					continue;
				}
				if (remoteReferences == null || remoteReferences.length == 0) {
					logError("handleDiscoveredServiceAvailable", //$NON-NLS-1$
							"getRemoteServiceReferences result is empty. " //$NON-NLS-1$
									+ "containerHelper=" //$NON-NLS-1$
									+ rsContainers[i]
									+ "remoteReferences=" //$NON-NLS-1$
									+ ((remoteReferences == null) ? "null" //$NON-NLS-1$
											: Arrays.asList(remoteReferences)
													.toString()), null);
					continue;
				} else {
					registerRemoteServiceReferences(endpointDescription,
							rsContainers[i], remoteReferences);
				}
			}
		}
	}

	private String getFullRemoteServicesFilter(String remoteServicesFilter,
			long remoteServiceId) {
		if (remoteServiceId < 0)
			return remoteServicesFilter;
		StringBuffer filter = new StringBuffer("(&(") //$NON-NLS-1$
				.append(org.eclipse.ecf.remoteservice.Constants.SERVICE_ID)
				.append("=").append(remoteServiceId).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
		if (remoteServicesFilter != null)
			filter.append(remoteServicesFilter);
		filter.append(")"); //$NON-NLS-1$
		return filter.toString();
	}

	private void firePreGetRemoteServiceReferences(
			final IRemoteServiceEndpointDescription endpointDescription,
			final IRemoteServiceContainer remoteServiceContainer) {
		Activator activator = Activator.getDefault();
		if (activator != null) {
			IProxyDistributionListener[] listeners = activator
					.getProxyDistributionListeners();
			if (listeners != null) {
				for (int i = 0; i < listeners.length; i++) {
					final IProxyDistributionListener l = listeners[i];
					SafeRunner.run(new ISafeRunnable() {
						public void handleException(Throwable exception) {
							logError(
									"firePreGetRemoteServiceReferences", //$NON-NLS-1$
									"Exception calling proxy distribution listener", //$NON-NLS-1$
									exception);
						}

						public void run() throws Exception {
							l.retrievingRemoteServiceReferences(
									endpointDescription, remoteServiceContainer);
						}
					});
				}
			}
		}
	}

	private void firePreRegister(
			final IRemoteServiceEndpointDescription endpointDescription,
			final IRemoteServiceContainer remoteServiceContainer,
			final IRemoteServiceReference remoteServiceReference) {
		Activator activator = Activator.getDefault();
		if (activator != null) {
			IProxyDistributionListener[] listeners = activator
					.getProxyDistributionListeners();
			if (listeners != null) {
				for (int i = 0; i < listeners.length; i++) {
					final IProxyDistributionListener l = listeners[i];
					SafeRunner.run(new ISafeRunnable() {
						public void handleException(Throwable exception) {
							logError(
									"firePreRegister", //$NON-NLS-1$
									"Exception calling proxy distribution listener", //$NON-NLS-1$
									exception);
						}

						public void run() throws Exception {
							l.registering(endpointDescription,
									remoteServiceContainer,
									remoteServiceReference);
						}
					});
				}
			}
		}
	}

	private void firePostRegister(
			final IRemoteServiceEndpointDescription endpointDescription,
			final IRemoteServiceContainer remoteServiceContainer,
			final IRemoteServiceReference remoteServiceReference,
			final ServiceRegistration serviceRegistration) {
		Activator activator = Activator.getDefault();
		if (activator != null) {
			IProxyDistributionListener[] listeners = activator
					.getProxyDistributionListeners();
			if (listeners != null) {
				for (int i = 0; i < listeners.length; i++) {
					final IProxyDistributionListener l = listeners[i];
					SafeRunner.run(new ISafeRunnable() {
						public void handleException(Throwable exception) {
							logError(
									"firePreRegister", //$NON-NLS-1$
									"Exception calling proxy distribution listener", //$NON-NLS-1$
									exception);
						}

						public void run() throws Exception {
							l.registered(endpointDescription,
									remoteServiceContainer,
									remoteServiceReference, serviceRegistration);
						}
					});
				}
			}
		}
	}

	private void fireUnregister(
			final IRemoteServiceEndpointDescription endpointDescription,
			final ServiceRegistration registration) {
		Activator activator = Activator.getDefault();
		if (activator != null) {
			IProxyDistributionListener[] listeners = activator
					.getProxyDistributionListeners();
			if (listeners != null) {
				for (int i = 0; i < listeners.length; i++) {
					final IProxyDistributionListener l = listeners[i];
					SafeRunner.run(new ISafeRunnable() {
						public void handleException(Throwable exception) {
							logError(
									"fireUnregister", //$NON-NLS-1$
									"Exception calling proxy distribution listener", //$NON-NLS-1$
									exception);
						}

						public void run() throws Exception {
							l.unregistered(endpointDescription, registration);
						}
					});
				}
			}
		}
	}

	private RemoteServiceEndpointDescription getECFDescription(
			ServiceEndpointDescription aServiceEndpointDesc) {
		RemoteServiceEndpointDescription ecfSED;
		if (!(aServiceEndpointDesc instanceof RemoteServiceEndpointDescription)) {
			ecfSED = (RemoteServiceEndpointDescription) Activator
					.getDefault()
					.getAdapterManager()
					.loadAdapter(aServiceEndpointDesc,
							RemoteServiceEndpointDescription.class.getName());
		} else
			ecfSED = (RemoteServiceEndpointDescription) aServiceEndpointDesc;
		return ecfSED;
	}

	private boolean findProxyServiceRegistration(
			RemoteServiceEndpointDescription sed) {
		synchronized (discoveredRemoteServiceRegistrations) {
			for (Iterator i = discoveredRemoteServiceRegistrations.keySet()
					.iterator(); i.hasNext();) {
				ID containerID = (ID) i.next();
				RemoteServiceRegistration reg = (RemoteServiceRegistration) discoveredRemoteServiceRegistrations
						.get(containerID);
				if (reg.hasRSED(sed))
					return true;
			}
			return false;
		}
	}

	private ServiceRegistration[] removeProxyServiceRegistrations(
			RemoteServiceEndpointDescription sed) {
		List results = new ArrayList();
		synchronized (discoveredRemoteServiceRegistrations) {
			final List containerIDsToRemove = new ArrayList();
			for (Iterator i = discoveredRemoteServiceRegistrations.keySet()
					.iterator(); i.hasNext();) {
				ID containerID = (ID) i.next();
				RemoteServiceRegistration reg = (RemoteServiceRegistration) discoveredRemoteServiceRegistrations
						.get(containerID);
				if (reg != null) {
					ServiceRegistration sr = reg.removeServiceRegistration(sed);
					if (sr != null)
						results.add(sr);
					if (reg.isEmpty()) {
						reg.dispose();
						containerIDsToRemove.add(containerID);
					}
				}
			}
			// Outside of the iterator, now remove any containerID found to
			// match
			for (Iterator i = containerIDsToRemove.iterator(); i.hasNext();) {
				discoveredRemoteServiceRegistrations.remove(i.next());
			}
			return (ServiceRegistration[]) results
					.toArray(new ServiceRegistration[] {});
		}
	}

	class RemoteServiceReferenceUnregisteredListener implements
			IRemoteServiceListener {
		public void handleServiceEvent(IRemoteServiceEvent event) {
			if (event instanceof IRemoteServiceUnregisteredEvent) {
				ID containerID = event.getContainerID();
				ID localContainerID = event.getLocalContainerID();
				IRemoteServiceReference reference = event.getReference();
				trace("handleRemoteServiceUnregisteredEvent", //$NON-NLS-1$
						"localContainerID=" + localContainerID //$NON-NLS-1$
								+ ",containerID=" + containerID //$NON-NLS-1$
								+ ",remoteReference=" + reference); //$NON-NLS-1$
				// Synchronize on serviceLocations so no other changes happen
				// while
				// this is going on...as it can be invoked by an arbitrary
				RemoteServiceRegistration.RSEDAndSRAssoc[] assocs = null;
				synchronized (serviceLocations) {
					synchronized (discoveredRemoteServiceRegistrations) {
						List containerIDsToRemove = new ArrayList();
						RemoteServiceRegistration rsRegs = (RemoteServiceRegistration) discoveredRemoteServiceRegistrations
								.get(localContainerID);
						// If we've got any remote service registrations for the
						// containerID
						if (rsRegs != null) {
							assocs = rsRegs
									.removeServiceRegistration(reference);
							// If this removes *all* references for this
							// registration
							if (rsRegs.isEmpty()) {
								rsRegs.dispose();
								containerIDsToRemove.add(localContainerID);
							}
							if (assocs != null) {
								for (int i = 0; i < assocs.length; i++) {
									removeDiscoveredServiceID(assocs[i]
											.getRSED());
								}
							}
						}
						for (Iterator i = containerIDsToRemove.iterator(); i
								.hasNext();) {
							discoveredRemoteServiceRegistrations.remove(i
									.next());
						}
					}

				}
				// Call this outside of synchronized block
				if (assocs != null) {
					for (int i = 0; i < assocs.length; i++) {
						ServiceRegistration sr = assocs[i].getSR();
						trace("handleRemoteServiceUnregisteredEvent.unregister", //$NON-NLS-1$
						"localContainerID=" //$NON-NLS-1$
								+ localContainerID + ",containerID=" //$NON-NLS-1$
								+ containerID + ",remoteReference=" //$NON-NLS-1$
								+ reference + ",proxyServiceRegistrations=" //$NON-NLS-1$
								+ sr);
						unregisterProxyServiceRegistration(assocs[i].getRSED(),
								sr);
					}
				}
			}
		}
	}

	private void unregisterProxyServiceRegistration(
			IRemoteServiceEndpointDescription endpointDescription,
			ServiceRegistration reg) {
		try {
			distributionProvider.removeRemoteService(reg.getReference());
			reg.unregister();
		} catch (IllegalStateException e) {
			// Ignore
			logWarning("unregisterProxyServiceRegistration", //$NON-NLS-1$
					"Exception unregistering serviceRegistration=" + reg); //$NON-NLS-1$
		} catch (Exception e) {
			logError("unregisterProxyServiceRegistration", //$NON-NLS-1$
					"Exception unregistering serviceRegistration=" + reg, e); //$NON-NLS-1$
		}
		fireUnregister(endpointDescription, reg);
	}

	private void registerRemoteServiceReferences(
			RemoteServiceEndpointDescription sed,
			IRemoteServiceContainer remoteServiceContainer,
			IRemoteServiceReference[] remoteReferences) {

		synchronized (serviceLocations) {
			// check to make sure that this serviceLocation
			// is still present
			if (!containsDiscoveredServiceID(sed)) {
				logError("registerRemoteServiceReferences", "serviceLocation=" //$NON-NLS-1$ //$NON-NLS-2$
						+ sed + " no longer present", null); //$NON-NLS-1$
				return;
			}
			// check to make sure that the proxy service registry is not
			// already there
			if (findProxyServiceRegistration(sed)) {
				logError("registerRemoteServiceReferences", //$NON-NLS-1$
						"serviceEndpointDesc=" + sed //$NON-NLS-1$
								+ " previously registered locally...ignoring", //$NON-NLS-1$
						null);
				return;
			}
			// Then get/setup remote service
			for (int i = 0; i < remoteReferences.length; i++) {
				// Get IRemoteService, used to create the proxy
				IRemoteService remoteService = remoteServiceContainer
						.getContainerAdapter().getRemoteService(
								remoteReferences[i]);
				// If no remote service then give up
				if (remoteService == null) {
					logError("registerRemoteServiceReferences", //$NON-NLS-1$
							"Remote service is null for remote reference " //$NON-NLS-1$
									+ remoteReferences[i], null);
					continue;
				}

				// Get classes to register for remote service
				String[] clazzes = (String[]) remoteReferences[i]
						.getProperty(Constants.OBJECTCLASS);
				if (clazzes == null || clazzes.length == 0) {
					logError("registerRemoteServiceReferences", //$NON-NLS-1$
							"No classes specified for remote service reference " //$NON-NLS-1$
									+ remoteReferences[i], null);
					continue;
				}

				// Get service properties for the proxy registration
				Dictionary properties = getPropertiesForRemoteService(sed,
						remoteServiceContainer, remoteReferences[i],
						remoteService);

				// Create proxy right here
				Object proxy = null;
				try {
					proxy = remoteService.getProxy();
					if (proxy == null) {
						logError("registerRemoteServiceReferences", //$NON-NLS-1$
								"Remote service proxy is null", null); //$NON-NLS-1$
						continue;
					}
					// Fire pre register notification fir
					// IProxyDistributionListener
					firePreRegister(sed, remoteServiceContainer,
							remoteReferences[i]);
					trace("registerRemoteServiceReferences", "rsca=" //$NON-NLS-1$ //$NON-NLS-2$
							+ remoteServiceContainer + ",remoteReference=" //$NON-NLS-1$
							+ remoteReferences[i]);
					// Actually register proxy here
					ServiceRegistration registration = Activator.getDefault()
							.getContext()
							.registerService(clazzes, proxy, properties);

					RemoteServiceRegistration reg = getProxyServiceRegistration(remoteServiceContainer);
					reg.addServiceRegistration(remoteReferences[i], sed,
							registration);
					// And add to distribution provider
					distributionProvider.addRemoteService(registration
							.getReference());
					trace("addLocalServiceRegistration.COMPLETE", //$NON-NLS-1$
							"containerHelper=" + remoteServiceContainer //$NON-NLS-1$
									+ ",remoteServiceReference=" //$NON-NLS-1$
									+ remoteReferences[i]
									+ ",localServiceRegistration=" //$NON-NLS-1$
									+ registration);
					// Fire IProxyDistributionListener to notify we're done
					firePostRegister(sed, remoteServiceContainer,
							remoteReferences[i], registration);
				} catch (Exception e) {
					logError("registerRemoteServiceReferences", //$NON-NLS-1$
							"Exception creating or registering remote reference " //$NON-NLS-1$
									+ remoteReferences[i], e);
					continue;
				}
			}
		}
	}

	private RemoteServiceRegistration getProxyServiceRegistration(
			IRemoteServiceContainer rsContainer) {
		ID localContainerID = rsContainer.getContainer().getID();
		synchronized (discoveredRemoteServiceRegistrations) {
			RemoteServiceRegistration reg = (RemoteServiceRegistration) discoveredRemoteServiceRegistrations
					.get(localContainerID);
			// If there is none, then create one
			if (reg == null) {
				reg = new RemoteServiceRegistration(rsContainer,
						new RemoteServiceReferenceUnregisteredListener());
				discoveredRemoteServiceRegistrations.put(localContainerID, reg);
			}
			return reg;
		}
	}

	private boolean isRemoteServiceProperty(String propertyKey) {
		return ecfRemoteServiceProperties.contains(propertyKey);
	}

	private Dictionary getPropertiesForRemoteService(
			RemoteServiceEndpointDescription rsEndpointDescription,
			IRemoteServiceContainer rsContainer,
			IRemoteServiceReference rsReference, IRemoteService remoteService) {

		Properties props = new Properties();
		// Add the required 'service.imported' property, which for ECF rs
		// providers
		// exposes the IRemoteService
		props.put(IDistributionConstants.SERVICE_IMPORTED, remoteService);

		// Add service intents...if not null (optional property)
		String[] serviceIntents = rsEndpointDescription.getServiceIntents();
		if (serviceIntents != null)
			props.put(IDistributionConstants.SERVICE_INTENTS, serviceIntents);

		// Then add all other service properties
		String[] propKeys = rsReference.getPropertyKeys();
		for (int i = 0; i < propKeys.length; i++) {
			if (!isRemoteServiceProperty(propKeys[i])) {
				props.put(propKeys[i], rsReference.getProperty(propKeys[i]));
			}
		}

		// make the service identifiable by consumers
		// especially org.eclipse.ecf.remoteservice.ui.dosgi
		final ID endpointId = (ID) rsReference
				.getProperty(org.eclipse.ecf.remoteservice.Constants.SERVICE_CONTAINER_ID);
		final Long serviceId = (Long) rsReference
				.getProperty(org.eclipse.ecf.remoteservice.Constants.SERVICE_ID);
		props.put(ServicePublication.ENDPOINT_ID, endpointId + "#" + serviceId); //$NON-NLS-1$

		// finally add service.imported.configs
		addImportedConfigsProperties(
				getContainerTypeDescription(rsContainer.getContainer()),
				rsEndpointDescription.getSupportedConfigs(), props);

		return props;
	}

	private void addImportedConfigsProperties(
			ContainerTypeDescription containerTypeDescription,
			String[] remoteExportedConfigs, Dictionary exportedProperties) {
		if (containerTypeDescription == null)
			return;
		if (remoteExportedConfigs != null) {
			String[] importedConfigs = containerTypeDescription
					.getImportedConfigs(remoteExportedConfigs);
			if (importedConfigs != null) {
				// Add the service.imported.configs property
				exportedProperties.put(
						IDistributionConstants.SERVICE_IMPORTED_CONFIGS,
						importedConfigs);
				// First get any/all properties to add
				Dictionary localConfigProperties = containerTypeDescription
						.getPropertiesForImportedConfigs(importedConfigs,
								exportedProperties);
				if (localConfigProperties != null) {
					for (Enumeration e = localConfigProperties.keys(); e
							.hasMoreElements();) {
						String key = (String) e.nextElement();
						exportedProperties.put(key,
								localConfigProperties.get(key));
					}
				}
			}
		}
	}

	protected ContainerTypeDescription getContainerTypeDescription(
			IContainer container) {
		IContainerManager containerManager = getContainerManager();
		if (containerManager == null)
			return null;
		return containerManager.getContainerTypeDescription(container.getID());
	}

	protected IContainerManager getContainerManager() {
		Activator activator = Activator.getDefault();
		if (activator == null)
			return null;
		return activator.getContainerManager();
	}

	private boolean addDiscoveredServiceID(RemoteServiceEndpointDescription desc) {
		synchronized (serviceLocations) {
			return serviceLocations.add(desc);
		}
	}

	private boolean removeDiscoveredServiceID(
			RemoteServiceEndpointDescription desc) {
		synchronized (serviceLocations) {
			return serviceLocations.remove(desc);
		}
	}

	private boolean containsDiscoveredServiceID(
			RemoteServiceEndpointDescription desc) {
		synchronized (serviceLocations) {
			return serviceLocations.contains(desc);
		}
	}

	protected void trace(String methodName, String message) {
		LogUtility.trace(methodName, DebugOptions.DISCOVEREDSERVICETRACKER,
				this.getClass(), message);
	}

	protected void traceException(String methodName, String message, Throwable t) {
		LogUtility.traceException(methodName, DebugOptions.EXCEPTIONS_CATCHING,
				this.getClass(), message, t);
	}

	protected void logError(String methodName, String message, Throwable t) {
		LogUtility.logError(methodName, DebugOptions.DISCOVEREDSERVICETRACKER,
				this.getClass(), message, t);
	}

	protected void logError(String methodName, String message) {
		LogUtility.logError(methodName, DebugOptions.DISCOVEREDSERVICETRACKER,
				this.getClass(), message);
	}

	protected void logWarning(String methodName, String message) {
		LogUtility
				.logWarning(methodName, DebugOptions.DISCOVEREDSERVICETRACKER,
						this.getClass(), message);
	}

	private boolean isValidDescription(
			RemoteServiceEndpointDescription rsEndpointDescription) {
		if (rsEndpointDescription == null)
			return false;
		synchronized (serviceLocations) {
			if (containsDiscoveredServiceID(rsEndpointDescription)) {
				return false;
			} else {
				addDiscoveredServiceID(rsEndpointDescription);
				return true;
			}
		}
	}

	private IRemoteServiceContainer[] findProxyContainers(
			final RemoteServiceEndpointDescription rsEndpointDescription) {
		// Get activator
		Activator activator = Activator.getDefault();
		if (activator == null)
			return null;
		// Get finder (as service)
		IProxyContainerFinder finder = activator
				.getProxyRemoteServiceContainerFinder();
		if (finder == null) {
			logError("findRemoteServiceContainersViaService", //$NON-NLS-1$
					"No container finders available"); //$NON-NLS-1$
			return null;
		}
		return finder.findProxyContainers(rsEndpointDescription.getServiceID(),
				rsEndpointDescription);
	}

}
