more changes to remote connections for discovery + load extensions
authordadubrow
Thu, 17 Dec 2009 11:28:11 -0600
changeset 698 9162f4cfad65
parent 696 3edbbd22908c
child 699 fe13162b76cf
child 703 3a27d56389d5
more changes to remote connections for discovery + load extensions
connectivity/com.nokia.carbide.remoteConnections/META-INF/MANIFEST.MF
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/RemoteConnectionsActivator.java
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractConnectedService.java
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractConnection.java
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/IConnectionsManager.java
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/internal/registry/Registry.java
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/messages.properties
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/ui/ClientServiceSiteUI.java
--- a/connectivity/com.nokia.carbide.remoteConnections/META-INF/MANIFEST.MF	Thu Dec 17 10:38:24 2009 -0600
+++ b/connectivity/com.nokia.carbide.remoteConnections/META-INF/MANIFEST.MF	Thu Dec 17 11:28:11 2009 -0600
@@ -19,6 +19,7 @@
  com.nokia.carbide.installpackages.gen.InstallPackages,
  com.nokia.carbide.remoteconnections,
  com.nokia.carbide.remoteconnections.interfaces,
+ com.nokia.carbide.remoteconnections.internal,
  com.nokia.carbide.remoteconnections.internal.registry;x-friends:="com.nokia.carbide.remoteConnections.tests,com.nokia.carbide.tests.debug",
  com.nokia.carbide.remoteconnections.settings.ui;x-friends:="com.nokia.carbide.tests.debug"
 Bundle-ClassPath: .,
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/RemoteConnectionsActivator.java	Thu Dec 17 10:38:24 2009 -0600
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/RemoteConnectionsActivator.java	Thu Dec 17 11:28:11 2009 -0600
@@ -16,18 +16,25 @@
 */
 package com.nokia.carbide.remoteconnections;
 
-import com.nokia.carbide.remoteconnections.interfaces.IConnectionTypeProvider;
-import com.nokia.carbide.remoteconnections.interfaces.IConnectionsManager;
-import com.nokia.carbide.remoteconnections.internal.registry.Registry;
-import com.nokia.cpp.internal.api.utils.core.Logging;
+import java.util.ArrayList;
+import java.util.Collection;
 
-import org.eclipse.core.net.proxy.IProxyService;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
 import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IFilter;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.plugin.AbstractUIPlugin;
 import org.osgi.framework.BundleContext;
-import org.osgi.util.tracker.ServiceTracker;
+
+import com.nokia.carbide.remoteconnections.interfaces.IConnectionTypeProvider;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectionsManager;
+import com.nokia.carbide.remoteconnections.internal.IDeviceDiscoveryAgent;
+import com.nokia.carbide.remoteconnections.internal.registry.Registry;
+import com.nokia.cpp.internal.api.utils.core.Logging;
 
 /**
  * The activator class controls the plug-in life cycle
@@ -37,51 +44,35 @@
 	// The plug-in ID
 	public static final String PLUGIN_ID = "com.nokia.carbide.remoteConnections"; //$NON-NLS-1$
 
+	private static final String DISCOVERY_AGENT_EXTENSION = 
+		PLUGIN_ID + ".deviceDiscoveryAgent"; //$NON-NLS-1$
+
 	// The shared instance
 	private static RemoteConnectionsActivator plugin;
-	
-	// A service tracker for the proxy service
-	private ServiceTracker proxyServiceTracker;
-	
+
+	private Collection<IDeviceDiscoveryAgent> discoveryAgents;
+
 	/**
 	 * The constructor
 	 */
 	public RemoteConnectionsActivator() {
 	}
-
  
