bug 10493 - only test one service for each physical connection RCL_2_4
authordadubrow
Fri, 05 Feb 2010 09:51:33 -0600
branchRCL_2_4
changeset 898 b8f39c88d4f1
parent 897 702ac8834c87
child 900 8b30bf718a17
bug 10493 - only test one service for each physical connection
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractConnectedService.java
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractConnectedService2.java
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractSynchronizedConnection.java
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/internal/ServiceTester.java
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/settings/ui/ConnectionSettingsPage.java
debuggercdi/com.nokia.carbide.trk.support/src/com/nokia/carbide/trk/support/service/ConnectedServiceFactory.java
debuggercdi/com.nokia.carbide.trk.support/src/com/nokia/carbide/trk/support/service/TRKConnectedService.java
debuggercdi/com.nokia.carbide.trk.support/src/com/nokia/carbide/trk/support/service/TracingConnectedService.java
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractConnectedService.java	Fri Feb 05 07:42:52 2010 -0600
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractConnectedService.java	Fri Feb 05 09:51:33 2010 -0600
@@ -34,6 +34,9 @@
 import java.util.HashMap;
 import java.util.Map;
 
+/**
+ @deprecated use AbstractConnectedService2
+ */
 public abstract class AbstractConnectedService implements IConnectedService2 {
 	
 	public final static int TIMEOUT = 2000;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractConnectedService2.java	Fri Feb 05 09:51:33 2010 -0600
@@ -0,0 +1,220 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+package com.nokia.carbide.remoteconnections.interfaces;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.widgets.Display;
+
+import com.nokia.carbide.remoteconnections.Messages;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus.EStatus;
+import com.nokia.carbide.remoteconnections.internal.ServiceTester;
+import com.nokia.carbide.remoteconnections.internal.api.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;
+
+public abstract class AbstractConnectedService2 implements IConnectedService2 {
+	
+	public final static int TIMEOUT = 2000;
+
+	public static class ConnectionFailException extends Exception {
+		public ConnectionFailException(String string) {
+			super(string);
+		}
+
+		private static final long serialVersionUID = -5438012263174866437L;
+	}
+
+	public class Status implements IStatus {
+		private volatile EStatus estatus;
+		private String shortDescription;
+		private String longDescription;
+		
+		public IConnectedService getConnectedService() {
+			return AbstractConnectedService2.this;
+		}
+
+		public EStatus getEStatus() {
+			return internalGetEStatus();
+		}
+
+		protected EStatus internalGetEStatus() {
+			if (estatus == null)
+				estatus = EStatus.UNKNOWN;
+			return estatus;
+		}
+		
+		public String getLongDescription() {
+			return longDescription;
+		}
+		
+		public String getShortDescription() {
+			return shortDescription;
+		}
+		
+		public void setEStatus(EStatus estatus, String shortDescription, String longDescription) {
+			// if everything is the same don't fire status changed
+			if (estatus.equals(this.estatus) &&
+					ObjectUtils.equals(shortDescription, this.shortDescription) &&
+					ObjectUtils.equals(longDescription, this.longDescription))
+				return;
+			this.estatus = estatus;
+			this.shortDescription = shortDescription;
+			this.longDescription = longDescription;
+			fireStatusChanged();
+		}
+	}
+	
+	public static class TestResult {
+		public TestResult(EStatus estatus, String shortDescription, String longDescription) {
+			this.estatus = estatus;
+			this.shortDescription = shortDescription;
+			this.longDescription = longDescription;
+		}
+		private EStatus estatus;
+		private String shortDescription;
+		private String longDescription;
+	}
+	
+	protected abstract TestResult runTestStatus(IProgressMonitor monitor);
+	
+	protected IService service;
+	protected AbstractSynchronizedConnection connection;
+	private ListenerList<IStatusChangedListener> listeners;
+	protected IRunnableContext runnableContext;
+	protected Status currentStatus;
+	protected boolean externalTesting;
+	private Map<String, String> properties;
+
+	public AbstractConnectedService2(IService service, AbstractSynchronizedConnection connection) {
+		this.service = service;
+		this.connection = connection;
+		properties = new HashMap<String, String>();
+	}
+	
+	public void setRunnableContext(IRunnableContext runnableContext) {
+		this.runnableContext = runnableContext;
+	}
+
+	public void addStatusChangedListener(IStatusChangedListener listener) {
+		if (listeners == null)
+			listeners = new ListenerList<IStatusChangedListener>();
+		listeners.add(listener);
+	}
+
+	public void dispose() {
+		if (listeners != null) {
+			for (IStatusChangedListener listener : listeners) {
+				listeners.remove(listener);
+			}
+		}
+		ServiceTester.getInstance().unregister(this);
+	}
+
+	public IService getService() {
+		return service;
+	}
+
+	protected void fireStatusChanged() {
+		if (listeners != null) {
+			for (IStatusChangedListener listener : listeners) {
+				listener.statusChanged(getStatus());
+			}
+		}
+	}
+
+	public void removeStatusChangedListener(IStatusChangedListener listener) {
+		if (listeners != null)
+			listeners.remove(listener);
+	}
+
+	public IConnection getConnection() {
+		return connection;
+	}
+
+	public void testStatus() {
+		if (!(isEnabled() || externalTesting))
+			return;
+			
+		final TestResult result[] = { null };
+		if (runnableContext != null && (!(runnableContext instanceof WizardDialog) || ((WizardDialog) runnableContext).getShell() != null)) {
+			Display.getDefault().syncExec(new Runnable() {
+				public void run() {
+					try {
+						runnableContext.run(true, false, new IRunnableWithProgress() {
+							public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+								result[0] = runTestStatus(monitor);
+							}
+						});
+					} catch (InvocationTargetException e) {
+					} catch (InterruptedException e) {
+					}
+				}
+			});
+		}
+		else {
+			result[0] = runTestStatus(new NullProgressMonitor());
+		}
+		
+		if (!(isEnabled() || externalTesting)) // could be waiting for response past when service testing was disabled
+			return;
+		if (result[0].shortDescription != null && result[0].longDescription != null) {
+			currentStatus.setEStatus(result[0].estatus, result[0].shortDescription, result[0].longDescription);
+		}
+	}
+	
+	public void setExternalTesting() {
+		externalTesting = true;
+	}
+
+	public boolean isEnabled() {
+		return ServiceTester.getInstance().isRegistered(this);
+	}
+
+	public void setEnabled(boolean enabled) {
+		if (!service.isTestable())
+			return;
+		if (enabled && !isEnabled()) {
+			Check.checkState(connection.getSettings() != null);
+			ServiceTester.getInstance().register(this);
+		}
+		else if (!enabled && isEnabled()) {
+			ServiceTester.getInstance().unregister(this);
+			currentStatus.setEStatus(EStatus.UNKNOWN, 
+					Messages.getString("AbstractConnectedService.NoTestingLabel"), //$NON-NLS-1$
+					Messages.getString("AbstractConnectedService.UserDisabledMessage")); //$NON-NLS-1$
+		}
+	}
+	
+	public Map<String, String> getProperties() {
+		return properties;
+	}
+
+	public void setStatus(Status status) {
+		if (currentStatus == null)
+			currentStatus = new Status();
+		currentStatus.setEStatus(status.internalGetEStatus(), status.getShortDescription(), status.getLongDescription());
+	}
+}
\ No newline at end of file
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractSynchronizedConnection.java	Fri Feb 05 07:42:52 2010 -0600
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/interfaces/AbstractSynchronizedConnection.java	Fri Feb 05 09:51:33 2010 -0600
@@ -100,4 +100,8 @@
 		}
 		setInUse(use);
 	}
