/*******************************************************************************
 * Copyright (c) 2010-2011 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.osgi.services.remoteserviceadmin;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
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.Properties;
import java.util.Set;
import java.util.TreeMap;

import org.eclipse.core.runtime.Assert;
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.core.util.ECFException;
import org.eclipse.ecf.internal.osgi.services.remoteserviceadmin.Activator;
import org.eclipse.ecf.internal.osgi.services.remoteserviceadmin.DebugOptions;
import org.eclipse.ecf.internal.osgi.services.remoteserviceadmin.LogUtility;
import org.eclipse.ecf.internal.osgi.services.remoteserviceadmin.PropertiesUtil;
import org.eclipse.ecf.remoteservice.IOSGiRemoteServiceContainerAdapter;
import org.eclipse.ecf.remoteservice.IRemoteService;
import org.eclipse.ecf.remoteservice.IRemoteServiceContainer;
import org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter;
import org.eclipse.ecf.remoteservice.IRemoteServiceID;
import org.eclipse.ecf.remoteservice.IRemoteServiceListener;
import org.eclipse.ecf.remoteservice.IRemoteServiceReference;
import org.eclipse.ecf.remoteservice.IRemoteServiceRegistration;
import org.eclipse.ecf.remoteservice.events.IRemoteServiceEvent;
import org.eclipse.ecf.remoteservice.events.IRemoteServiceUnregisteredEvent;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceException;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.Version;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.remoteserviceadmin.EndpointPermission;
import org.osgi.service.remoteserviceadmin.RemoteServiceAdminListener;
import org.osgi.util.tracker.ServiceTracker;

@SuppressWarnings("deprecation")
public class RemoteServiceAdmin implements
		org.osgi.service.remoteserviceadmin.RemoteServiceAdmin {

	public static final String SERVICE_PROP = "org.eclipse.ecf.rsa"; //$NON-NLS-1$

	private Bundle clientBundle;

	private boolean hostAutoCreateContainer = new Boolean(
			System.getProperty(
					"org.eclipse.ecf.osgi.services.remoteserviceadmin.hostAutoCreateContainer", //$NON-NLS-1$
					"true")).booleanValue(); //$NON-NLS-1$
	private String[] hostDefaultConfigTypes = new String[] { System
			.getProperty(
					"org.eclipse.ecf.osgi.services.remoteserviceadmin.hostDefaultConfigType", //$NON-NLS-1$
					"ecf.generic.server") }; //$NON-NLS-1$

	private boolean consumerAutoCreateContainer = new Boolean(
			System.getProperty(
					"org.eclipse.ecf.osgi.services.remoteserviceadmin.consumerAutoCreateContainer", //$NON-NLS-1$
					"true")).booleanValue(); //$NON-NLS-1$

	private ServiceTracker packageAdminTracker;
	private Object packageAdminTrackerLock = new Object();

	private Object eventAdminTrackerLock = new Object();
	private ServiceTracker eventAdminTracker;

	private Object remoteServiceAdminListenerTrackerLock = new Object();
	private ServiceTracker remoteServiceAdminListenerTracker;

	private HostContainerSelector defaultHostContainerSelector;
	private ServiceRegistration defaultHostContainerSelectorRegistration;

	private ConsumerContainerSelector defaultConsumerContainerSelector;
	private ServiceRegistration defaultConsumerContainerSelectorRegistration;

	private Collection<ExportRegistration> exportedRegistrations = new ArrayList<ExportRegistration>();
	private Collection<ImportRegistration> importedRegistrations = new ArrayList<ImportRegistration>();

	public RemoteServiceAdmin(Bundle clientBundle) {
		this.clientBundle = clientBundle;
		Assert.isNotNull(this.clientBundle);
		trace("RemoteServiceAdmin<init>",
				"clientBundle=" + clientBundle.getSymbolicName());
		// Only setup defaults if it hasn't already been done by some other
		// Remote Service Admin instance
		Properties props = new Properties();
		props.put(org.osgi.framework.Constants.SERVICE_RANKING, new Integer(
				Integer.MIN_VALUE));
		// host container selector
		ServiceReference[] hostContainerSelectorRefs = null;
		try {
			hostContainerSelectorRefs = getClientBundleContext()
					.getServiceReferences(
							IHostContainerSelector.class.getName(), null);
		} catch (InvalidSyntaxException e) {
			// will not happen
		}
		// register a default only if no others already exist
		if (hostContainerSelectorRefs == null
				|| hostContainerSelectorRefs.length == 0) {
			defaultHostContainerSelector = new HostContainerSelector(
					hostDefaultConfigTypes, hostAutoCreateContainer);
			defaultHostContainerSelectorRegistration = getClientBundleContext()
					.registerService(IHostContainerSelector.class.getName(),
							defaultHostContainerSelector, (Dictionary) props);
		}
		// consumer container selector
		ServiceReference[] consumerContainerSelectorRefs = null;
		try {
			consumerContainerSelectorRefs = getClientBundleContext()
					.getServiceReferences(
							IConsumerContainerSelector.class.getName(), null);
		} catch (InvalidSyntaxException e) {
			// will not happen
		}
		// register a default only if no others already exist
		if (consumerContainerSelectorRefs == null
				|| consumerContainerSelectorRefs.length == 0) {
			defaultConsumerContainerSelector = new ConsumerContainerSelector(
					consumerAutoCreateContainer);
			defaultConsumerContainerSelectorRegistration = getClientBundleContext()
					.registerService(
							IConsumerContainerSelector.class.getName(),
							defaultConsumerContainerSelector,
							(Dictionary) props);
		}
	}

	// RemoteServiceAdmin service interface impl methods
	public Collection<org.osgi.service.remoteserviceadmin.ExportRegistration> exportService(
			ServiceReference serviceReference,
			Map<String, Object> overridingProperties) {

		trace("exportService", "serviceReference=" + serviceReference //$NON-NLS-1$ //$NON-NLS-2$
				+ ",properties=" + overridingProperties); //$NON-NLS-1$

		overridingProperties = (overridingProperties == null) ? Collections.EMPTY_MAP
				: overridingProperties;

		// First get exported interfaces
		String[] exportedInterfaces = (String[]) overridingProperties
				.get(org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_EXPORTED_INTERFACES);
		// As per 122.5.1 we only use the OBJECTCLASS value from the
		// serviceReference, not from the overridingProperties map
		if (exportedInterfaces == null)
			exportedInterfaces = PropertiesUtil
					.getExportedInterfaces(serviceReference);
		// If exportedInterfaces is still null, we throw
		if (exportedInterfaces == null)
			throw new IllegalArgumentException(
					org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_EXPORTED_INTERFACES
							+ " not set"); //$NON-NLS-1$

		// Get optional exported configs
		String[] exportedConfigs = PropertiesUtil
				.getStringArrayFromPropertyValue(overridingProperties
						.get(org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_EXPORTED_CONFIGS));
		if (exportedConfigs == null) {
			exportedConfigs = PropertiesUtil
					.getStringArrayFromPropertyValue(serviceReference
							.getProperty(org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_EXPORTED_CONFIGS));
		}
		// Get all intents (service.intents, service.exported.intents,
		// service.exported.intents.extra)
		String[] serviceIntents = PropertiesUtil.getServiceIntents(
				serviceReference, overridingProperties);

		// Get a host container selector, and use it to
		IHostContainerSelector hostContainerSelector = getHostContainerSelector();
		if (hostContainerSelector == null) {
			logError("handleServiceRegistering", //$NON-NLS-1$
					"No defaultHostContainerSelector available"); //$NON-NLS-1$
			return Collections.EMPTY_LIST;
		}
		// select ECF remote service containers that match given exported
		// interfaces, configs, and intents
		IRemoteServiceContainer[] rsContainers = hostContainerSelector
				.selectHostContainers(serviceReference, exportedInterfaces,
						exportedConfigs, serviceIntents);
		// If none found, log a warning and we're done
		if (rsContainers == null || rsContainers.length == 0) {
			logWarning(
					"handleServiceRegistered", "No remote service containers found for serviceReference=" //$NON-NLS-1$ //$NON-NLS-2$
							+ serviceReference
							+ ". Remote service NOT EXPORTED"); //$NON-NLS-1$
			return Collections.EMPTY_LIST;
		}
		Collection<ExportRegistration> exportRegistrations = new ArrayList<ExportRegistration>();
		synchronized (exportedRegistrations) {
			for (int i = 0; i < rsContainers.length; i++) {
				ExportRegistration exportRegistration = null;
				// If we've already got an export endpoint
				// for this service reference/containerID combination,
				// then create an ExportRegistration that uses the endpoint
				ExportEndpoint exportEndpoint = findExistingExportEndpoint(
						serviceReference, rsContainers[i].getContainer()
								.getID());
				// If we've already got one, then create a new
				// ExportRegistration for it and we're done
				if (exportEndpoint != null)
					exportRegistration = new ExportRegistration(exportEndpoint);
				else {
					// otherwise, actually export the service to create a new
					// ExportEndpoint
					// and use it to create a new ExportRegistration
					exportRegistration = new ExportRegistration(
							exportService(serviceReference,
									overridingProperties, exportedInterfaces,
									serviceIntents, rsContainers[i]));
					// If no exception, we add it to our known set of exported
					// registrations
					if (exportRegistration.getException() == null)
						addExportRegistration(exportRegistration);
				}
				// We add it to the results in either case
				exportRegistrations.add(exportRegistration);
			}
		}
		// publish all exportRegistrations
		for (ExportRegistration exportReg : exportRegistrations)
			publishExportEvent(exportReg);
		// and return
		return new ArrayList<org.osgi.service.remoteserviceadmin.ExportRegistration>(
				exportRegistrations);
	}

	public org.osgi.service.remoteserviceadmin.ImportRegistration importService(
			org.osgi.service.remoteserviceadmin.EndpointDescription endpointDescription) {

		trace("importService", "endpointDescription=" + endpointDescription); //$NON-NLS-1$ //$NON-NLS-2$
		// First, make sure that the client bundle has the IMPORT endpoint
		// permission
		checkEndpointPermission(endpointDescription, EndpointPermission.IMPORT);

		if (endpointDescription.getServiceId() == 0)
			return handleNonOSGiService(endpointDescription);

		EndpointDescription ed = null;
		if (endpointDescription instanceof EndpointDescription)
			ed = (EndpointDescription) endpointDescription;
		else
			ed = new EndpointDescription(endpointDescription.getProperties());

		// Now get IConsumerContainerSelector, to select the ECF container
		// for the given endpointDescription
		IConsumerContainerSelector consumerContainerSelector = getConsumerContainerSelector();
		// If there is none, then we can go no further
		if (consumerContainerSelector == null) {
			logError("importService", //$NON-NLS-1$
					"No defaultConsumerContainerSelector available"); //$NON-NLS-1$
			return null;
		}
		// Select the rsContainer to handle the endpoint description
		IRemoteServiceContainer rsContainer = consumerContainerSelector
				.selectConsumerContainer(ed);
		// If none found, log a warning and we're done
		if (rsContainer == null) {
			logWarning(
					"importService", "No remote service container selected for endpoint=" //$NON-NLS-1$ //$NON-NLS-2$
							+ endpointDescription
							+ ". Remote service NOT IMPORTED"); //$NON-NLS-1$
			return null;
		}
		// If one selected then import the service to create an import
		// registration
		ImportRegistration importRegistration = null;
		synchronized (importedRegistrations) {
			ImportEndpoint importEndpoint = findImportEndpoint(ed);
			if (importEndpoint != null)
				importRegistration = new ImportRegistration(importEndpoint);
			else {
				importEndpoint = importService(ed, rsContainer);
				importRegistration = new ImportRegistration(importEndpoint);
				if (importRegistration.getException() == null)
					addImportRegistration(importRegistration);
			}
		}
		// publish import event
		publishImportEvent(importRegistration);
		// Finally, return the importRegistration. It may be null or not.
		return importRegistration;
	}

	public Collection<org.osgi.service.remoteserviceadmin.ExportReference> getExportedServices() {
		Collection<org.osgi.service.remoteserviceadmin.ExportReference> results = new ArrayList<org.osgi.service.remoteserviceadmin.ExportReference>();
		synchronized (exportedRegistrations) {
			for (ExportRegistration reg : exportedRegistrations) {
				org.osgi.service.remoteserviceadmin.ExportReference eRef = reg
						.getExportReference();
				if (eRef != null
						&& checkEndpointPermissionRead("getExportedServices", //$NON-NLS-1$
								eRef.getExportedEndpoint()))
					results.add(eRef);
			}
		}
		return results;
	}

	public Collection<org.osgi.service.remoteserviceadmin.ImportReference> getImportedEndpoints() {
		Collection<org.osgi.service.remoteserviceadmin.ImportReference> results = new ArrayList<org.osgi.service.remoteserviceadmin.ImportReference>();
		synchronized (importedRegistrations) {
			for (ImportRegistration reg : importedRegistrations) {
				org.osgi.service.remoteserviceadmin.ImportReference iRef = reg
						.getImportReference();
				if (iRef != null
						&& checkEndpointPermissionRead("getImportedEndpoints", //$NON-NLS-1$
								iRef.getImportedEndpoint()))
					results.add(iRef);
			}
		}
		return results;
	}

	// end RemoteServiceAdmin service interface impl methods

	private boolean checkEndpointPermissionRead(
			String methodName,
			org.osgi.service.remoteserviceadmin.EndpointDescription endpointDescription) {
		try {
			checkEndpointPermission(endpointDescription,
					EndpointPermission.READ);
			return true;
		} catch (SecurityException e) {
			logError(methodName,
					"permission check failed for read access to endpointDescription=" //$NON-NLS-1$
							+ endpointDescription, e);
			return false;
		}
	}

	private BundleContext getClientBundleContext() {
		return clientBundle.getBundleContext();
	}

	private Bundle getClientBundle() {
		return clientBundle;
	}

	private void addImportRegistration(ImportRegistration importRegistration) {
		synchronized (importedRegistrations) {
			importedRegistrations.add(importRegistration);
			trace("addImportRegistration", "importRegistration="
					+ importRegistration + " importedRegistrations="
					+ importedRegistrations);
		}
	}

	private void addExportRegistration(ExportRegistration exportRegistration) {
		synchronized (exportedRegistrations) {
			exportedRegistrations.add(exportRegistration);
			trace("addExportRegistration", "exportRegistration="
					+ exportRegistration + " exportedRegistrations="
					+ exportedRegistrations);
		}
	}

	private boolean removeExportRegistration(
			ExportRegistration exportRegistration) {
		synchronized (exportedRegistrations) {
			boolean removed = exportedRegistrations.remove(exportRegistration);
			trace("removeExportRegistration", "exportRegistration=" //$NON-NLS-1$ //$NON-NLS-2$
					+ exportRegistration + " exportedRegistrations=" //$NON-NLS-1$
					+ exportedRegistrations + " removed=" + removed); //$NON-NLS-1$
			return removed;
		}
	}

	private boolean removeImportRegistration(
			ImportRegistration importRegistration) {
		synchronized (importedRegistrations) {
			boolean removed = importedRegistrations.remove(importRegistration);
			trace("removeImportRegistration", "importRegistration=" //$NON-NLS-1$ //$NON-NLS-2$
					+ importRegistration + " importedRegistrations=" //$NON-NLS-1$
					+ importedRegistrations + " removed=" + removed); //$NON-NLS-1$
			return removed;
		}
	}

	private void closeDefaultContainerSelectors() {
		if (defaultHostContainerSelectorRegistration != null) {
			defaultHostContainerSelectorRegistration.unregister();
			defaultHostContainerSelectorRegistration = null;
		}
		if (defaultHostContainerSelector != null) {
			defaultHostContainerSelector.close();
			defaultHostContainerSelector = null;
		}
		if (defaultConsumerContainerSelectorRegistration != null) {
			defaultConsumerContainerSelectorRegistration.unregister();
			defaultConsumerContainerSelectorRegistration = null;
		}
		if (defaultConsumerContainerSelector != null) {
			defaultConsumerContainerSelector.close();
			defaultConsumerContainerSelector = null;
		}
	}

	private void checkEndpointPermission(
			org.osgi.service.remoteserviceadmin.EndpointDescription endpointDescription,
			String permissionType) throws SecurityException {
		SecurityManager sm = System.getSecurityManager();
		if (sm == null)
			return;
		sm.checkPermission(new EndpointPermission(endpointDescription,
				Activator.getDefault().getFrameworkUUID(), permissionType));
	}

	class ExportEndpoint {

		private ServiceReference serviceReference;
		private EndpointDescription endpointDescription;

		private IRemoteServiceRegistration rsRegistration;
		private ExportReference exportReference;
		private Set<ExportRegistration> exportRegistrations = new HashSet<ExportRegistration>();

		private Throwable exception;

		ExportEndpoint(ServiceReference serviceReference,
				EndpointDescription endpointDescription,
				IRemoteServiceRegistration reg) {
			Assert.isNotNull(serviceReference);
			this.serviceReference = serviceReference;
			Assert.isNotNull(endpointDescription);
			this.endpointDescription = endpointDescription;

			Assert.isNotNull(reg);
			this.rsRegistration = reg;
			this.exportReference = new ExportReference(serviceReference,
					endpointDescription);
		}

		ExportEndpoint(ServiceReference serviceReference,
				EndpointDescription endpointDescription, Throwable t) {
			Assert.isNotNull(serviceReference);
			this.serviceReference = serviceReference;
			Assert.isNotNull(endpointDescription);
			this.endpointDescription = endpointDescription;
			this.exception = t;
		}

		synchronized Throwable getException() {
			return exception;
		}

		synchronized ID getContainerID() {
			return endpointDescription.getContainerID();
		}

		synchronized ServiceReference getServiceReference() {
			return serviceReference;
		}

		synchronized EndpointDescription getEndpointDescription() {
			return endpointDescription;
		}

		synchronized ExportReference getExportReference() {
			return exportReference;
		}

		synchronized IRemoteServiceRegistration getRemoteServiceRegistration() {
			return rsRegistration;
		}

		synchronized boolean add(ExportRegistration exportRegistration) {
			return this.exportRegistrations.add(exportRegistration);
		}

		synchronized boolean close(ExportRegistration exportRegistration) {
			boolean removed = this.exportRegistrations
					.remove(exportRegistration);
			if (removed && exportRegistrations.size() == 0) {
				if (rsRegistration != null) {
					rsRegistration.unregister();
					rsRegistration = null;
				}
				if (exportReference != null) {
					exportReference.close();
					exportReference = null;
				}
			}
			return removed;
		}

		public synchronized String toString() {
			return "ExportEndpoint[rsRegistration=" + rsRegistration //$NON-NLS-1$
					+ ", exportReference=" + exportReference + "]"; //$NON-NLS-1$ //$NON-NLS-2$
		}

	}

	class ExportRegistration implements
			org.osgi.service.remoteserviceadmin.ExportRegistration {

		private ExportEndpoint exportEndpoint;

		ExportRegistration(ExportEndpoint exportEndpoint) {
			Assert.isNotNull(exportEndpoint);
			this.exportEndpoint = exportEndpoint;
			// Add ourselves to this exported endpoint
			this.exportEndpoint.add(this);
		}

		synchronized ID getContainerID() {
			return (exportEndpoint == null) ? null : exportEndpoint
					.getContainerID();
		}

		synchronized ServiceReference getServiceReference() {
			return (exportEndpoint == null) ? null : exportEndpoint
					.getServiceReference();
		}

		public synchronized org.osgi.service.remoteserviceadmin.ExportReference getExportReference() {
			Throwable t = getException();
			if (t != null)
				throw new IllegalStateException(
						"Cannot get export reference as export registration is invalid", //$NON-NLS-1$
						t);
			return (exportEndpoint == null) ? null : exportEndpoint
					.getExportReference();
		}

		synchronized boolean match(ServiceReference serviceReference) {
			return match(serviceReference, null);
		}

		synchronized boolean match(ServiceReference serviceReference,
				ID containerID) {
			ServiceReference ourServiceReference = getServiceReference();
			if (ourServiceReference == null)
				return false;
			boolean serviceReferenceCompare = ourServiceReference
					.equals(serviceReference);
			// If the second parameter is null, then we compare only on service
			// references
			if (containerID == null)
				return serviceReferenceCompare;
			ID ourContainerID = getContainerID();
			if (ourContainerID == null)
				return false;
			return serviceReferenceCompare
					&& ourContainerID.equals(containerID);
		}

		synchronized ExportEndpoint getExportEndpoint(
				ServiceReference serviceReference, ID containerID) {
			return match(serviceReference, containerID) ? exportEndpoint : null;
		}

		synchronized IRemoteServiceRegistration getRemoteServiceRegistration() {
			return (exportEndpoint == null) ? null : exportEndpoint
					.getRemoteServiceRegistration();
		}

		synchronized EndpointDescription getEndpointDescription() {
			return (exportEndpoint == null) ? null : exportEndpoint
					.getEndpointDescription();
		}

		public void close() {
			boolean closed = false;
			Throwable t = null;
			org.osgi.service.remoteserviceadmin.ExportReference exportReference = null;
			EndpointDescription endpointDescription = null;
			synchronized (this) {
				if (exportEndpoint != null) {
					t = getException();
					exportReference = (t == null) ? getExportReference() : null;
					endpointDescription = getEndpointDescription();
					closed = exportEndpoint.close(this);
					exportEndpoint = null;
				}
			}
			if (closed) {
				removeExportRegistration(this);
				publishEvent(
						new RemoteServiceAdminEvent(
								endpointDescription.getContainerID(),
								RemoteServiceAdminEvent.EXPORT_UNREGISTRATION,
								getClientBundle(), exportReference, t),
						endpointDescription);
			}
		}

		public synchronized Throwable getException() {
			return (exportEndpoint == null) ? null : exportEndpoint
					.getException();
		}

		public synchronized String toString() {
			return "ExportRegistration[exportEndpoint=" + exportEndpoint + "]"; //$NON-NLS-1$ //$NON-NLS-2$
		}

	}

	class ExportReference implements
			org.osgi.service.remoteserviceadmin.ExportReference {

		private ServiceReference serviceReference;
		private EndpointDescription endpointDescription;

		ExportReference(ServiceReference serviceReference,
				EndpointDescription endpointDescription) {
			this.serviceReference = serviceReference;
			this.endpointDescription = endpointDescription;
		}

		public synchronized ServiceReference getExportedService() {
			return serviceReference;
		}

		public synchronized org.osgi.service.remoteserviceadmin.EndpointDescription getExportedEndpoint() {
			return endpointDescription;
		}

		synchronized void close() {
			this.serviceReference = null;
			this.endpointDescription = null;
		}

		public synchronized String toString() {
			return "ExportReference[serviceReference=" + serviceReference //$NON-NLS-1$
					+ ", endpointDescription=" + endpointDescription + "]"; //$NON-NLS-1$ //$NON-NLS-2$
		}

	}

	class ImportEndpoint {

		private IRemoteServiceContainerAdapter rsContainerAdapter;
		private EndpointDescription endpointDescription;
		private IRemoteServiceListener rsListener;
		private IRemoteServiceReference rsReference;
		private ServiceRegistration proxyRegistration;
		private ImportReference importReference;
		private Set<ImportRegistration> importRegistrations = new HashSet<ImportRegistration>();

		private Throwable exception;

		ImportEndpoint(IRemoteServiceContainerAdapter rsContainerAdapter,
				IRemoteServiceReference rsReference,
				IRemoteServiceListener rsListener,
				ServiceRegistration proxyRegistration,
				EndpointDescription endpointDescription) {
			this.rsContainerAdapter = rsContainerAdapter;
			this.endpointDescription = endpointDescription;
			this.rsReference = rsReference;
			this.rsListener = rsListener;
			this.proxyRegistration = proxyRegistration;
			this.importReference = new ImportReference(
					proxyRegistration.getReference(), endpointDescription);
			// Add the remoteservice listener to the container adapter, so that
			// the
			// rsListener
			// notified asynchronously if our underlying remote service
			// reference is
			// unregistered locally
			// due to disconnect or remote ejection
			this.rsContainerAdapter.addRemoteServiceListener(this.rsListener);
		}

		ImportEndpoint(IRemoteServiceContainerAdapter rsContainerAdapter,
				EndpointDescription endpointDescription, Throwable t) {
			this.rsContainerAdapter = rsContainerAdapter;
			this.endpointDescription = endpointDescription;
			this.exception = t;
		}

		synchronized EndpointDescription getEndpointDescription() {
			return endpointDescription;
		}

		synchronized Throwable getException() {
			return exception;
		}

		synchronized ID getContainerID() {
			return (rsReference == null) ? null : rsReference.getContainerID();
		}

		synchronized boolean add(ImportRegistration importRegistration) {
			return this.importRegistrations.add(importRegistration);
		}

		synchronized boolean close(ImportRegistration importRegistration) {
			boolean removed = this.importRegistrations
					.remove(importRegistration);
			if (removed && importRegistrations.size() == 0) {
				if (proxyRegistration != null) {
					proxyRegistration.unregister();
					proxyRegistration = null;
				}
				if (rsContainerAdapter != null) {
					if (rsReference != null) {
						rsContainerAdapter.ungetRemoteService(rsReference);
						rsReference = null;
					}
					// remove remote service listener
					if (rsListener != null) {
						rsContainerAdapter
								.removeRemoteServiceListener(rsListener);
						rsListener = null;
					}
					rsContainerAdapter = null;
				}
				if (importReference != null) {
					importReference.close();
					importReference = null;
				}
			}
			return removed;
		}

		synchronized ImportReference getImportReference() {
			return importReference;
		}

		synchronized boolean match(IRemoteServiceID remoteServiceID) {
			if (remoteServiceID == null || rsReference == null)
				return false;
			return rsReference.getID().equals(remoteServiceID);
		}

		public synchronized String toString() {
			return "ImportEndpoint[rsReference=" + rsReference //$NON-NLS-1$
					+ ", proxyRegistration=" + proxyRegistration //$NON-NLS-1$
					+ ", importReference=" + importReference + "]"; //$NON-NLS-1$ //$NON-NLS-2$
		}

		synchronized boolean match(EndpointDescription ed) {
			if (importReference == null)
				return false;
			EndpointDescription importedEndpoint = (EndpointDescription) importReference
					.getImportedEndpoint();
			if (importedEndpoint == null)
				return false;
			return importedEndpoint.isSameService(ed);
		}

	}

	class ImportRegistration implements
			org.osgi.service.remoteserviceadmin.ImportRegistration {

		private ImportEndpoint importEndpoint;

		ImportRegistration(ImportEndpoint importEndpoint) {
			Assert.isNotNull(importEndpoint);
			this.importEndpoint = importEndpoint;
			this.importEndpoint.add(this);
		}

		synchronized ID getContainerID() {
			return importEndpoint == null ? null : importEndpoint
					.getContainerID();
		}

		synchronized EndpointDescription getEndpointDescription() {
			return (importEndpoint == null) ? null : importEndpoint
					.getEndpointDescription();
		}

		synchronized boolean match(IRemoteServiceID remoteServiceID) {
			if (importEndpoint == null)
				return false;
			return importEndpoint.match(remoteServiceID);
		}

		synchronized ImportEndpoint getImportEndpoint(EndpointDescription ed) {
			if (importEndpoint == null)
				return null;
			if (importEndpoint.match(ed))
				return importEndpoint;
			return null;
		}

		public synchronized org.osgi.service.remoteserviceadmin.ImportReference getImportReference() {
			Throwable t = getException();
			if (t != null)
				throw new IllegalStateException(
						"Cannot get import reference as registration not properly initialized", //$NON-NLS-1$
						t);
			return importEndpoint == null ? null : importEndpoint
					.getImportReference();
		}

		public void close() {
			boolean closed = false;
			org.osgi.service.remoteserviceadmin.ImportReference importReference = null;
			EndpointDescription endpointDescription = null;
			Throwable t = null;
			synchronized (this) {
				if (importEndpoint != null) {
					t = getException();
					importReference = (t == null) ? getImportReference() : null;
					endpointDescription = getEndpointDescription();
					closed = importEndpoint.close(this);
					importEndpoint = null;
				}
			}
			if (closed) {
				removeImportRegistration(this);
				publishEvent(
						new RemoteServiceAdminEvent(
								endpointDescription.getContainerID(),
								RemoteServiceAdminEvent.IMPORT_UNREGISTRATION,
								getClientBundle(), importReference, t),
						endpointDescription);
			}
		}

		public synchronized Throwable getException() {
			return (importEndpoint == null) ? null : importEndpoint
					.getException();
		}

		public synchronized String toString() {
			return "ImportRegistration[importEndpoint=" + importEndpoint + "]"; //$NON-NLS-1$ //$NON-NLS-2$
		}

	}

	class ImportReference implements
			org.osgi.service.remoteserviceadmin.ImportReference {

		private ServiceReference importedServiceReference;
		private EndpointDescription endpointDescription;

		ImportReference(ServiceReference serviceReference,
				EndpointDescription endpointDescription) {
			this.importedServiceReference = serviceReference;
			this.endpointDescription = endpointDescription;
		}

		public synchronized ServiceReference getImportedService() {
			return importedServiceReference;
		}

		public synchronized org.osgi.service.remoteserviceadmin.EndpointDescription getImportedEndpoint() {
			return endpointDescription;
		}

		synchronized void close() {
			this.importedServiceReference = null;
			this.endpointDescription = null;
		}

		public synchronized String toString() {
			return "ImportReference[importedServiceReference=" //$NON-NLS-1$
					+ importedServiceReference + ", endpointDescription=" //$NON-NLS-1$
					+ endpointDescription + "]"; //$NON-NLS-1$
		}

	}

	private void publishEvent(RemoteServiceAdminEvent event,
			EndpointDescription endpointDescription) {
		// send event synchronously to RemoteServiceAdminListeners
		EndpointPermission perm = new EndpointPermission(endpointDescription,
				Activator.getDefault().getFrameworkUUID(),
				EndpointPermission.READ);
		// notify synchronously all appropriate listeners (those with READ
		// permission)
		RemoteServiceAdminListener[] listeners = getListeners(perm);
		if (listeners != null)
			for (int i = 0; i < listeners.length; i++)
				listeners[i].remoteAdminEvent(event);
		// Now also post the event asynchronously to EventAdmin
		postEvent(event, endpointDescription);
	}

	private void postEvent(RemoteServiceAdminEvent event,
			EndpointDescription endpointDescription) {
		EventAdmin eventAdmin = getEventAdmin();
		if (eventAdmin == null) {
			logWarning("postEvent", "No event admin available to post event=" //$NON-NLS-1$ //$NON-NLS-2$
					+ event);
			return;
		}
		int eventType = event.getType();
		String eventTypeName = null;
		switch (eventType) {
		case (RemoteServiceAdminEvent.EXPORT_REGISTRATION):
			eventTypeName = "EXPORT_REGISTRATION"; //$NON-NLS-1$
			break;
		case (RemoteServiceAdminEvent.EXPORT_ERROR):
			eventTypeName = "EXPORT_ERROR"; //$NON-NLS-1$
			break;
		case (RemoteServiceAdminEvent.EXPORT_UNREGISTRATION):
			eventTypeName = "EXPORT_UNREGISTRATION"; //$NON-NLS-1$
			break;
		case (RemoteServiceAdminEvent.EXPORT_WARNING):
			eventTypeName = "EXPORT_WARNING"; //$NON-NLS-1$
			break;
		case (RemoteServiceAdminEvent.IMPORT_REGISTRATION):
			eventTypeName = "IMPORT_REGISTRATION"; //$NON-NLS-1$
			break;
		case (RemoteServiceAdminEvent.IMPORT_ERROR):
			eventTypeName = "IMPORT_ERROR"; //$NON-NLS-1$
			break;
		case (RemoteServiceAdminEvent.IMPORT_UNREGISTRATION):
			eventTypeName = "IMPORT_UNREGISTRATION"; //$NON-NLS-1$
			break;
		case (RemoteServiceAdminEvent.IMPORT_WARNING):
			eventTypeName = "IMPORT_WARNING"; //$NON-NLS-1$
			break;
		}
		if (eventTypeName == null)
			logError("postEvent", "Event type=" + eventType //$NON-NLS-1$ //$NON-NLS-2$
					+ " not understood for event=" + event + ".  Not posting"); //$NON-NLS-1$ //$NON-NLS-2$
		String topic = "org/osgi/service/remoteserviceadmin/" + eventTypeName; //$NON-NLS-1$
		Bundle rsaBundle = getClientBundle();
		Dictionary eventProperties = new Properties();
		eventProperties.put("clientBundle", rsaBundle); //$NON-NLS-1$
		eventProperties.put("clientBundle.id", //$NON-NLS-1$
				new Long(rsaBundle.getBundleId()));
		eventProperties.put("clientBundle.symbolicname", //$NON-NLS-1$
				rsaBundle.getSymbolicName());
		eventProperties.put("clientBundle.version", rsaBundle.getVersion()); //$NON-NLS-1$
		String[] signers = getSignersForBundle(clientBundle);
		if (signers != null && signers.length > 0)
			eventProperties.put("clientBundle.signer", signers); //$NON-NLS-1$
		Throwable t = event.getException();
		if (t != null)
			eventProperties.put("cause", t); //$NON-NLS-1$
		long serviceId = endpointDescription.getServiceId();
		if (serviceId != 0)
			eventProperties
					.put(org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_SERVICE_ID,
							new Long(serviceId));
		String frameworkUUID = endpointDescription.getFrameworkUUID();
		if (frameworkUUID != null)
			eventProperties
					.put(org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_FRAMEWORK_UUID,
							frameworkUUID);
		String endpointId = endpointDescription.getId();
		if (endpointId != null)
			eventProperties
					.put(org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_ID,
							endpointId);
		List<String> interfaces = endpointDescription.getInterfaces();
		if (interfaces != null && interfaces.size() > 0)
			eventProperties.put(org.osgi.framework.Constants.OBJECTCLASS,
					interfaces.toArray(new String[interfaces.size()]));
		List<String> importedConfigs = endpointDescription
				.getConfigurationTypes();
		if (importedConfigs != null && importedConfigs.size() > 0)
			eventProperties
					.put(org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_IMPORTED_CONFIGS,
							importedConfigs.toArray(new String[importedConfigs
									.size()]));
		eventProperties.put("timestamp", new Long(new Date().getTime())); //$NON-NLS-1$
		eventProperties.put("event", event); //$NON-NLS-1$
		postRemoteServiceAdminEvent(topic, eventProperties);

	}

	private String[] getSignersForBundle(Bundle bundle) {
		List<String> result = new ArrayList<String>();
		Map signers = bundle.getSignerCertificates(Bundle.SIGNERS_ALL);
		for (Iterator i = signers.keySet().iterator(); i.hasNext();)
			result.add(i.next().toString());
		return (String[]) result.toArray(new String[result.size()]);
	}

	private void publishExportEvent(ExportRegistration exportRegistration) {
		Throwable exception = exportRegistration.getException();
		org.osgi.service.remoteserviceadmin.ExportReference exportReference = (exception == null) ? exportRegistration
				.getExportReference() : null;
		RemoteServiceAdminEvent rsaEvent = new RemoteServiceAdminEvent(
				exportRegistration.getContainerID(),
				(exception == null) ? RemoteServiceAdminEvent.EXPORT_REGISTRATION
						: RemoteServiceAdminEvent.EXPORT_ERROR,
				getClientBundle(), exportReference, exception);
		publishEvent(rsaEvent, exportRegistration.getEndpointDescription());
	}

	private void publishImportEvent(ImportRegistration importRegistration) {
		Throwable exception = importRegistration.getException();
		org.osgi.service.remoteserviceadmin.ImportReference importReference = (exception == null) ? importRegistration
				.getImportReference() : null;
		RemoteServiceAdminEvent rsaEvent = new RemoteServiceAdminEvent(
				importRegistration.getContainerID(),
				(exception == null) ? RemoteServiceAdminEvent.IMPORT_REGISTRATION
						: RemoteServiceAdminEvent.IMPORT_ERROR,
				getClientBundle(), importReference, exception);
		publishEvent(rsaEvent, importRegistration.getEndpointDescription());
	}

	private void closeRemoteServiceAdminListenerTracker() {
		synchronized (remoteServiceAdminListenerTrackerLock) {
			if (remoteServiceAdminListenerTracker != null) {
				remoteServiceAdminListenerTracker.close();
				remoteServiceAdminListenerTracker = null;
			}
		}
	}

	private RemoteServiceAdminListener[] getListeners(EndpointPermission perm) {
		synchronized (remoteServiceAdminListenerTrackerLock) {
			if (remoteServiceAdminListenerTracker == null) {
				remoteServiceAdminListenerTracker = new ServiceTracker(
						getClientBundleContext(),
						RemoteServiceAdminListener.class.getName(), null);
				remoteServiceAdminListenerTracker.open(true);
			}
		}
		ServiceReference[] unfilteredRefs = remoteServiceAdminListenerTracker
				.getServiceReferences();
		if (unfilteredRefs == null)
			return null;
		// Filter by Bundle.hasPermission
		List<ServiceReference> filteredRefs = new ArrayList<ServiceReference>();
		for (ServiceReference ref : unfilteredRefs)
			if (perm == null || ref.getBundle().hasPermission(perm))
				filteredRefs.add(ref);
		List<RemoteServiceAdminListener> results = new ArrayList<RemoteServiceAdminListener>();
		for (ServiceReference ref : filteredRefs) {
			RemoteServiceAdminListener l = (RemoteServiceAdminListener) remoteServiceAdminListenerTracker
					.getService(ref);
			if (l != null)
				results.add(l);
		}
		return results.toArray(new RemoteServiceAdminListener[results.size()]);
	}

	private ExportEndpoint findExistingExportEndpoint(
			ServiceReference serviceReference, ID containerID) {
		for (ExportRegistration eReg : exportedRegistrations) {
			ExportEndpoint exportEndpoint = eReg.getExportEndpoint(
					serviceReference, containerID);
			if (exportEndpoint != null)
				return exportEndpoint;
		}
		return null;
	}

	private EventAdmin getEventAdmin() {
		synchronized (eventAdminTrackerLock) {
			eventAdminTracker = new ServiceTracker(getClientBundleContext(),
					EventAdmin.class.getName(), null);
			eventAdminTracker.open(true);
		}
		return (EventAdmin) eventAdminTracker.getService();
	}

	private void postRemoteServiceAdminEvent(String topic,
			Dictionary eventProperties) {
		EventAdmin eventAdmin = getEventAdmin();
		if (eventAdmin == null) {
			logError("postRemoteServiceAdminEvent", //$NON-NLS-1$
					"No EventAdmin service available to send eventTopic=" //$NON-NLS-1$
							+ topic + " eventProperties=" + eventProperties); //$NON-NLS-1$
			return;
		}
		eventAdmin.postEvent(new Event(topic, eventProperties));
	}

	private void closeEventAdminTracker() {
		synchronized (eventAdminTrackerLock) {
			if (eventAdminTracker != null) {
				eventAdminTracker.close();
				eventAdminTracker = null;
			}
		}
	}

	private void closePackageAdminTracker() {
		synchronized (packageAdminTrackerLock) {
			if (packageAdminTracker != null) {
				packageAdminTracker.close();
				packageAdminTracker = null;
			}
		}
	}

	private Object consumerContainerSelectorTrackerLock = new Object();
	private ServiceTracker consumerContainerSelectorTracker;

	private void closeConsumerContainerSelectorTracker() {
		synchronized (consumerContainerSelectorTrackerLock) {
			if (consumerContainerSelectorTracker != null) {
				consumerContainerSelectorTracker.close();
				consumerContainerSelectorTracker = null;
			}
		}
		if (defaultConsumerContainerSelector != null) {
			defaultConsumerContainerSelector.close();
			defaultConsumerContainerSelector = null;
		}
	}

	private Object hostContainerSelectorTrackerLock = new Object();
	private ServiceTracker hostContainerSelectorTracker;

	private void closeHostContainerSelectorTracker() {
		synchronized (hostContainerSelectorTrackerLock) {
			if (hostContainerSelectorTracker != null) {
				hostContainerSelectorTracker.close();
				hostContainerSelectorTracker = null;
			}
		}
		if (defaultHostContainerSelector != null) {
			defaultHostContainerSelector.close();
			defaultHostContainerSelector = null;
		}
	}

	protected IHostContainerSelector getHostContainerSelector() {
		synchronized (hostContainerSelectorTrackerLock) {
			if (hostContainerSelectorTracker == null) {
				hostContainerSelectorTracker = new ServiceTracker(
						getClientBundleContext(),
						IHostContainerSelector.class.getName(), null);
				hostContainerSelectorTracker.open();
			}
		}
		return (IHostContainerSelector) hostContainerSelectorTracker
				.getService();
	}

	protected IConsumerContainerSelector getConsumerContainerSelector() {
		synchronized (consumerContainerSelectorTrackerLock) {
			if (consumerContainerSelectorTracker == null) {
				consumerContainerSelectorTracker = new ServiceTracker(
						getClientBundleContext(),
						IConsumerContainerSelector.class.getName(), null);
				consumerContainerSelectorTracker.open();
			}
		}
		return (IConsumerContainerSelector) consumerContainerSelectorTracker
				.getService();
	}

	private Version getPackageVersion(ServiceReference serviceReference,
			String serviceInterface, String packageName) {
		Object service = getClientBundleContext().getService(serviceReference);
		if (service == null)
			return null;
		Class[] interfaceClasses = service.getClass().getInterfaces();
		if (interfaceClasses == null)
			return null;
		Class interfaceClass = null;
		for (int i = 0; i < interfaceClasses.length; i++) {
			if (interfaceClasses[i].getName().equals(serviceInterface))
				interfaceClass = interfaceClasses[i];
		}
		if (interfaceClass == null)
			return null;
		ExportedPackage exportedPackage = getExportedPackageForClass(
				getPackageAdmin(), interfaceClass);
		return (exportedPackage == null) ? null : exportedPackage.getVersion();
	}

	private Map<String, Object> createExportEndpointDescriptionProperties(
			ServiceReference serviceReference,
			Map<String, Object> overridingProperties,
			String[] exportedInterfaces, String[] serviceIntents,
			IRemoteServiceContainer rsContainer) {
		IContainer container = rsContainer.getContainer();
		ID containerID = container.getID();

		Map<String, Object> endpointDescriptionProperties = new TreeMap<String, Object>(
				String.CASE_INSENSITIVE_ORDER);

		// OSGi properties
		// OBJECTCLASS set to exportedInterfaces
		endpointDescriptionProperties.put(
				org.osgi.framework.Constants.OBJECTCLASS, exportedInterfaces);

		// Service interface versions
		for (int i = 0; i < exportedInterfaces.length; i++) {
			String packageName = getPackageName(exportedInterfaces[i]);
			String packageVersionKey = org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_PACKAGE_VERSION_
					+ packageName;
			// If it's pre-set...by registration or by overridingProperties,
			// then use that value
			String packageVersion = (String) PropertiesUtil.getPropertyValue(
					serviceReference, overridingProperties, packageVersionKey);
			if (packageVersion == null) {
				Version version = getPackageVersion(serviceReference,
						exportedInterfaces[i], packageName);
				if (version != null && !version.equals(Version.emptyVersion))
					packageVersion = version.toString();
			}
			// Only set the package version if we have a non-null value
			if (packageVersion != null)
				endpointDescriptionProperties.put(packageVersionKey,
						packageVersion);
		}

		// ENDPOINT_ID
		String endpointId = (String) PropertiesUtil
				.getPropertyValue(
						serviceReference,
						overridingProperties,
						org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_ID);
		if (endpointId == null)
			endpointId = containerID.getName();
		endpointDescriptionProperties
				.put(org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_ID,
						endpointId);

		// ENDPOINT_SERVICE_ID
		// This is always set to the value from serviceReference as per 122.5.1
		Long serviceId = (Long) serviceReference
				.getProperty(org.osgi.framework.Constants.SERVICE_ID);
		endpointDescriptionProperties.put(
				org.osgi.framework.Constants.SERVICE_ID, serviceId);

		// ENDPOINT_FRAMEWORK_ID
		String frameworkId = (String) PropertiesUtil
				.getPropertyValue(
						serviceReference,
						overridingProperties,
						org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_FRAMEWORK_UUID);
		if (frameworkId == null)
			frameworkId = Activator.getDefault().getFrameworkUUID();
		endpointDescriptionProperties
				.put(org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_FRAMEWORK_UUID,
						frameworkId);

		// REMOTE_CONFIGS_SUPPORTED
		String[] remoteConfigsSupported = getSupportedConfigs(container);
		if (remoteConfigsSupported != null)
			endpointDescriptionProperties
					.put(org.osgi.service.remoteserviceadmin.RemoteConstants.REMOTE_CONFIGS_SUPPORTED,
							remoteConfigsSupported);
		// SERVICE_IMPORTED_CONFIGS...set to same value as remote configs
		// supported (which is computed
		// for the exporting ECF container
		endpointDescriptionProperties
				.put(org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_IMPORTED_CONFIGS,
						remoteConfigsSupported);

		// SERVICE_INTENTS
		String[] intents = (String[]) PropertiesUtil
				.getPropertyValue(
						null,
						overridingProperties,
						org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_INTENTS);
		if (intents == null)
			intents = serviceIntents;
		if (intents != null)
			endpointDescriptionProperties
					.put(org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_INTENTS,
							intents);

		// REMOTE_INTENTS_SUPPORTED
		String[] remoteIntentsSupported = getSupportedIntents(container);
		if (remoteIntentsSupported != null)
			endpointDescriptionProperties
					.put(org.osgi.service.remoteserviceadmin.RemoteConstants.REMOTE_INTENTS_SUPPORTED,
							remoteIntentsSupported);

		// ECF properties
		// ID namespace
		String idNamespace = containerID.getNamespace().getName();
		endpointDescriptionProperties.put(
				RemoteConstants.ENDPOINT_CONTAINER_ID_NAMESPACE, idNamespace);

		// ENDPOINT_CONNECTTARGET_ID
		String connectTarget = (String) PropertiesUtil.getPropertyValue(
				serviceReference, overridingProperties,
				RemoteConstants.ENDPOINT_CONNECTTARGET_ID);
		if (connectTarget == null) {
			ID connectedID = rsContainer.getContainer().getConnectedID();
			if (connectedID != null && !connectedID.equals(containerID))
				connectTarget = connectedID.getName();
		}
		if (connectTarget != null)
			endpointDescriptionProperties.put(
					RemoteConstants.ENDPOINT_CONNECTTARGET_ID, connectTarget);

		// ENDPOINT_IDFILTER_IDS
		String[] idFilter = (String[]) PropertiesUtil.getPropertyValue(
				serviceReference, overridingProperties,
				RemoteConstants.ENDPOINT_IDFILTER_IDS);
		if (idFilter != null && idFilter.length > 0)
			endpointDescriptionProperties.put(
					RemoteConstants.ENDPOINT_IDFILTER_IDS, idFilter);

		// ENDPOINT_REMOTESERVICE_FILTER
		String rsFilter = (String) PropertiesUtil.getPropertyValue(
				serviceReference, overridingProperties,
				RemoteConstants.ENDPOINT_REMOTESERVICE_FILTER);
		if (rsFilter != null)
			endpointDescriptionProperties.put(
					RemoteConstants.ENDPOINT_REMOTESERVICE_FILTER, rsFilter);

		return endpointDescriptionProperties;

	}

	private Map<String, Object> copyNonReservedProperties(
			ServiceReference serviceReference,
			Map<String, Object> overridingProperties, Map<String, Object> target) {
		// copy all other properties...from service reference
		PropertiesUtil.copyNonReservedProperties(serviceReference, target);
		// And override with overridingProperties
		PropertiesUtil.copyNonReservedProperties(overridingProperties, target);
		return target;
	}

	private ContainerTypeDescription getContainerTypeDescription(
			IContainer container) {
		IContainerManager containerManager = Activator.getDefault()
				.getContainerManager();
		if (containerManager == null)
			return null;
		return containerManager.getContainerTypeDescription(container.getID());
	}

	private String[] getSupportedConfigs(IContainer container) {
		ContainerTypeDescription ctd = getContainerTypeDescription(container);
		return (ctd == null) ? null : ctd.getSupportedConfigs();
	}

	private String[] getImportedConfigs(IContainer container,
			String[] exporterSupportedConfigs) {
		ContainerTypeDescription ctd = getContainerTypeDescription(container);
		return (ctd == null) ? null : ctd
				.getImportedConfigs(exporterSupportedConfigs);
	}

	private String[] getSupportedIntents(IContainer container) {
		ContainerTypeDescription ctd = getContainerTypeDescription(container);
		return (ctd == null) ? null : ctd.getSupportedIntents();
	}

	private ID[] getIDFilter(EndpointDescription endpointDescription,
			ID endpointID) {
		ID[] idFilter = endpointDescription.getIDFilter();
		// If it is null,
		return (idFilter == null) ? new ID[] { endpointID } : idFilter;
	}

	private String getRemoteServiceFilter(
			EndpointDescription endpointDescription) {

		long rsId = 0;
		// if the ECF remote service id is present in properties, allow it to
		// override
		Long l = (Long) endpointDescription.getProperties().get(
				org.eclipse.ecf.remoteservice.Constants.SERVICE_ID);
		if (l != null)
			rsId = l.longValue();
		// if rsId is still zero, use the endpoint.service.id from
		// endpoint description
		if (rsId == 0)
			rsId = endpointDescription.getServiceId();
		// If it's *still* zero, then just use the raw filter
		if (rsId == 0) {
			// It's not known...so we just return the 'raw' remote service
			// filter
			return endpointDescription.getRemoteServiceFilter();
		} else {
			String edRsFilter = endpointDescription.getRemoteServiceFilter();
			// It's a real remote service id...so we return
			StringBuffer result = new StringBuffer("(&(") //$NON-NLS-1$
					.append(org.eclipse.ecf.remoteservice.Constants.SERVICE_ID)
					.append("=").append(rsId).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
			if (edRsFilter != null)
				result.append(edRsFilter);
			result.append(")"); //$NON-NLS-1$
			return result.toString();
		}
	}

	private org.osgi.service.remoteserviceadmin.ImportRegistration handleNonOSGiService(
			org.osgi.service.remoteserviceadmin.EndpointDescription endpointDescription) {
		// With non-OSGi service id (service id=0), we log a warning and return
		// null;
		logWarning("handleNonOSGiService", //$NON-NLS-1$
				"OSGi remote service id is 0 for endpointDescription=" //$NON-NLS-1$
						+ endpointDescription);
		return null;
	}

	private ImportEndpoint createAndRegisterProxy(
			EndpointDescription endpointDescription,
			IRemoteServiceContainer rsContainer,
			IRemoteServiceReference selectedRsReference) throws Exception {

		IRemoteServiceContainerAdapter containerAdapter = rsContainer
				.getContainerAdapter();
		ID rsContainerID = rsContainer.getContainer().getID();
		// First get IRemoteService for selectedRsReference
		IRemoteService rs = containerAdapter
				.getRemoteService(selectedRsReference);
		if (rs == null)
			throw new NullPointerException(
					"getRemoteService returned null for selectedRsReference=" //$NON-NLS-1$
							+ selectedRsReference + ",rsContainerID=" //$NON-NLS-1$
							+ rsContainerID);

		Map proxyProperties = createProxyProperties(endpointDescription,
				rsContainer, selectedRsReference, rs);

		List<String> interfaces = endpointDescription.getInterfaces();

		ServiceRegistration proxyRegistration = getClientBundleContext()
				.registerService(
						(String[]) interfaces.toArray(new String[interfaces
								.size()]),
						createProxyServiceFactory(endpointDescription, rs),
						(Dictionary) PropertiesUtil
								.createDictionaryFromMap(proxyProperties));

		return new ImportEndpoint(containerAdapter, selectedRsReference,
				new RemoteServiceListener(), proxyRegistration,
				endpointDescription);
	}

	private ServiceFactory createProxyServiceFactory(
			EndpointDescription endpointDescription,
			IRemoteService remoteService) {
		return new ProxyServiceFactory(
				endpointDescription.getInterfaceVersions(), remoteService);
	}

	private Collection<Class> loadServiceInterfacesViaBundle(Bundle bundle,
			String[] interfaces) {
		List<Class> result = new ArrayList<Class>();
		for (int i = 0; i < interfaces.length; i++) {
			try {
				result.add(bundle.loadClass(interfaces[i]));
			} catch (ClassNotFoundException e) {
				logError("loadInterfacesViaBundle", "interface=" //$NON-NLS-1$ //$NON-NLS-2$
						+ interfaces[i] + " cannot be loaded by clientBundle=" //$NON-NLS-1$
						+ bundle.getSymbolicName(), e);
				continue;
			} catch (IllegalStateException e) {
				logError(
						"loadInterfacesViaBundle", //$NON-NLS-1$
						"interface=" //$NON-NLS-1$
								+ interfaces[i]
								+ " cannot be loaded since clientBundle is in illegal state", //$NON-NLS-1$
						e);
				continue;
			}
		}
		return result;
	}

	class ProxyServiceFactory implements ServiceFactory {
		private IRemoteService remoteService;
		private Map<String, Version> interfaceVersions;

		public ProxyServiceFactory(Map<String, Version> interfaceVersions,
				IRemoteService remoteService) {
			this.interfaceVersions = interfaceVersions;
			this.remoteService = remoteService;
		}

		public Object getService(Bundle bundle, ServiceRegistration registration) {
			return createProxy(bundle, registration.getReference(),
					remoteService, interfaceVersions);
		}

		public void ungetService(Bundle bundle,
				ServiceRegistration registration, Object service) {
			ungetProxyClassLoader(bundle);
			this.remoteService = null;
			this.interfaceVersions = null;
		}
	}

	private Object createProxy(Bundle requestingBundle,
			ServiceReference serviceReference, IRemoteService remoteService,
			Map<String, Version> interfaceVersions) {
		// Get symbolicName once for possible use below
		String bundleSymbolicName = requestingBundle.getSymbolicName();
		// Get String[] via OBJECTCLASS constant property
		String[] serviceClassnames = (String[]) serviceReference
				.getProperty(org.osgi.framework.Constants.OBJECTCLASS);
		// Load as many of the serviceInterface classes as possible
		Collection<Class> serviceInterfaceClasses = loadServiceInterfacesViaBundle(
				requestingBundle, serviceClassnames);
		// There has to be at least one serviceInterface that the clientBundle
		// can
		// load...otherwise the service can't be accessed
		if (serviceInterfaceClasses.size() < 1)
			throw new RuntimeException(
					"ProxyServiceFactory cannot load any serviceInterfaces=" //$NON-NLS-1$
							+ serviceInterfaceClasses
							+ " for serviceReference=" + serviceReference //$NON-NLS-1$
							+ " via clientBundle=" + bundleSymbolicName); //$NON-NLS-1$

		// Now verify that the classes are of valid versions
		verifyServiceInterfaceVersionsForProxy(requestingBundle,
				serviceInterfaceClasses, interfaceVersions);

		// Now create/get class loader for proxy. This will typically
		// be an instance of ProxyClassLoader
		ClassLoader cl = getProxyClassLoader(requestingBundle);
		try {
			return remoteService.getProxy(cl, (Class[]) serviceInterfaceClasses
					.toArray(new Class[serviceInterfaceClasses.size()]));
		} catch (ECFException e) {
			throw new ServiceException(
					"ProxyServiceFactory cannot create proxy for clientBundle=" //$NON-NLS-1$
							+ bundleSymbolicName + " from serviceReference=" //$NON-NLS-1$
							+ serviceReference, e);
		}

	}

	private Map<Bundle, ProxyClassLoader> proxyClassLoaders = new HashMap<Bundle, ProxyClassLoader>();

	private void closeProxyClassLoaderCache() {
		synchronized (proxyClassLoaders) {
			proxyClassLoaders.clear();
		}
	}

	private ClassLoader getProxyClassLoader(Bundle bundle) {
		ProxyClassLoader proxyClassLoaderForBundle = null;
		synchronized (proxyClassLoaders) {
			proxyClassLoaderForBundle = proxyClassLoaders.get(bundle);
			if (proxyClassLoaderForBundle == null) {
				proxyClassLoaderForBundle = new ProxyClassLoader(bundle);
				proxyClassLoaders.put(bundle, proxyClassLoaderForBundle);
			} else
				proxyClassLoaderForBundle.addServiceUseCount();
		}
		return proxyClassLoaderForBundle;
	}

	private void ungetProxyClassLoader(Bundle bundle) {
		synchronized (proxyClassLoaders) {
			ProxyClassLoader proxyClassLoaderForBundle = proxyClassLoaders
					.get(bundle);
			if (proxyClassLoaderForBundle != null) {
				int useCount = proxyClassLoaderForBundle.getServiceUseCount();
				if (useCount == 0)
					proxyClassLoaders.remove(bundle);
				else
					proxyClassLoaderForBundle.removeServiceUseCount();
			}
		}
	}

	protected class ProxyClassLoader extends ClassLoader {
		private Bundle loadingBundle;
		private int serviceUseCount = 0;

		public ProxyClassLoader(Bundle loadingBundle) {
			this.loadingBundle = loadingBundle;
		}

		public Class loadClass(String name) throws ClassNotFoundException {
			return loadingBundle.loadClass(name);
		}

		public int getServiceUseCount() {
			return serviceUseCount;
		}

		public void addServiceUseCount() {
			serviceUseCount++;
		}

		public void removeServiceUseCount() {
			serviceUseCount--;
		}
	}

	private PackageAdmin getPackageAdmin() {
		synchronized (packageAdminTrackerLock) {
			if (packageAdminTracker == null) {
				packageAdminTracker = new ServiceTracker(
						getClientBundleContext(), PackageAdmin.class.getName(),
						null);
				packageAdminTracker.open();
			}
		}
		return (PackageAdmin) packageAdminTracker.getService();
	}

	private ExportedPackage getExportedPackageForClass(
			PackageAdmin packageAdmin, Class clazz) {
		String packageName = getPackageName(clazz.getName());
		// Get all exported packages with given package name
		ExportedPackage[] exportedPackagesWithName = packageAdmin
				.getExportedPackages(packageName);
		// If none then we return null
		if (exportedPackagesWithName == null)
			return null;
		// Get the clientBundle for the previously loaded interface class
		Bundle classBundle = packageAdmin.getBundle(clazz);
		if (classBundle == null)
			return null;
		for (int i = 0; i < exportedPackagesWithName.length; i++) {
			Bundle packageBundle = exportedPackagesWithName[i]
					.getExportingBundle();
			if (packageBundle == null)
				continue;
			if (packageBundle.equals(classBundle))
				return exportedPackagesWithName[i];
		}
		return null;
	}

	private String getPackageName(String className) {
		int lastDotIndex = className.lastIndexOf("."); //$NON-NLS-1$
		if (lastDotIndex == -1)
			return ""; //$NON-NLS-1$
		return className.substring(0, lastDotIndex);
	}

	private void comparePackageVersions(String packageName,
			Version remoteVersion, Version localVersion)
			throws RuntimeException {
		
		if (remoteVersion == null)
			throw new NullPointerException("Remote package=" + packageName //$NON-NLS-1$
					+ " has no Version"); //$NON-NLS-1$
		if (localVersion == null)
			throw new NullPointerException("Local package=" + packageName //$NON-NLS-1$
					+ " has no Version"); //$NON-NLS-1$

		LogUtility.trace(
				"comparePackageVersions", //$NON-NLS-1$
				DebugOptions.PACKAGE_VERSION_COMPARATOR, this.getClass(),
				"packageName=" + packageName + ",remoteVersion=" //$NON-NLS-1$ //$NON-NLS-2$
						+ remoteVersion + ",localVersion=" + localVersion); //$NON-NLS-1$
		// By default we do strict comparison of remote with local...they must
		// be exactly the same, or we thrown a runtime exception
		int compareResult = localVersion.compareTo(remoteVersion);
		// Now check compare result, and throw exception to fail compare
		if (compareResult != 0)
			throw new RuntimeException(
					"Package version compare failed with compareResult=" //$NON-NLS-1$
							+ compareResult + " for package=" + packageName //$NON-NLS-1$
							+ " localVersion=" + localVersion //$NON-NLS-1$
							+ " remoteVersion=" + remoteVersion); //$NON-NLS-1$
	}
	
	private void verifyServiceInterfaceVersionsForProxy(Bundle bundle,
			Collection<Class> classes, Map<String, Version> interfaceVersions) {
		// For all service interface classes
		for (Class clazz : classes) {
			String className = clazz.getName();
			String packageName = getPackageName(className);
			ExportedPackage exportedPackage = getExportedPackageForClass(
					getPackageAdmin(), clazz);
			if (exportedPackage == null)
				throw new NullPointerException(
						"No exported package found for class=" + className); //$NON-NLS-1$
			// Now do compare via package version comparator service
			comparePackageVersions(packageName,
					interfaceVersions.get(className), exportedPackage.getVersion());
		}
	}

	private IRemoteServiceReference selectRemoteServiceReference(
			Collection<IRemoteServiceReference> rsRefs, ID targetID,
			ID[] idFilter, Collection<String> interfaces, String rsFilter,
			IRemoteServiceContainer rsContainer) {
		if (rsRefs.size() == 0)
			return null;
		if (rsRefs.size() > 1) {
			logWarning("selectRemoteServiceReference", "rsRefs=" + rsRefs //$NON-NLS-1$ //$NON-NLS-2$
					+ ",targetID=" + targetID + ",idFilter=" + idFilter //$NON-NLS-1$ //$NON-NLS-2$
					+ ",interfaces=" + interfaces + ",rsFilter=" + rsFilter //$NON-NLS-1$ //$NON-NLS-2$
					+ ",rsContainer=" + rsContainer.getContainer().getID() //$NON-NLS-1$
					+ " has " + rsRefs.size() //$NON-NLS-1$
					+ " values.  Selecting the first element"); //$NON-NLS-1$
		}
		return rsRefs.iterator().next();
	}

	private Map createProxyProperties(EndpointDescription endpointDescription,
			IRemoteServiceContainer rsContainer,
			IRemoteServiceReference rsReference, IRemoteService remoteService) {

		Map resultProperties = new TreeMap<String, Object>(
				String.CASE_INSENSITIVE_ORDER);
		PropertiesUtil.copyNonReservedProperties(rsReference, resultProperties);
		// remove OBJECTCLASS
		resultProperties
				.remove(org.eclipse.ecf.remoteservice.Constants.OBJECTCLASS);
		// remove remote service id
		resultProperties
				.remove(org.eclipse.ecf.remoteservice.Constants.SERVICE_ID);
		// Set intents if there are intents
		Object intentsValue = PropertiesUtil
				.convertToStringPlusValue(endpointDescription.getIntents());
		if (intentsValue != null)
			resultProperties
					.put(org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_INTENTS,
							intentsValue);

		// Set service.imported to IRemoteService unless
		// SERVICE_IMPORTED_VALUETYPE is
		// set
		String serviceImportedType = (String) endpointDescription
				.getProperties()
				.get(org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteConstants.SERVICE_IMPORTED_VALUETYPE);
		if (serviceImportedType == null
				|| serviceImportedType.equals(IRemoteService.class.getName()))
			resultProperties
					.put(org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_IMPORTED,
							remoteService);
		else
			resultProperties
					.put(org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_IMPORTED,
							new Boolean(true));

		String[] exporterSupportedConfigs = (String[]) endpointDescription
				.getProperties()
				.get(org.osgi.service.remoteserviceadmin.RemoteConstants.REMOTE_CONFIGS_SUPPORTED);
		String[] importedConfigs = getImportedConfigs(
				rsContainer.getContainer(), exporterSupportedConfigs);
		// Set service.imported.configs
		resultProperties
				.put(org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_IMPORTED_CONFIGS,
						importedConfigs);
		return resultProperties;
	}

	private ExportEndpoint exportService(ServiceReference serviceReference,
			Map<String, Object> overridingProperties,
			String[] exportedInterfaces, String[] serviceIntents,
			IRemoteServiceContainer rsContainer) {

		Map endpointDescriptionProperties = createExportEndpointDescriptionProperties(
				serviceReference, overridingProperties, exportedInterfaces,
				serviceIntents, rsContainer);

		// Create remote service properties
		Map remoteServiceProperties = copyNonReservedProperties(
				serviceReference, overridingProperties,
				new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER));

		IRemoteServiceContainerAdapter containerAdapter = rsContainer
				.getContainerAdapter();

		// Register remote service via ECF container adapter to create
		// remote service registration
		IRemoteServiceRegistration remoteRegistration = null;
		Throwable exception = null;
		try {
			// Check security access for export
			checkEndpointPermission(new EndpointDescription(serviceReference,
					endpointDescriptionProperties), EndpointPermission.EXPORT);

			if (containerAdapter instanceof IOSGiRemoteServiceContainerAdapter) {
				IOSGiRemoteServiceContainerAdapter osgiContainerAdapter = (IOSGiRemoteServiceContainerAdapter) containerAdapter;
				remoteRegistration = osgiContainerAdapter
						.registerRemoteService(
								exportedInterfaces,
								serviceReference,
								PropertiesUtil
										.createDictionaryFromMap(remoteServiceProperties));
			} else
				remoteRegistration = containerAdapter
						.registerRemoteService(
								exportedInterfaces,
								getClientBundleContext().getService(
										serviceReference),
								PropertiesUtil
										.createDictionaryFromMap(remoteServiceProperties));
			endpointDescriptionProperties
					.put(org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_SERVICE_ID,
							remoteRegistration
									.getProperty(org.eclipse.ecf.remoteservice.Constants.SERVICE_ID));
		} catch (Exception e) {
			exception = e;
			if (remoteRegistration != null)
				remoteRegistration.unregister();
		}
		EndpointDescription endpointDescription = new EndpointDescription(
				serviceReference, endpointDescriptionProperties);
		// Create ExportEndpoint/ExportRegistration
		return (exception == null) ? new ExportEndpoint(serviceReference,
				endpointDescription, remoteRegistration) : new ExportEndpoint(
				serviceReference, endpointDescription, exception);
	}

	private ImportEndpoint importService(
			EndpointDescription endpointDescription,
			IRemoteServiceContainer rsContainer) {
		trace("doImportService", "endpointDescription=" + endpointDescription //$NON-NLS-1$ //$NON-NLS-2$
				+ ",rsContainerID=" + rsContainer.getContainer().getID()); //$NON-NLS-1$
		// Get interfaces from endpoint description
		Collection<String> interfaces = endpointDescription.getInterfaces();
		Assert.isNotNull(interfaces);
		Assert.isTrue(interfaces.size() > 0);
		// Get ECF endpoint ID...if this throws IDCreateException (because the
		// local system does not have
		// namespace for creating ID, or no namespace is present in
		// endpointDescription or endpoint id,
		// then it will be caught by the caller
		ID endpointContainerID = endpointDescription.getContainerID();
		Assert.isNotNull(endpointContainerID);
		// Get connect target ID. May be null
		ID targetID = endpointDescription.getConnectTargetID();
		if (targetID == null)
			targetID = endpointContainerID;
		// Get idFilter...also may be null
		ID[] idFilter = getIDFilter(endpointDescription, endpointContainerID);
		// Get remote service filter
		String rsFilter = getRemoteServiceFilter(endpointDescription);
		// IRemoteServiceReferences from query
		Collection<IRemoteServiceReference> rsRefs = new ArrayList<IRemoteServiceReference>();
		// Get IRemoteServiceContainerAdapter
		IRemoteServiceContainerAdapter containerAdapter = rsContainer
				.getContainerAdapter();
		// rsContainerID
		ID rsContainerID = rsContainer.getContainer().getID();
		try {
			// Get first interface name for service reference
			// lookup
			String intf = interfaces.iterator().next();
			// Get/lookup remote service references
			IRemoteServiceReference[] refs = containerAdapter
					.getRemoteServiceReferences(targetID, idFilter, intf,
							rsFilter);
			if (refs == null) {
				logWarning("doImportService", //$NON-NLS-1$
						"getRemoteServiceReferences return null for targetID=" //$NON-NLS-1$
								+ targetID + ",idFilter=" + idFilter //$NON-NLS-1$
								+ ",intf=" + intf + ",rsFilter=" + rsFilter //$NON-NLS-1$ //$NON-NLS-2$
								+ " on rsContainerID=" + rsContainerID); //$NON-NLS-1$
			} else
				for (int i = 0; i < refs.length; i++)
					rsRefs.add(refs[i]);
			// If there are several refs resulting (should not be)
			// we select the one to use
			IRemoteServiceReference selectedRsReference = selectRemoteServiceReference(
					rsRefs, targetID, idFilter, interfaces, rsFilter,
					rsContainer);
			// If none found, we obviously can't continue
			if (selectedRsReference == null)
				throw new RemoteReferenceNotFoundException(targetID, idFilter,
						interfaces, rsFilter);

			return createAndRegisterProxy(endpointDescription, rsContainer,
					selectedRsReference);
		} catch (Exception e) {
			logError(
					"importService", "selectRemoteServiceReference returned null for rsRefs=" //$NON-NLS-1$
							+ rsRefs + ",targetID=" + targetID //$NON-NLS-1$
							+ ",idFilter=" + idFilter + ",interfaces=" //$NON-NLS-1$ //$NON-NLS-2$
							+ interfaces + ",rsFilter=" + rsFilter //$NON-NLS-1$
							+ ",rsContainerID=" + rsContainerID, e);
			return new ImportEndpoint(containerAdapter, endpointDescription, e);
		}
	}

	private void closeExportRegistrations() {
		List<ExportRegistration> toClose = null;
		synchronized (exportedRegistrations) {
			toClose = new ArrayList<ExportRegistration>(exportedRegistrations);
			exportedRegistrations.clear();
		}
		for (ExportRegistration reg : toClose)
			reg.close();
	}

	private void closeImportRegistrations() {
		List<ImportRegistration> toClose = null;
		synchronized (importedRegistrations) {
			toClose = new ArrayList<ImportRegistration>(importedRegistrations);
			importedRegistrations.clear();
		}
		for (ImportRegistration reg : toClose)
			reg.close();
	}

	public void close() {
		trace("close", "closing importedRegistrations=" + importedRegistrations //$NON-NLS-1$ //$NON-NLS-2$
				+ " exportedRegistrations=" + exportedRegistrations); //$NON-NLS-1$
		closeRemoteServiceAdminListenerTracker();
		closeEventAdminTracker();
		closePackageAdminTracker();
		closeProxyClassLoaderCache();
		closeConsumerContainerSelectorTracker();
		closeHostContainerSelectorTracker();
		closeDefaultContainerSelectors();
		closeImportRegistrations();
		closeExportRegistrations();
		this.clientBundle = null;
	}

	private ImportEndpoint findImportEndpoint(EndpointDescription ed) {
		for (ImportRegistration reg : importedRegistrations) {
			ImportEndpoint endpoint = reg.getImportEndpoint(ed);
			if (endpoint != null)
				return endpoint;
		}
		return null;
	}

	private void unimportService(IRemoteServiceID remoteServiceID) {
		List<ImportRegistration> removedRegistrations = new ArrayList<ImportRegistration>();
		synchronized (importedRegistrations) {
			for (Iterator<ImportRegistration> i = importedRegistrations
					.iterator(); i.hasNext();) {
				ImportRegistration importRegistration = i.next();
				if (importRegistration != null
						&& importRegistration.match(remoteServiceID))
					removedRegistrations.add(importRegistration);
			}
		}
		// Now close all of them
		for (ImportRegistration removedReg : removedRegistrations) {
			trace("unimportService", "closing importRegistration=" + removedReg); //$NON-NLS-1$ //$NON-NLS-2$
			removedReg.close();
		}
	}

	class RemoteServiceListener implements IRemoteServiceListener {
		public void handleServiceEvent(IRemoteServiceEvent event) {
			if (event instanceof IRemoteServiceUnregisteredEvent)
				unimportService(event.getReference().getID());
		}
	}

	private void trace(String methodName, String message) {
		LogUtility.trace(methodName, DebugOptions.REMOTE_SERVICE_ADMIN,
				this.getClass(), message);
	}

	private void logWarning(String methodName, String message) {
		LogUtility.logWarning(methodName, DebugOptions.REMOTE_SERVICE_ADMIN,
				this.getClass(), message);
	}

	private void logError(String methodName, String message, Throwable t) {
		LogUtility.logError(methodName, DebugOptions.REMOTE_SERVICE_ADMIN,
				this.getClass(), message, t);
	}

	private void logError(String methodName, String message) {
		logError(methodName, message, (Throwable) null);
	}

	public class RemoteServiceAdminEvent extends
			org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent {

		private ID containerID;

		public RemoteServiceAdminEvent(
				ID containerID,
				int type,
				Bundle source,
				org.osgi.service.remoteserviceadmin.ExportReference exportReference,
				Throwable exception) {
			super(type, source, exportReference, exception);
			this.containerID = containerID;
		}

		public RemoteServiceAdminEvent(
				ID containerID,
				int type,
				Bundle source,
				org.osgi.service.remoteserviceadmin.ImportReference importReference,
				Throwable exception) {
			super(type, source, importReference, exception);
			this.containerID = containerID;
		}

		public ID getContainerID() {
			return containerID;
		}

		public String toString() {
			return "RemoteServiceAdminEvent[containerID=" + containerID //$NON-NLS-1$
					+ ", getType()=" + getType() + ", getSource()=" + getSource() //$NON-NLS-1$ //$NON-NLS-2$
					+ ", getException()=" + getException() //$NON-NLS-1$
					+ ", getImportReference()=" + getImportReference() //$NON-NLS-1$
					+ ", getExportReference()=" + getExportReference() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
		}

	}

}