- 	/**
-	 * Returns IProxyService.
-	 * @deprecated
-	 */
-	public IProxyService getProxyService() {
-		return (IProxyService) proxyServiceTracker.getService();
-	}
-	
-	/*
-	 * (non-Javadoc)
-	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
-	 */
 	public void start(BundleContext context) throws Exception {
 		super.start(context);
 		plugin = this;
 		Registry instance = Registry.instance();
 		instance.loadExtensions();
 		instance.loadConnections();
-		this.proxyServiceTracker = new ServiceTracker(context, IProxyService.class.getName(), null);
-		this.proxyServiceTracker.open();
+		loadAndStartDeviceDiscoveryAgents();
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
-	 */
 	public void stop(BundleContext context) throws Exception {
+		stopDeviceDiscoveryAgents();
 		Registry.instance().storeConnections();
 		Registry.instance().disposeConnections();
 		plugin = null;
 		super.stop(context);
-		this.proxyServiceTracker.close();
 	}
 
 	/**
@@ -131,4 +122,62 @@
 	public static void setHelp(Control control, String id) {
 		PlatformUI.getWorkbench().getHelpSystem().setHelp(control, PLUGIN_ID + id);		 //$NON-NLS-1$
 	}
+	
+	private void loadAndStartDeviceDiscoveryAgents() {
+		String loadError = Messages.getString("RemoteConnectionsActivator.DiscoveryAgentLoadError");
+		discoveryAgents = new ArrayList<IDeviceDiscoveryAgent>();
+		loadExtensions(DISCOVERY_AGENT_EXTENSION, loadError, discoveryAgents, new IFilter() {
+			public boolean select(Object toTest) {
+				if (toTest instanceof IDeviceDiscoveryAgent) {
+					try {
+						((IDeviceDiscoveryAgent) toTest).start();
+						return true;
+					} catch (CoreException e) {
+						logError(e);
+					}
+				}
+				return false;
+			}
+		});
+		
+	}
+
+	private void stopDeviceDiscoveryAgents() {
+		for (IDeviceDiscoveryAgent agent : discoveryAgents) {
+			try {
+				agent.stop();
+			} catch (CoreException e) {
+				logError(e);
+			}
+		}
+		
+	}
+
+	public static void log(String errorStr, Throwable t) {
+		RemoteConnectionsActivator p = RemoteConnectionsActivator.getDefault();
+		String error = errorStr;
+		if (t != null) {
+			error += " : " + t.getLocalizedMessage(); //$NON-NLS-1$
+		}
+		Logging.log(p, Logging.newStatus(p, IStatus.ERROR, error));
+		if (t instanceof CoreException)
+			Logging.log(p, ((CoreException) t).getStatus());
+	}
+	
+	@SuppressWarnings("unchecked")
+	public static <T> void loadExtensions(String extensionId, String loadError, Collection<T> extensionObjects, IFilter filter) {
+		IConfigurationElement[] elements = 
+			Platform.getExtensionRegistry().getConfigurationElementsFor(extensionId);
+		for (IConfigurationElement element : elements) {
+			try {
+				T extObject = (T) element.createExecutableExtension("class"); //$NON-NLS-1$
+				if (filter == null || filter.select(extObject))
+					extensionObjects.add(extObject);
+			} 
+			catch (CoreException e) {
+				if (loadError != null)
+					RemoteConnectionsActivator.log(loadError, e);
+			}
+		}
+	}
 }
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractConnectedService.java	Thu Dec 17 10:38:24 2009 -0600
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractConnectedService.java	Thu Dec 17 11:28:11 2009 -0600
@@ -18,6 +18,7 @@
 
 import com.nokia.carbide.remoteconnections.Messages;
 import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus.EStatus;
+import com.nokia.carbide.remoteconnections.internal.IConnectedService2;
 import com.nokia.cpp.internal.api.utils.core.Check;
 import com.nokia.cpp.internal.api.utils.core.ListenerList;
 import com.nokia.cpp.internal.api.utils.core.ObjectUtils;
@@ -30,8 +31,10 @@
 import org.eclipse.swt.widgets.Display;
 
 import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
 
-public abstract class AbstractConnectedService implements IConnectedService {
+public abstract class AbstractConnectedService implements IConnectedService2 {
 	
 	public final static int TIMEOUT = 2000;
 	
@@ -124,10 +127,12 @@
 	protected Status currentStatus;
 	protected Tester tester;
 	protected boolean manualTesting;
+	private Map<String, String> properties;
 
 	public AbstractConnectedService(IService service, AbstractSynchronizedConnection connection) {
 		this.service = service;
 		this.connection = connection;
+		properties = new HashMap<String, String>();
 	}
 	
 	public void setRunnableContext(IRunnableContext runnableContext) {
@@ -229,4 +234,8 @@
 					Messages.getString("AbstractConnectedService.UserDisabledMessage")); //$NON-NLS-1$
 		}
 	}
+	
+	public Map<String, String> getProperties() {
+		return properties;
+	}
 }
\ No newline at end of file
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractConnection.java	Thu Dec 17 10:38:24 2009 -0600
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractConnection.java	Thu Dec 17 11:28:11 2009 -0600
@@ -18,25 +18,60 @@
 
 package com.nokia.carbide.remoteconnections.interfaces;
 
-import com.nokia.carbide.remoteconnections.interfaces.IConnection;
-import com.nokia.carbide.remoteconnections.interfaces.IConnectionType;
-
 import java.util.HashMap;
 import java.util.Map;
 
+import org.eclipse.jface.resource.ImageDescriptor;
+
+import com.nokia.carbide.remoteconnections.internal.IConnection2;
+import com.nokia.carbide.remoteconnections.internal.IConnection2.IStatus.EStatus;
+import com.nokia.cpp.internal.api.utils.core.Check;
+import com.nokia.cpp.internal.api.utils.core.ListenerList;
+
 /**
  * A standard implementation of IConnection
  */
-public abstract class AbstractConnection implements IConnection {
+public abstract class AbstractConnection implements IConnection2 {
+	
+	public class Status implements IStatus {
+		private EStatus estatus;
+		private String description;
+		
+		public Status(EStatus estatus, String description) {
+			this.estatus = estatus;
+			this.description = description;
+		}
+
+		public EStatus getEStatus() {
+			return estatus;
+		}
+		
+		public String getDescription() {
+			return description;
+		}
+
+		public void setEStatus(EStatus estatus) {
+			this.estatus = estatus;
+		}
+
+		public void setDescription(String description) {
+			this.description = description;
+		}
+	}
 
 	private final IConnectionType connectionType;
 	private final Map<String, String> settings;
 	private String name;
 	private String id;
+	private boolean dynamic;
+	private IStatus status;
+	private ImageDescriptor imageDescriptor;
+	private ListenerList<IStatusChangedListener> listeners;
 
 	public AbstractConnection(IConnectionType connectionType, Map<String, String> settings) {
 		this.connectionType = connectionType;
 		this.settings = new HashMap<String, String>(settings);
+		status = new Status(EStatus.NOT_READY, ""); //$NON-NLS-1$
 	}
 
 	public void dispose() {
@@ -71,4 +106,49 @@
 		settings.putAll(newSettings);
 	}
 
+	public boolean isDynamic() {
+		return dynamic;
+	}
+	
+	public void setDynamic(boolean dynamic) {
+		this.dynamic = dynamic;
+	}
+	
+	public IStatus getStatus() {
+		return status;
+	}
+
+	public void setStatus(IStatus status) {
+		Check.checkArg(status);
+		this.status = status;
+	}
+	
+	public void addStatusChangedListener(IStatusChangedListener listener) {
+		if (listeners == null)
+			listeners = new ListenerList<IStatusChangedListener>();
+		listeners.add(listener);
+	}
+	
+	public void removeStatusChangedListener(IStatusChangedListener listener) {
+		if (listeners != null)
+			listeners.remove(listener);
+	}
+	
+	public void fireStatusChanged() {
+		if (listeners == null)
+			return;
+		for (IStatusChangedListener listener : listeners) {
+			listener.statusChanged(status);
+		}
+	}
+
+	public ImageDescriptor getImageDescriptor() {
+		return imageDescriptor;
+	}
+	
+	public void setImageDescriptor(ImageDescriptor imageDescriptor) {
+		this.imageDescriptor = imageDescriptor;
+	}
+	
+
 }
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/IConnectionsManager.java	Thu Dec 17 10:38:24 2009 -0600
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/IConnectionsManager.java	Thu Dec 17 11:28:11 2009 -0600
@@ -159,6 +159,13 @@
 	void setDefaultConnection(IConnection connection);
 	
 	/**
+	 * Returns the default connection.
+	 * @return IConnection
+	 * @since 3.0
+	 */
+	IConnection getDefaultConnection();
+	
+	/**
 	 * Can be called by specific service implementors (e.g., debugger) to ensure some connection
 	 * exists and supports this service. If the connection does not exist or does not support
 	 * the service, a CoreException may be thrown after the framework attempts to allow the user
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/internal/registry/Registry.java	Thu Dec 17 10:38:24 2009 -0600
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/internal/registry/Registry.java	Thu Dec 17 11:28:11 2009 -0600
@@ -18,26 +18,51 @@
 
 package com.nokia.carbide.remoteconnections.internal.registry;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.viewers.IFilter;
+
 import com.nokia.carbide.remoteconnections.Messages;
 import com.nokia.carbide.remoteconnections.RemoteConnectionsActivator;
-import com.nokia.carbide.remoteconnections.interfaces.*;
+import com.nokia.carbide.remoteconnections.interfaces.IClientServiceSiteUI;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectedService;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectedServiceFactory;
+import com.nokia.carbide.remoteconnections.interfaces.IConnection;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectionType;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectionTypeProvider;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectionsManager;
+import com.nokia.carbide.remoteconnections.interfaces.IExtensionFilter;
+import com.nokia.carbide.remoteconnections.interfaces.IService;
+import com.nokia.carbide.remoteconnections.internal.IConnection2;
 import com.nokia.carbide.remoteconnections.ui.ClientServiceSiteUI;
 import com.nokia.cpp.internal.api.utils.core.Check;
 import com.nokia.cpp.internal.api.utils.core.ListenerList;
 import com.nokia.cpp.internal.api.utils.core.Logging;
 
-import org.eclipse.core.runtime.*;
-import org.eclipse.jface.viewers.IFilter;
-
-import java.io.*;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
 /**
  * A registry of connection type and service extensions
  */
+@SuppressWarnings("deprecation")
 public class Registry implements IConnectionTypeProvider, IConnectionsManager {
 
 	private static final String FILTER_EXTENSION = RemoteConnectionsActivator.PLUGIN_ID + ".extensionFilter"; //$NON-NLS-1$
@@ -57,6 +82,7 @@
 	private ListenerList<IConnectionsManagerListener> listeners;
 	private List<IConnectedServiceFactory> connectedServiceFactories;
 	private ListenerList<IConnectionListener> connectionListeners;
+	private IConnection defaultConnection;
 
 	public static Registry instance() {
 		if (instance == null) {
@@ -82,19 +108,21 @@
 	private void loadConnectedServiceFactoryExtensions() {
 		connectedServiceFactories = new ArrayList<IConnectedServiceFactory>();
 		String loadError = Messages.getString("Registry.ConnectedServiceFactoryExtensionLoadError"); //$NON-NLS-1$
-		loadExtensions(CONNECTED_SERVICE_FACTORY_EXTENSION, loadError, connectedServiceFactories, null);
+		RemoteConnectionsActivator.loadExtensions(CONNECTED_SERVICE_FACTORY_EXTENSION, loadError, 
+				connectedServiceFactories, null);
 	}
 
 	private void loadExtensionFilters() {
 		extensionFilters = new ArrayList<IExtensionFilter>();
 		String loadError = Messages.getString("Registry.FilterExtensionLoadError"); //$NON-NLS-1$
-		loadExtensions(FILTER_EXTENSION, loadError, extensionFilters, null);
+		RemoteConnectionsActivator.loadExtensions(FILTER_EXTENSION, loadError, extensionFilters, null);
 	}
 
 	private void loadConnectionTypeExtensions() {
 		List<IConnectionType> connectionTypeExtensions = new ArrayList<IConnectionType>();
 		String loadError = Messages.getString("Registry.ConnectionTypeExtensionLoadError"); //$NON-NLS-1$
-		loadExtensions(CONNECTION_TYPE_EXTENSION, loadError, connectionTypeExtensions, new IFilter() {
+		RemoteConnectionsActivator.loadExtensions(CONNECTION_TYPE_EXTENSION, loadError, 
+				connectionTypeExtensions, new IFilter() {
 			public boolean select(Object toTest) {
 				return acceptConnectionType(((IConnectionType) toTest).getIdentifier());
 			}
@@ -117,7 +145,7 @@
 	private void loadServiceExtensions() {
 		services = new ArrayList<IService>();
 		String loadError = Messages.getString("Registry.ServiceExtensionLoadError"); //$NON-NLS-1$
-		loadExtensions(SERVICE_EXTENSION, loadError, services, new IFilter() {
+		RemoteConnectionsActivator.loadExtensions(SERVICE_EXTENSION, loadError, services, new IFilter() {
 			public boolean select(Object toTest) {
 				return acceptService(((IService) toTest).getIdentifier());
 			}
@@ -132,29 +160,6 @@
 		return true;
 	}
 	
-	@SuppressWarnings("unchecked")
-	private <T> void loadExtensions(String extensionId, String loadError, Collection<T> extensionObjects, IFilter filter) {
-		IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
-		IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(extensionId);
-		IExtension[] extensions = extensionPoint.getExtensions();
-		
-		for (int i = 0; i < extensions.length; i++) {
-			IExtension extension = extensions[i];
-			IConfigurationElement[] elements = extension.getConfigurationElements();
-			Check.checkContract(elements.length == 1);
-			IConfigurationElement element = elements[0];
-			try {
-				T extObject = (T) element.createExecutableExtension("class"); //$NON-NLS-1$
-				if (filter == null || filter.select(extObject))
-					extensionObjects.add(extObject);
-			} 
-			catch (CoreException e) {
-				if (loadError != null)
-					log(loadError, e);
-			}
-		}
-	}
-	
 	private void mapConnectionTypeToServices() {
 		connectionTypeToServices = new HashMap<IConnectionType, Collection<IService>>();
 		Set<String> connectionTypeIds = connectionTypeIdMap.keySet();
@@ -200,17 +205,6 @@
 		return accept;
 	}
 
-	private void log(String errorStr, Throwable t) {
-		RemoteConnectionsActivator p = RemoteConnectionsActivator.getDefault();
-		String error = errorStr;
-		if (t != null) {
-			error += " : " + t.getLocalizedMessage(); //$NON-NLS-1$
-		}
-		Logging.log(p, Logging.newStatus(p, IStatus.ERROR, error));
-		if (t instanceof CoreException)
-			Logging.log(p, ((CoreException) t).getStatus());
-	}
-	
 	/* (non-Javadoc)
 	 * @see com.nokia.carbide.remoteconnections.registry.IConnectionStore#loadConnections()
 	 */
@@ -228,7 +222,7 @@
 			fireConnectionStoreChanged();
 		} 
 		catch (Exception e) {
-			log(Messages.getString("Registry.ConnectionLoadError"), e); //$NON-NLS-1$
+			RemoteConnectionsActivator.log(Messages.getString("Registry.ConnectionLoadError"), e); //$NON-NLS-1$
 		}
 		
 	}
@@ -250,7 +244,7 @@
 			if (connectedService != null)
 				return connectedService;
 		}
-		log(MessageFormat.format(
+		RemoteConnectionsActivator.log(MessageFormat.format(
 				Messages.getString("Registry.ConnectedServiceFactoryError"), //$NON-NLS-1$
 				service.getDisplayName(), connection.getConnectionType().getDisplayName()), null);
 		return null;
@@ -265,13 +259,10 @@
 			Writer.writeToXML(os, connectionToConnectedServices.keySet());
 		} 
 		catch (Exception e) {
-			log(Messages.getString("Registry.ConnectionStoreError"), e); //$NON-NLS-1$
+			RemoteConnectionsActivator.log(Messages.getString("Registry.ConnectionStoreError"), e); //$NON-NLS-1$
 		}
 	}
 	
-	/* (non-Javadoc)
-	 * @see com.nokia.carbide.remoteconnections.registry.IConnectionStore#addConnectionStoreChangedListener(com.nokia.carbide.remoteconnections.registry.Registry.IConnectionStoreChangedListener)
-	 */
 	public void addConnectionStoreChangedListener(IConnectionsManagerListener listener) {
 		if (listeners == null)
 			listeners = new ListenerList<IConnectionsManagerListener>();
@@ -290,10 +281,7 @@
 			listener.connectionStoreChanged();
 		}
 	}
-	
-	/* (non-Javadoc)
-	 * @see com.nokia.carbide.remoteconnections.registry.IConnectionTypeProvider#getConnectionType(java.lang.String)
-	 */
+
 	public IConnectionType getConnectionType(String identifier) {
 		Check.checkContract(connectionTypeIdMap != null);
 		return connectionTypeIdMap.get(identifier);
@@ -320,11 +308,12 @@
 		List<IConnectedService> connectedServices = createConnectedServicesForConnection(connection);
 		connectionToConnectedServices.put(connection, connectedServices);
 		fireConnectionStoreChanged();
+		fireConnectionAdded(connection);
 	}
 	
 	private void ensureUniqueId(IConnection connection) {
 		String id = connection.getIdentifier();
-		if (id == null || id.length() == 0 || connectionIdInUse(id))
+		if (id == null || id.length() == 0 || findConnectionById(id) != null)
 			connection.setIdentifier(getUniqueConnectionId());
 	}
 	
@@ -332,15 +321,13 @@
 		return UUID.randomUUID().toString();
 	}
 	
-	private boolean connectionIdInUse(String id) {
-		boolean used = false;
-		for (IConnection c : connectionToConnectedServices.keySet()) {
-			if (c.getIdentifier().equals(id)) {
-				used = true;
-				break;
+	public IConnection findConnectionById(String id) {
+		for (IConnection connection : connectionToConnectedServices.keySet()) {
+			if (connection.getIdentifier().equals(id)) {
+				return connection;
 			}
 		}
-		return used;
+		return null;
 	}
 
 	private void ensureUniqueName(IConnection connection) {
@@ -385,13 +372,30 @@
 		return used;
 	}
 
-	/* (non-Javadoc)
-	 * @see com.nokia.carbide.remoteconnections.registry.IConnectionStore#removeConnection(com.nokia.carbide.remoteconnections.extensions.IConnection)
-	 */
 	public void removeConnection(IConnection connection) {
 		disposeConnection(connection);
 		connectionToConnectedServices.remove(connection);
+		if (connection == defaultConnection) {
+			defaultConnection = null;
+			pickNewDefaultConnection();
+		}
 		fireConnectionStoreChanged();
+		fireConnectionRemoved(connection);
+	}
+
+	private void pickNewDefaultConnection() {
+		Set<IConnection> connections = connectionToConnectedServices.keySet();
+		// try to get a dynamic connection
+		for (IConnection connection : connections) {
+			if (connection instanceof IConnection2 && 
+					((IConnection2) connection).isDynamic()) {
+				setDefaultConnection(connection);
+				break;
+			}
+		}
+		// otherwise, any connection will do
+		if (defaultConnection == null && !connections.isEmpty())
+			setDefaultConnection(connections.iterator().next());
 	}
 
 	private void disposeConnection(IConnection connection) {
@@ -468,28 +472,69 @@
 			connectionListeners.remove(listener);
 	}
 	
-	public void setDefaultConnection(IConnection connection, Object source) {
-		// TODO Auto-generated method stub
-		
+	private void fireConnectionAdded(IConnection connection) {
+		if (listeners == null)
+			return;
+		for (IConnectionListener listener : connectionListeners) {
+			listener.connectionAdded(connection);
+		}
+	}
+	
+	private void fireConnectionRemoved(IConnection connection) {
+		if (listeners == null)
+			return;
+		for (IConnectionListener listener : connectionListeners) {
+			listener.connectionRemoved(connection);
+		}
+	}
+	
+	private void fireDefaultConnectionSet(IConnection connection) {
+		if (listeners == null)
+			return;
+		for (IConnectionListener listener : connectionListeners) {
+			listener.defaultConnectionSet(connection);
+		}
+	}
+	
+	public IConnection ensureConnection(String id, IService service) throws CoreException {
+		Check.checkArg(service);
+		IConnection connection = findConnectionById(id);
+		if (!isCompatibleConnection(connection, service)) {
+			// TODO ask user to connect a device or cancel
+			throw new CoreException(
+					Logging.newStatus(RemoteConnectionsActivator.getDefault(), IStatus.ERROR, 
+							"No compatible connection found for this id"));
+		}
+		return connection;
 	}
 
-	public IConnection ensureConnection(String id, IService service) throws CoreException {
-		// TODO Auto-generated method stub
-		return null;
+	private boolean isCompatibleConnection(IConnection connection, IService service) {
+		if (connection == null)
+			return false;
+		return getCompatibleServices(connection.getConnectionType()).contains(service);
 	}
 
 	public void setDefaultConnection(IConnection connection) {
-		// TODO Auto-generated method stub
-		
+		if (connectionToConnectedServices.keySet().contains(connection)) {
+			defaultConnection = connection;
+			fireDefaultConnectionSet(connection);
+		}
+	}
+
+	public IConnection getDefaultConnection() {
+		return defaultConnection;
 	}
 
 	public void disconnect(IConnection connection) {
-		// TODO Auto-generated method stub
+		// TODO transition to disconnected state and wait:
+		// if not in-use, remove and stop waiting
+		// if reconnected, stop waiting
 		
 	}
 
 	public boolean reconnect(IConnection connection) {
-		// TODO Auto-generated method stub
+		// TODO if not removed, transition out of disconnected state
+		// return not removed
 		return false;
 	}
 }
\ No newline at end of file
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/messages.properties	Thu Dec 17 10:38:24 2009 -0600
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/messages.properties	Thu Dec 17 11:28:11 2009 -0600
@@ -84,4 +84,5 @@
 Registry.ServiceExtensionLoadError=Could not load service extensions
 Registry.ServiceListUnknownConnectionTypeError=Service ''{0}'' lists unknown connection type ''{1}'' as compatible
 SettingsWizard.WindowTitle.Edit=Edit {0} Settings
-SettingsWizard.WindowTitle.New=New Connection
\ No newline at end of file
+SettingsWizard.WindowTitle.New=New Connection
+RemoteConnectionsActivator.DiscoveryAgentLoadError=Could not load device discovery agent
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/ui/ClientServiceSiteUI.java	Thu Dec 17 10:38:24 2009 -0600
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/ui/ClientServiceSiteUI.java	Thu Dec 17 11:28:11 2009 -0600
@@ -19,7 +19,6 @@
 package com.nokia.carbide.remoteconnections.ui;
 
 import com.nokia.carbide.remoteconnections.Messages;
-import com.nokia.carbide.remoteconnections.RemoteConnectionsActivator;
 import com.nokia.carbide.remoteconnections.interfaces.*;
 import com.nokia.carbide.remoteconnections.internal.registry.Registry;
 import com.nokia.carbide.remoteconnections.settings.ui.SettingsWizard;
@@ -205,14 +204,16 @@
 		viewer.setSelection(new StructuredSelection(connection));
 	}
 	
+	@SuppressWarnings("unchecked")
 	private boolean viewerInputContainsConnection(IConnection connection) {
 		Object input = viewer.getInput();
-		if (input instanceof List) {
-			return ((List) input).contains(connection);
+		if (input instanceof Collection) {
+			return ((Collection) input).contains(connection);
 		}
 		return false;
 	}
 
+	@SuppressWarnings("unchecked")
 	private void addConnectionToViewerInput(IConnection connection) {
 		Object input = viewer.getInput();
 		if (input instanceof Collection) {