+	
+	public Object getCurrentResource() {
+		return getCurrentResourceString();
+	}
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/internal/ServiceTester.java	Fri Feb 05 09:51:33 2010 -0600
@@ -0,0 +1,198 @@
+/**
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+package com.nokia.carbide.remoteconnections.internal;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import com.nokia.carbide.remoteconnections.interfaces.AbstractConnectedService2;
+import com.nokia.carbide.remoteconnections.interfaces.AbstractSynchronizedConnection;
+import com.nokia.carbide.remoteconnections.interfaces.AbstractConnectedService2.Status;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus;
+
+
+public class ServiceTester {
+
+	public class TestRunner extends Thread {
+		private final Collection<Set<AbstractConnectedService2>> connectedServicesSets;
+
+		public TestRunner(Collection<Set<AbstractConnectedService2>> connectedServicesSets) {
+			this.connectedServicesSets = connectedServicesSets;
+		}
+
+		@Override
+		public void run() {
+			for (Set<AbstractConnectedService2> connectedServices : connectedServicesSets) {
+				// test first in the set and set status for others
+				Iterator<AbstractConnectedService2> iterator = connectedServices.iterator();
+				AbstractConnectedService2 toTest = iterator.next();
+				toTest.testStatus();
+				IStatus status = toTest.getStatus();
+				while (iterator.hasNext()) {
+					AbstractConnectedService2 next = iterator.next();
+					next.setStatus((Status) status);
+				}
+			}
+			unregisterThread(this);
+		}
+		
+		@Override
+		public synchronized void start() {
+			registerThread(this);
+			super.start();
+		}
+
+		public boolean contains(AbstractConnectedService2 connectedService) {
+			for (Set<AbstractConnectedService2> csSet : connectedServicesSets) {
+				if (csSet.contains(connectedService))
+					return true;
+			}
+			
+			return false;
+		}
+
+	}
+
+	public interface IEquivalence {
+		Object getRelation(AbstractConnectedService2 cs);
+	}
+
+	private static ServiceTester instance;
+	
+	private Set<AbstractConnectedService2> registry;
+	private Set<TestRunner> runningThreads;
+
+	public static ServiceTester getInstance() {
+		if (instance == null)
+			instance = new ServiceTester();
+		return instance;
+	}
+	
+	private ServiceTester() {
+		registry = new HashSet<AbstractConnectedService2>();
+		runningThreads = new HashSet<TestRunner>();
+		Thread t = new Thread(new Runnable() {
+			public void run() {
+				while (true) {
+					Collection<Set<AbstractConnectedService2>> csSetsByResource = 
+						createConnectedServiceSetsByResource(registry);
+					for (Set<AbstractConnectedService2> set : csSetsByResource) {
+						Collection<Set<AbstractConnectedService2>> csSetsByService = 
+							createConnectedServiceSetsByService(set);
+						runTests(csSetsByService);
+					}
+					try {
+						Thread.sleep(AbstractConnectedService2.TIMEOUT);
+					} catch (InterruptedException e) {
+					}
+				}
+			}
+		});
+		t.start();
+	}
+	
+	private void runTests(Collection<Set<AbstractConnectedService2>> csSetsByResource) {
+		if (isRunningTest(csSetsByResource))
+			return;
+		
+		if (csSetsByResource.isEmpty())
+			return;
+		
+		TestRunner runner = new TestRunner(csSetsByResource);
+		runner.start();
+		
+	}
+	
+	private Collection<Set<AbstractConnectedService2>> partition(
+			Set<AbstractConnectedService2> connectedServices, IEquivalence equivalence) {
+		Map<Object, Set<AbstractConnectedService2>> collatedConnectedServiceSetMap = 
+			new HashMap<Object, Set<AbstractConnectedService2>>();
+		for (AbstractConnectedService2 cs : connectedServices) {
+			Object object = equivalence.getRelation(cs);
+			if (object == null)
+				continue;
+			if (!collatedConnectedServiceSetMap.containsKey(object))
+				collatedConnectedServiceSetMap.put(object, new HashSet<AbstractConnectedService2>());
+			collatedConnectedServiceSetMap.get(object).add(cs);
+		}
+		return collatedConnectedServiceSetMap.values();
+	}
+
+	private Collection<Set<AbstractConnectedService2>> createConnectedServiceSetsByResource(Set<AbstractConnectedService2> connectedServices) {
+		return partition(connectedServices, new IEquivalence() {
+			public Object getRelation(AbstractConnectedService2 cs) {
+				AbstractSynchronizedConnection connection = (AbstractSynchronizedConnection) cs.getConnection();
+				if (connection != null)
+					return connection.getCurrentResource();
+				
+				return null;
+			}
+		});
+	}
+
+	protected Collection<Set<AbstractConnectedService2>> createConnectedServiceSetsByService(Set<AbstractConnectedService2> connectedServices) {
+		return partition(connectedServices, new IEquivalence() {
+			public Object getRelation(AbstractConnectedService2 cs) {
+				return cs.getService();
+			}
+		});
+	}
+
+	public void register(AbstractConnectedService2 connectedService) {
+		registry.add(connectedService);
+	}
+	
+	public boolean isRegistered(AbstractConnectedService2 connectedService) {
+		return registry.contains(connectedService);
+	}
+	
+	public void unregister(AbstractConnectedService2 connectedService) {
+		registry.remove(connectedService);
+	}
+
+	public synchronized void registerThread(TestRunner testRunner) {
+		runningThreads.add(testRunner);
+	}
+	
+	public synchronized void unregisterThread(TestRunner testRunner) {
+		runningThreads.remove(testRunner);
+	}
+
+	public synchronized boolean isRunningTest(Collection<Set<AbstractConnectedService2>> csSetsByResource) {
+		for (Set<AbstractConnectedService2> set : csSetsByResource) {
+			for (AbstractConnectedService2 cs : set) {
+				if (isRunningTest(cs))
+					return true;
+			}
+		}
+		return false;
+	}
+
+	private boolean isRunningTest(AbstractConnectedService2 cs) {
+		for (TestRunner runner : runningThreads) {
+			if (runner.contains(cs))
+				return true;
+		}
+		
+		return false;
+	}
+}
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/settings/ui/ConnectionSettingsPage.java	Fri Feb 05 07:42:52 2010 -0600
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/settings/ui/ConnectionSettingsPage.java	Fri Feb 05 09:51:33 2010 -0600
@@ -78,7 +78,7 @@
 
 import com.nokia.carbide.remoteconnections.Messages;
 import com.nokia.carbide.remoteconnections.RemoteConnectionsActivator;
-import com.nokia.carbide.remoteconnections.interfaces.AbstractConnectedService;
+import com.nokia.carbide.remoteconnections.interfaces.AbstractConnectedService2;
 import com.nokia.carbide.remoteconnections.interfaces.IConnectedService;
 import com.nokia.carbide.remoteconnections.interfaces.IConnection;
 import com.nokia.carbide.remoteconnections.interfaces.IConnectionFactory;
@@ -105,12 +105,12 @@
 	public final class Tester extends Thread {
 		@Override
 		public void run() {
-			((AbstractConnectedService) connectedService).setManualTesting();
+			((AbstractConnectedService2) connectedService).setExternalTesting();
 			for (int i = 0; i < 3 && connectedService != null; i++) {
 				connectedService.testStatus();
 				try {
 					if (i < 2)
-						sleep(AbstractConnectedService.TIMEOUT);
+						sleep(AbstractConnectedService2.TIMEOUT);
 				} catch (InterruptedException e) {
 					break;
 				}
@@ -678,8 +678,8 @@
 					});
 				}
 			});
-			if (connectedService instanceof AbstractConnectedService) {
-				((AbstractConnectedService) connectedService).setRunnableContext(getContainer());
+			if (connectedService instanceof AbstractConnectedService2) {
+				((AbstractConnectedService2) connectedService).setRunnableContext(getContainer());
 				tester = new Tester();
 				tester.start();
 			}
--- a/debuggercdi/com.nokia.carbide.trk.support/src/com/nokia/carbide/trk/support/service/ConnectedServiceFactory.java	Fri Feb 05 07:42:52 2010 -0600
+++ b/debuggercdi/com.nokia.carbide.trk.support/src/com/nokia/carbide/trk/support/service/ConnectedServiceFactory.java	Fri Feb 05 09:51:33 2010 -0600
@@ -18,12 +18,20 @@
 
 package com.nokia.carbide.trk.support.service;
 
-import com.nokia.carbide.remoteconnections.interfaces.*;
-import com.nokia.carbide.trk.support.connection.*;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import com.nokia.carbide.remoteconnections.interfaces.AbstractSynchronizedConnection;
+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.IService;
+import com.nokia.carbide.trk.support.connection.SerialBTConnectionType;
+import com.nokia.carbide.trk.support.connection.SerialConnectionType;
+import com.nokia.carbide.trk.support.connection.USBConnectionType;
 import com.nokia.cpp.internal.api.utils.core.HostOS;
 
-import java.util.*;
-
 /**
  *
  */
