debuggercdi/com.nokia.carbide.trk.support/src/com/nokia/carbide/trk/support/status/ConnectionStatusReconciler.java
branchRCL_2_4
changeset 860 fd6ae4e6e3d9
child 932 9eff68f52ec6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debuggercdi/com.nokia.carbide.trk.support/src/com/nokia/carbide/trk/support/status/ConnectionStatusReconciler.java	Mon Feb 01 13:33:02 2010 -0600
@@ -0,0 +1,290 @@
+/**
+* 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.trk.support.status;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.ui.PartInitException;
+
+import com.nokia.carbide.remoteconnections.RemoteConnectionsActivator;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectedService;
+import com.nokia.carbide.remoteconnections.interfaces.IConnection;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectionsManager;
+import com.nokia.carbide.remoteconnections.interfaces.AbstractConnection.ConnectionStatus;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatusChangedListener;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus.EStatus;
+import com.nokia.carbide.remoteconnections.interfaces.IConnectionsManager.IConnectionListener;
+import com.nokia.carbide.remoteconnections.internal.api.IConnection2;
+import com.nokia.carbide.remoteconnections.internal.api.IConnection2.IConnectionStatus;
+import com.nokia.carbide.remoteconnections.internal.api.IConnection2.IConnectionStatus.EConnectionStatus;
+import com.nokia.carbide.trk.support.Messages;
+import com.nokia.carbide.trk.support.connection.USBConnectionType;
+import com.nokia.carbide.trk.support.service.TRKConnectedService;
+import com.nokia.carbide.trk.support.service.TracingConnectedService;
+import com.nokia.cpp.internal.api.utils.ui.RunRunnableWhenWorkbenchVisibleJob;
+import com.nokia.cpp.internal.api.utils.ui.WorkbenchUtils;
+
+/**
+ * A singleton object that manages the device status of dynamic connections
+ * based on the status of the TRK and Tracing services.
+ */
+public class ConnectionStatusReconciler {
+	
+	private static final String CONNECTIONS_VIEW_ID = 
+		"com.nokia.carbide.remoteconnections.view.ConnectionsView"; //$NON-NLS-1$
+
+	private class ConnectionListener implements IConnectionListener {
+
+		public void connectionAdded(IConnection connection) {
+			addConnection(connection);
+		}
+
+		public void connectionRemoved(IConnection connection) {
+			if (connection.equals(userSetCurrentConnection))
+				userSetCurrentConnection = null;
+			removeConnection(connection);
+		}
+		
+		public void currentConnectionSet(IConnection connection) {
+			if (connection != null && !connection.equals(reconcilerSetCurrentConnection))
+				userSetCurrentConnection = connection;
+		}
+		
+	}
+	
+	private class ServiceStatusListener implements IStatusChangedListener {
+
+		public void statusChanged(IStatus status) {
+			handleServiceStatusChange(status);
+		}
+		
+	}
+	
+	private static ConnectionStatusReconciler instance;
+	private IConnectionsManager manager;
+	private IConnectionListener connectionListener;
+	private List<IConnection> handledConnections;
+	private ServiceStatusListener serviceStatusListener;
+	private IConnection reconcilerSetCurrentConnection;
+	private IConnection userSetCurrentConnection;
+	
+	private ConnectionStatusReconciler() {
+		connectionListener = new ConnectionListener();
+		manager = RemoteConnectionsActivator.getConnectionsManager();
+		manager.addConnectionListener(connectionListener);
+		handledConnections = new ArrayList<IConnection>();
+		serviceStatusListener = new ServiceStatusListener();
+	}
+	
+	public static ConnectionStatusReconciler getInstance() {
+		if (instance == null)
+			instance = new ConnectionStatusReconciler();
+		
+		return instance;
+	}
+
+	public void dispose() {
+		manager.removeConnectionListener(connectionListener);
+		for (IConnection connection : new ArrayList<IConnection>(handledConnections)) {
+			removeConnection(connection);
+		}
+	}
+
+	private boolean isDynamic(IConnection connection) {
+		return connection instanceof IConnection2 && ((IConnection2) connection).isDynamic();
+	}
+
+	private boolean isSysTRK(TRKConnectedService service) {
+		String value = service.getProperties().get(TRKConnectedService.PROP_SYS_TRK);
+		return Boolean.parseBoolean(value);
+	}
+	
+	private void addConnection(IConnection connection) {
+		handledConnections.add(connection);
+		for (IConnectedService service : manager.getConnectedServices(connection)) {
+			if (service instanceof TRKConnectedService ||
+					service instanceof TracingConnectedService) {
+				service.addStatusChangedListener(serviceStatusListener);
+			}
+		}
+		showConnectionsView();
+	}
+
+	private void showConnectionsView() {
+		RunRunnableWhenWorkbenchVisibleJob.start(new Runnable() {
+			public void run() {
+				// try to show the connections view to start service testers
+				try {
+					WorkbenchUtils.getView(CONNECTIONS_VIEW_ID);
+				} catch (PartInitException e) {
+				}
+			}
+		});
+	}
+	
+	private void reconcileAsCurrent(IConnection connection) {
+		if (canBeSetToCurrent(connection)) {
+			if (isReady(connection)) { // set as current
+				reconcilerSetCurrentConnection = connection;
+				manager.setCurrentConnection(connection);
+			} else if (isNotReady(connection) && connection.equals(manager.getCurrentConnection())) { 
+				// unset current or set something else current
+				if (isDynamic(connection) && userSetCurrentConnection != null) {
+					manager.setCurrentConnection(userSetCurrentConnection);
+				}
+				else {
+					// look for some other existing connection that is ready
+					for (IConnection c : manager.getConnections()) {
+						if (canBeSetToCurrent(c) && isReady(c)) {
+							reconcilerSetCurrentConnection = connection;
+							manager.setCurrentConnection(connection);
+							return;
+						}
+					}
+					// set to no current connection
+					manager.setCurrentConnection(null);
+				}
+			}
+		}
+	}
+
+	private boolean isReady(IConnection connection) {
+		return equalsConnectionStatus(connection, EConnectionStatus.READY);
+	}
+
+	private boolean isNotReady(IConnection connection) {
+		return equalsConnectionStatus(connection, EConnectionStatus.NOT_READY);
+	}
+	
+	private boolean equalsConnectionStatus(IConnection connection, EConnectionStatus status) {
+		if (connection instanceof IConnection2) {
+			IConnectionStatus connectionStatus = ((IConnection2) connection).getStatus();
+			if (connectionStatus != null)
+				return connectionStatus.getEConnectionStatus().equals(status);
+		}
+		return false;
+	}
+	
+	private boolean canBeSetToCurrent(IConnection connection) {
+		// USB connections for now
+		return USBConnectionType.ID.equals(connection.getConnectionType().getIdentifier());
+	}
+
+	private void reconcileStatus(IConnection connection) {
+		if (!isDynamic(connection)) // don't set status for user generated connections
+			return;
+		
+		boolean isSysTRK = false;
+		EStatus trkStatus = EStatus.UNKNOWN;
+		EStatus traceStatus = EStatus.UNKNOWN;
+		for (IConnectedService service : manager.getConnectedServices(connection)) {
+			if (service instanceof TRKConnectedService) {
+				isSysTRK = isSysTRK((TRKConnectedService) service);
+				trkStatus = service.getStatus().getEStatus();
+			}
+			if (service instanceof TracingConnectedService) {
+				traceStatus = service.getStatus().getEStatus();
+			}
+		}
+		setConnectionStatus((IConnection2) connection, isSysTRK, trkStatus, traceStatus);
+	}
+
+	private void setConnectionStatus(IConnection2 connection, boolean isSysTRK, EStatus trkStatus, EStatus traceStatus) {
+		// use trk status
+		EConnectionStatus connectionStatus = service2ConnectionStatus(trkStatus);
+		// if sys trk, tracing also used
+		if (isSysTRK && connectionStatus.equals(EConnectionStatus.READY)) {
+			connectionStatus = service2ConnectionStatus(traceStatus);
+		}
+
+		String shortDesc = getShortDescriptionForStatus(connectionStatus);
+		StringBuilder longDesc = new StringBuilder(Messages.getString("ConnectionStatusReconciler_TRKServicePrefix")); //$NON-NLS-1$
+		longDesc.append(getServiceStatusString(trkStatus));
+		if (isSysTRK) {
+			longDesc.append(Messages.getString("ConnectionStatusReconciler_TracingServicePrefix")); //$NON-NLS-1$
+			longDesc.append(getServiceStatusString(traceStatus));
+		}
+		
+		connection.setStatus(new ConnectionStatus(connectionStatus, shortDesc, longDesc.toString()));
+	}
+
+	private String getShortDescriptionForStatus(EConnectionStatus connectionStatus) {
+		switch (connectionStatus) {
+			case READY:
+				return Messages.getString("ConnectionStatusReconciler_ReadyLabel"); //$NON-NLS-1$
+			case NOT_READY:
+				return Messages.getString("ConnectionStatusReconciler_NotReadyLabel"); //$NON-NLS-1$
+			case IN_USE:
+				return Messages.getString("ConnectionStatusReconciler_InUseLabel"); //$NON-NLS-1$
+			case IN_USE_DISCONNECTED:
+				return Messages.getString("ConnectionStatusReconciler_DisconnectedLabel"); //$NON-NLS-1$
+			}
+		return ""; //$NON-NLS-1$
+	}
+
+	private String getServiceStatusString(EStatus status) {
+		switch (status) {
+			case UP:
+				return Messages.getString("ConnectionStatusReconciler_availableLabel"); //$NON-NLS-1$
+			case DOWN:
+				return Messages.getString("ConnectionStatusReconciler_unavailableLabel"); //$NON-NLS-1$
+			case IN_USE:
+				return Messages.getString("ConnectionStatusReconciler_inUseLabel_lower"); //$NON-NLS-1$
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	private EConnectionStatus service2ConnectionStatus(EStatus serviceStatus) {
+		switch (serviceStatus) {
+			case UP:
+				return EConnectionStatus.READY;
+			case DOWN:
+				return EConnectionStatus.NOT_READY;
+			case IN_USE:
+				return EConnectionStatus.IN_USE;
+		}
+		return EConnectionStatus.NONE;
+	}
+
+	private void removeConnection(IConnection connection) {
+		handledConnections.remove(connection);
+	}
+
+	private IConnection findConnection(IConnectedService cs) {
+		for (IConnection connection : handledConnections) {
+			for (IConnectedService connectedService : manager.getConnectedServices(connection)) {
+				if (cs.equals(connectedService))
+					return connection;
+			}
+		}
+		return null;
+	}
+
+	public void handleServiceStatusChange(IStatus status) {
+		IConnectedService service = status.getConnectedService();
+		IConnection connection = findConnection(service);
+		if (connection instanceof IConnection2) {
+			reconcileStatus((IConnection2) connection);
+		}
+		if (connection != null)
+			reconcileAsCurrent(connection);
+	}
+
+}