--- a/debuggercdi/com.nokia.carbide.trk.support/src/com/nokia/carbide/trk/support/service/TRKConnectedService.java	Fri Feb 05 07:42:52 2010 -0600
+++ b/debuggercdi/com.nokia.carbide.trk.support/src/com/nokia/carbide/trk/support/service/TRKConnectedService.java	Fri Feb 05 09:51:33 2010 -0600
@@ -27,7 +27,7 @@
 import org.osgi.framework.Version;
 
 import com.freescale.cdt.debug.cw.core.SerialConnectionSettings;
-import com.nokia.carbide.remoteconnections.interfaces.AbstractConnectedService;
+import com.nokia.carbide.remoteconnections.interfaces.AbstractConnectedService2;
 import com.nokia.carbide.remoteconnections.interfaces.AbstractSynchronizedConnection;
 import com.nokia.carbide.remoteconnections.interfaces.IConnectionType;
 import com.nokia.carbide.remoteconnections.interfaces.IService;
@@ -51,7 +51,7 @@
 /**
  *
  */
-public class TRKConnectedService extends AbstractConnectedService {
+public class TRKConnectedService extends AbstractConnectedService2 {
 	
 	public static final String PROP_SYS_TRK = "is-system-trk"; //$NON-NLS-1$
 	
--- a/debuggercdi/com.nokia.carbide.trk.support/src/com/nokia/carbide/trk/support/service/TracingConnectedService.java	Fri Feb 05 07:42:52 2010 -0600
+++ b/debuggercdi/com.nokia.carbide.trk.support/src/com/nokia/carbide/trk/support/service/TracingConnectedService.java	Fri Feb 05 09:51:33 2010 -0600
@@ -18,22 +18,33 @@
 
 package com.nokia.carbide.trk.support.service;
 
-import com.freescale.cdt.debug.cw.core.SerialConnectionSettings;
-import com.nokia.carbide.remoteconnections.interfaces.*;
-import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus.EStatus;
-import com.nokia.carbide.trk.support.Messages;
-import com.nokia.carbide.trk.support.connection.*;
-import com.nokia.cpp.internal.api.utils.core.Check;
-import com.nokia.tcf.api.*;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Arrays;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.osgi.framework.Version;
 
-import java.io.IOException;
-import java.text.MessageFormat;
-import java.util.Arrays;
+import com.freescale.cdt.debug.cw.core.SerialConnectionSettings;
+import com.nokia.carbide.remoteconnections.interfaces.AbstractConnectedService2;
+import com.nokia.carbide.remoteconnections.interfaces.AbstractSynchronizedConnection;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectionType;
+import com.nokia.carbide.remoteconnections.interfaces.IService;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus.EStatus;
+import com.nokia.carbide.trk.support.Messages;
+import com.nokia.carbide.trk.support.connection.TCPIPConnectionFactory;
+import com.nokia.carbide.trk.support.connection.TCPIPConnectionType;
+import com.nokia.carbide.trk.support.connection.USBConnectionType;
+import com.nokia.cpp.internal.api.utils.core.Check;
+import com.nokia.tcf.api.ITCAPIConnection;
+import com.nokia.tcf.api.ITCConnection;
+import com.nokia.tcf.api.ITCMessage;
+import com.nokia.tcf.api.ITCMessageIds;
+import com.nokia.tcf.api.ITCMessageInputStream;
+import com.nokia.tcf.api.ITCMessageOptions;
+import com.nokia.tcf.api.TCFClassFactory;
 
-public class TracingConnectedService extends AbstractConnectedService {
+public class TracingConnectedService extends AbstractConnectedService2 {
 	
 	private static final String OK_STATUS = 
 		Messages.getString("TracingConnectedService.OKStatus"); //$NON-NLS-1$