htiextension/com.nokia.s60tools.hticonnection/src/com/nokia/s60tools/hticonnection/core/HtiConnection.java
changeset 0 61163b28edca
child 7 018264c44c89
equal deleted inserted replaced
-1:000000000000 0:61163b28edca
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 package com.nokia.s60tools.hticonnection.core;
       
    19 
       
    20 import java.util.ArrayList;
       
    21 import java.util.Collection;
       
    22 import java.util.List;
       
    23 import java.util.concurrent.ExecutionException;
       
    24 
       
    25 import org.eclipse.swt.SWT;
       
    26 import org.eclipse.swt.widgets.Display;
       
    27 import org.eclipse.ui.PartInitException;
       
    28 
       
    29 import com.nokia.carbide.remoteconnections.RemoteConnectionsActivator;
       
    30 import com.nokia.carbide.remoteconnections.interfaces.IConnectedService;
       
    31 import com.nokia.carbide.remoteconnections.interfaces.IConnection;
       
    32 import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus;
       
    33 import com.nokia.carbide.remoteconnections.interfaces.IConnectedService.IStatus.EStatus;
       
    34 import com.nokia.carbide.remoteconnections.interfaces.IConnectionsManager.IConnectionsManagerListener;
       
    35 import com.nokia.s60tools.hticonnection.HtiApiActivator;
       
    36 import com.nokia.s60tools.hticonnection.actions.OpenPreferencePageAction;
       
    37 import com.nokia.s60tools.hticonnection.connection.HTIConnectedService;
       
    38 import com.nokia.s60tools.hticonnection.connection.HTIConnectionStatus;
       
    39 import com.nokia.s60tools.hticonnection.connection.HTIService;
       
    40 import com.nokia.s60tools.hticonnection.gateway.DataGatewayManager;
       
    41 import com.nokia.s60tools.hticonnection.listener.HtiConnectionManager;
       
    42 import com.nokia.s60tools.hticonnection.preferences.HtiApiPreferenceConstants;
       
    43 import com.nokia.s60tools.hticonnection.preferences.HtiApiPreferencePage;
       
    44 import com.nokia.s60tools.hticonnection.resources.Messages;
       
    45 import com.nokia.s60tools.hticonnection.services.HTIVersion;
       
    46 import com.nokia.s60tools.hticonnection.ui.dialogs.ErrorDialogWithHelp;
       
    47 import com.nokia.s60tools.hticonnection.ui.dialogs.HtiApiMessageBox;
       
    48 import com.nokia.s60tools.hticonnection.ui.views.main.MainView;
       
    49 import com.nokia.s60tools.util.cmdline.UnsupportedOSException;
       
    50 
       
    51 /**
       
    52  * This class manages current connection and holds it status information.
       
    53  */
       
    54 public class HtiConnection implements IConnectionsManagerListener {
       
    55 
       
    56 	/**
       
    57 	 * Status of current connection. Used to device if new requests should
       
    58 	 * be accepted. Connection is in shutdown status when plug-in is started.
       
    59 	 */
       
    60 	private ConnectionStatus currentStatus = ConnectionStatus.SHUTDOWN;
       
    61 	
       
    62 	/**
       
    63 	 * Thread is used to test connection when connection has been started.
       
    64 	 */
       
    65 	private ConnectionCheckerThread connectionChecker = null;
       
    66 	
       
    67 	/**
       
    68 	 * Instance of this singleton class.
       
    69 	 */
       
    70 	private static HtiConnection instance = null;
       
    71 
       
    72 	/**
       
    73 	 * HTI version to which HTI Connection is currently connected.
       
    74 	 */
       
    75 	private HTIVersion version = null;
       
    76 	
       
    77 	/**
       
    78 	 * Currently used connection.
       
    79 	 */
       
    80 	private IConnection currentConnection = null;
       
    81 	
       
    82 	/**
       
    83 	 * Stores instance of data gateway, that is used for communication between HTI API and device.
       
    84 	 */
       
    85 	private DataGatewayManager gatewayManager = null;
       
    86 	
       
    87 	/**
       
    88 	 * Enumeration for status of the current connection.
       
    89 	 */
       
    90 	public enum ConnectionStatus {
       
    91 		SHUTDOWN, // Connection has been shut down.
       
    92 		TESTING,  // Testing connection. Used when testing connection from preferences.
       
    93 		CONNECTING, //  Connection is just started or there have been problems in connection.
       
    94 		CONNECTED // Connection is working.
       
    95 	};
       
    96 	
       
    97 	/**
       
    98 	 * Private constructor to prevent creating new instances.
       
    99 	 */
       
   100 	private HtiConnection(){
       
   101 		gatewayManager = new DataGatewayManager();
       
   102 	}
       
   103 	
       
   104 	/**
       
   105 	 * Only one instance can exist at one time.
       
   106 	 * @return Current instance.
       
   107 	 */
       
   108 	public static synchronized HtiConnection getInstance(){
       
   109 		if( instance == null ){
       
   110 			instance = new HtiConnection();
       
   111 		}
       
   112 		return instance;
       
   113 	}
       
   114 	
       
   115 	/**
       
   116 	 * Initializes listeners and settings.
       
   117 	 */
       
   118 	public void init() {
       
   119 		RemoteConnectionsActivator.getConnectionsManager().addConnectionStoreChangedListener(this);
       
   120 		currentConnection = HtiApiActivator.getPreferences().getCurrentConnection();
       
   121 	}
       
   122 	
       
   123 	/**
       
   124 	 * Stops thread that checks if connection is up.
       
   125 	 */
       
   126 	public void stop() {
       
   127 		setConnectionStatus(ConnectionStatus.SHUTDOWN);
       
   128 		RemoteConnectionsActivator.getConnectionsManager().removeConnectionStoreChangedListener(this);
       
   129 		connectionChecker = null;
       
   130 		
       
   131 		if(gatewayManager != null){
       
   132 			stopConnection();
       
   133 		}
       
   134 	}
       
   135 	
       
   136 	/**
       
   137 	 * Starts connection with current settings.
       
   138 	 * @param isTesting True if connection is started only to test connection settings.
       
   139 	 * @return True if connection was started successfully. False otherwise.
       
   140 	 */
       
   141 	public boolean startConnection(boolean isTesting) {
       
   142 		IConnection connection = getCurrentConnection(); 
       
   143 		if(gatewayManager.isReady()) {
       
   144 			// Old gateway needs to be stopped before starting new.
       
   145 			stopConnection();
       
   146 		}
       
   147 		
       
   148 		if(connection == null) {
       
   149 			String msg;
       
   150 			List<IConnection> htiConns = getHTIConnections();
       
   151 			if(htiConns.size() > 0) {
       
   152 				msg = new String(Messages.getString("HtiConnection.ConnectionNotSelected_ErrMsg")); //$NON-NLS-1$
       
   153 			} else {
       
   154 				msg = new String(Messages.getString("HtiConnection.NoConnections_ErrMsg")); //$NON-NLS-1$
       
   155 			}
       
   156 			
       
   157 			ErrorDialogRunnable runnable = new ErrorDialogRunnable(msg);
       
   158 			Display.getDefault().asyncExec(runnable);
       
   159 			return false;
       
   160 		}
       
   161 		
       
   162 		// Connection status needs to be set before starting gateway, so that connection is set to use.
       
   163 		ConnectionStatus status = (isTesting) ? ConnectionStatus.TESTING : ConnectionStatus.CONNECTING;
       
   164 		setConnectionStatus(status);
       
   165 		
       
   166 		return startGateway(connection, isTesting);
       
   167 	}
       
   168 	
       
   169 	/**
       
   170 	 * Starts datagateway with current settings.
       
   171 	 * @param isTesting True if datagateway is started only to test connection settings.
       
   172 	 * @return True if datagateway was started successfully. False otherwise.
       
   173 	 */
       
   174 	private boolean startGateway(IConnection connection, boolean isTesting) {
       
   175 		try {
       
   176 			boolean started = false;
       
   177 			// Connection status needs to be checked here, because setting connection status can take a while,
       
   178 			// when connection is set in to use. User could have stopped the connection during that time.
       
   179 			if(getConnectionStatus() != ConnectionStatus.SHUTDOWN) {
       
   180 				// Connection string needs to be updated, before starting connection.
       
   181 				// Otherwise old information might be shown.
       
   182 				started = gatewayManager.startGateway(connection, isTesting);
       
   183 			}
       
   184 			
       
   185 			if(started && !isTesting) {
       
   186 				// Connection needs to be tested after datagateway has been started.
       
   187 				connectionChecker = new ConnectionCheckerThread();
       
   188 				connectionChecker.start();
       
   189 			}
       
   190 			else if(!started) {
       
   191 				setConnectionStatus(ConnectionStatus.SHUTDOWN);
       
   192 			}
       
   193 			
       
   194 			return started;
       
   195 		
       
   196 		} catch (UnsupportedOSException e) {
       
   197 			Runnable runnable = new Runnable() {
       
   198 				public void run() {
       
   199 					// Only Windows operating system is supported.
       
   200 					String errMsg = Messages.getString("HtiConnection.FailedToStartGateway_ErrMsg"); //$NON-NLS-1$
       
   201 					HtiApiMessageBox msgBox = new HtiApiMessageBox(errMsg, SWT.ICON_ERROR | SWT.OK);
       
   202 					msgBox.open();
       
   203 				}
       
   204 				
       
   205 			};
       
   206 			// Messagebox needs to be opened from UI thread.
       
   207 			Display.getDefault().asyncExec(runnable);
       
   208 			
       
   209 			return false;
       
   210 		}
       
   211 	}
       
   212 	
       
   213 	/**
       
   214 	 * Stops datagateway.
       
   215 	 */
       
   216 	public void stopConnection() {
       
   217 		setConnectionStatus(ConnectionStatus.SHUTDOWN);
       
   218 		gatewayManager.stopGateway();
       
   219 	}
       
   220 	
       
   221 	/**
       
   222 	 * Tests given connection. Shuts down existing connection.
       
   223 	 * This method is synchronized, because there can come multiple test
       
   224 	 * request at the same time from Remote Connections.
       
   225 	 */
       
   226 	public synchronized IStatus testConnection(IConnection testConnection) {
       
   227 		
       
   228 		IConnection origConn = getCurrentConnection();
       
   229 		
       
   230 		EStatus testStatus = EStatus.UNKNOWN;
       
   231 		String shortDesc = Messages.getString("HtiConnection.NotConnected_StatusMsg"); //$NON-NLS-1$
       
   232 		String longDesc = Messages.getString("HtiConnection.ConnectionFailed_StatusMsg"); //$NON-NLS-1$
       
   233 		
       
   234 		try {
       
   235 			// Existing gateway needs to be stopped.
       
   236 			stopConnection();
       
   237 			
       
   238 			// New connection should be defined.
       
   239 			setCurrentConnection(testConnection, true);
       
   240 			
       
   241 			// Gateway can be started now.
       
   242 			if(startConnection(true)) {
       
   243 				if(RequestQueueManager.getInstance().testConnection()) {
       
   244 					HTIVersion version = getHTIVersion();
       
   245 					testStatus = EStatus.UP;
       
   246 					shortDesc = Messages.getString("HtiConnection.Connected_StatusMsg"); //$NON-NLS-1$
       
   247 					longDesc = Messages.getString("HtiConnection.Connected_LongStatusMsg") + version.toString(); //$NON-NLS-1$
       
   248 				} else {
       
   249 					testStatus = EStatus.DOWN;
       
   250 					shortDesc = Messages.getString("HtiConnection.NotConnected_StatusMsg"); //$NON-NLS-1$
       
   251 					longDesc = Messages.getString("HtiConnection.ConnectionFailed_StatusMsg"); //$NON-NLS-1$
       
   252 				}
       
   253 			} else {
       
   254 				testStatus = EStatus.DOWN;
       
   255 				shortDesc = Messages.getString("HtiConnection.NotConnected_StatusMsg"); //$NON-NLS-1$
       
   256 				longDesc = Messages.getString("HtiConnection.FailedToStartGateway_StatusMsg"); //$NON-NLS-1$
       
   257 			}
       
   258 			
       
   259 		} catch (Exception e) {
       
   260 			if (e.getMessage().equals("com.nokia.HTI.HTIException: HTI NOT INITIALIZED")) { //$NON-NLS-1$
       
   261 				// HTI agent is not responding
       
   262 				testStatus = EStatus.DOWN;
       
   263 				shortDesc = Messages.getString("HtiConnection.NotConnected_StatusMsg"); //$NON-NLS-1$
       
   264 				longDesc = Messages.getString("HtiConnection.HtiNotResponding_StatusMsg"); //$NON-NLS-1$
       
   265 			} else {
       
   266 				// Connection could not be created
       
   267 				testStatus = EStatus.DOWN;
       
   268 				shortDesc = Messages.getString("HtiConnection.NotConnected_StatusMsg"); //$NON-NLS-1$
       
   269 				longDesc = Messages.getString("HtiConnection.ConnectionFailed_StatusMsg"); //$NON-NLS-1$
       
   270 			}
       
   271 		} finally {
       
   272 			stopConnection();
       
   273 			setCurrentConnection(origConn, false);
       
   274 		}
       
   275 		
       
   276 		return new HTIConnectionStatus(null, testStatus, shortDesc, longDesc);
       
   277 	}
       
   278 	
       
   279 	/**
       
   280 	 * Set HTI version to which HTI Connection is currently connected.
       
   281 	 * @param version HTI version to which HTI Connection is currently connected.
       
   282 	 */
       
   283 	public void setHTIVersion(HTIVersion version) {
       
   284 		this.version = version;
       
   285 	}
       
   286 	
       
   287 	/**
       
   288 	 * Get HTI version to which HTI Connection is currently connected.
       
   289 	 * @return HTI version to which HTI Connection is currently connected,
       
   290 	 * or null if connection is down.
       
   291 	 */
       
   292 	public HTIVersion getHTIVersion() {
       
   293 		return version;
       
   294 	}
       
   295 	
       
   296 	/**
       
   297 	 * Returns all connections which support connection types that HTI Connection can use. 
       
   298 	 * @return List of connections that support connection types that HTI Connection can use.
       
   299 	 */
       
   300 	public List<IConnection> getHTIConnections() {
       
   301 		
       
   302 		// Getting needed variables.
       
   303 		Collection<IConnection> connections = RemoteConnectionsActivator.getConnectionsManager().getConnections();
       
   304 		Collection<String> connectionTypes = HTIService.getCompatibleConnectionTypeIds();
       
   305 		List<IConnection> htiConnections = new ArrayList<IConnection>();
       
   306 		
       
   307 		// Going through all connection.
       
   308 		for(IConnection conn : connections) {	
       
   309 			if(connectionTypes.contains(conn.getConnectionType().getIdentifier())) {
       
   310 				htiConnections.add(conn);
       
   311 			}
       
   312 		}
       
   313 		
       
   314 		return htiConnections;
       
   315 	}
       
   316 	
       
   317 	/**
       
   318 	 * Returns current status of connection.
       
   319 	 * @return Current status of connection.
       
   320 	 */
       
   321 	public ConnectionStatus getConnectionStatus() {
       
   322 		synchronized(currentStatus) {
       
   323 			return currentStatus;
       
   324 		}
       
   325 	}
       
   326 
       
   327 	/**
       
   328 	 * Updates connection status in views description.
       
   329 	 */
       
   330 	public void updateConnectionStatus() {
       
   331 		Runnable updater = new ConnectionStatusUpdater(getCurrentConnection());
       
   332 		// Updating connection status asynchronously in default UI thread.
       
   333 		Display.getDefault().asyncExec(updater);
       
   334 	}
       
   335 	
       
   336 	/**
       
   337 	 * Sets current status of connection.
       
   338 	 * @param currentStatus The currentStatus to set.
       
   339 	 */
       
   340 	public void setConnectionStatus(ConnectionStatus newStatus) {
       
   341 		// Flagging status change information.
       
   342 		boolean connectionStarted = false;
       
   343 		boolean connectionTerminated = false;
       
   344 		boolean connectionUp = false;
       
   345 		boolean connectionDown = false;
       
   346 		boolean needsUpdate = false;
       
   347 		
       
   348 		// Checking new status and updating current status.
       
   349 		synchronized(currentStatus) {
       
   350 			if (newStatus == ConnectionStatus.SHUTDOWN
       
   351 					&& currentStatus != ConnectionStatus.SHUTDOWN) {
       
   352 				// Shutting down the connection and connection tester.
       
   353 				connectionChecker = null;
       
   354 				connectionDown = true;
       
   355 			}
       
   356 			else if (newStatus == ConnectionStatus.CONNECTED
       
   357 					&& currentStatus != ConnectionStatus.CONNECTED) {
       
   358 				connectionUp = true;
       
   359 			}
       
   360 			else if (newStatus != ConnectionStatus.CONNECTED
       
   361 					&& currentStatus == ConnectionStatus.CONNECTED) {
       
   362 				connectionDown = true;
       
   363 			}
       
   364 			
       
   365 			// Checking if it is needed to start/stop using current connection.
       
   366 			if (newStatus != ConnectionStatus.SHUTDOWN
       
   367 					&& currentStatus == ConnectionStatus.SHUTDOWN) {
       
   368 				connectionStarted = true;
       
   369 			}
       
   370 			else if (newStatus == ConnectionStatus.SHUTDOWN
       
   371 					&& currentStatus != ConnectionStatus.SHUTDOWN) {
       
   372 				connectionTerminated = true;
       
   373 			}
       
   374 			
       
   375 			needsUpdate = (currentStatus != newStatus);
       
   376 			currentStatus = newStatus;
       
   377 		} // End synchronized
       
   378 		
       
   379 		// Updating and informing outside of the synchronized block to prevent
       
   380 		// synchronization slowing down connection status queries.
       
   381 		
       
   382 		if(needsUpdate) {
       
   383 			updateConnectionStatus();
       
   384 		}
       
   385 		
       
   386 		if(connectionUp) {
       
   387 			// Inform listeners of starting the connection
       
   388 			HtiConnectionManager.getInstance().informConnectionStarted();
       
   389 		}
       
   390 		else if(connectionDown) {
       
   391 			// Inform listeners of connection termination
       
   392 			HtiConnectionManager.getInstance().informConnectionTerminated();
       
   393 			setHTIVersion(null);
       
   394 			RequestQueueManager.getInstance().cancelRequestsInQueue();
       
   395 		}
       
   396 		
       
   397 		if(connectionStarted) {
       
   398 			// Connection needs to be set as used, before starting datagateway.
       
   399 			// This must be done as last operation, because useConnection can take some time and
       
   400 			// it is good to update other components first to prevent information lagging behind.
       
   401 			IConnection conn = getCurrentConnection();
       
   402 			if(conn != null) {
       
   403 				conn.useConnection(true);
       
   404 			}
       
   405 		}
       
   406 		else if(connectionTerminated) {
       
   407 			// Connection is not needed anymore.
       
   408 			IConnection conn = getCurrentConnection();
       
   409 			if(conn != null) {
       
   410 				conn.useConnection(false);
       
   411 			}
       
   412 		}
       
   413 	}
       
   414 	
       
   415 	/**
       
   416 	 * Shows message to user if exception is caused by communication problems.
       
   417 	 * This method also changes connection state to CONNECTNG, so service won't accept further requests.
       
   418 	 * @param exception Exception to be checked and reported.
       
   419 	 * @return Returns true if error was reported and connection is set to CONNECTING state, false otherwise.
       
   420 	 */
       
   421 	public boolean reportConnectionError(ExecutionException exception) {
       
   422 		
       
   423 		String msg;
       
   424 		
       
   425 		// Checking if there are problems with connection and handling problems.
       
   426 		if (exception.getMessage().equals("com.nokia.HTI.HTIException: HTI NOT INITIALIZED")) { //$NON-NLS-1$
       
   427 			msg = Messages.getString("HtiConnection.HtiNotResponding_MsgBoxMsg"); //$NON-NLS-1$
       
   428 		}
       
   429 		else if( exception.getMessage().equals("java.net.ConnectException: Connection refused: connect")) { //$NON-NLS-1$
       
   430 			msg = Messages.getString("HtiConnection.ConnectionFailed_MsgBoxMsg"); //$NON-NLS-1$
       
   431 		}
       
   432 		else {
       
   433 			// HTI was initialized correctly and connection was established.
       
   434 			// So this shouldn't be connection issue and no need to change to CONNECTING state.
       
   435 			return false;
       
   436 		}
       
   437 		
       
   438 		if(HtiConnection.getInstance().getConnectionStatus() != ConnectionStatus.SHUTDOWN) {
       
   439 			// Setting connection status to testing state here to prevent extra error messages.
       
   440 			HtiConnection.getInstance().setConnectionStatus(ConnectionStatus.CONNECTING);
       
   441 		}
       
   442 		
       
   443 		ErrorDialogRunnable runnable = new ErrorDialogRunnable(msg);
       
   444 		Display.getDefault().asyncExec(runnable);
       
   445 		return true;
       
   446 	}
       
   447 	
       
   448 	/**
       
   449 	 * Sets currently used connection. Saves connection to preferences, if it isn't a test connection.
       
   450 	 * @param currentConnection Connection to be set.
       
   451 	 * @param isTestConnection True if connection is set for test purposes. False otherwise.
       
   452 	 */
       
   453 	public synchronized void setCurrentConnection(IConnection connection, boolean isTestConnection) {
       
   454 		if(currentConnection != null && currentConnection != connection) {
       
   455 			// Connection can be set as not used, because HTI Connection uses only currentConnection.
       
   456 			currentConnection.useConnection(false);
       
   457 		}
       
   458 		this.currentConnection = connection;
       
   459 		
       
   460 		if(!isTestConnection) {
       
   461 			// ID of normal connection need to be saved to preferences so that it will be used later as default.
       
   462 			String connectionID = (currentConnection == null) ? HtiApiPreferenceConstants.DEFAULT_CONNECTION_ID 
       
   463 					: currentConnection.getIdentifier();
       
   464 			if (!connectionID.equals(HtiApiActivator.getPreferences().getConnectionID())) {
       
   465 				HtiApiActivator.getPreferences().setConnectionID(connectionID);
       
   466 			}
       
   467 		}
       
   468 	}
       
   469 	
       
   470 	/**
       
   471 	 * Gets currently used connection.
       
   472 	 * @return Currently used connection, or <code>null</code> if connection has not been set.
       
   473 	 */
       
   474 	public synchronized IConnection getCurrentConnection() {
       
   475 		return currentConnection;
       
   476 	}
       
   477 
       
   478 	/* (non-Javadoc)
       
   479 	 * @see com.nokia.carbide.remoteconnections.interfaces.IConnectionsManager.IConnectionsManagerListener#connectionStoreChanged()
       
   480 	 */
       
   481 	public void connectionStoreChanged() {
       
   482 		// Initializing needed variables.
       
   483 		IConnection currConn = getCurrentConnection();
       
   484 		if(currConn == null) {
       
   485 			// Nothing to do, if no connection is selected.
       
   486 			return;
       
   487 		}
       
   488 		String connID = currConn.getIdentifier();
       
   489 		Collection<IConnection> connections = RemoteConnectionsActivator.getConnectionsManager().getConnections();
       
   490 		
       
   491 		// Checking if current connection still exists.
       
   492 		boolean isFound = false;
       
   493 		for(IConnection conn : connections) {	
       
   494 			if(conn.getIdentifier().equals(connID)) {
       
   495 				isFound = true;
       
   496 				break;
       
   497 			}
       
   498 		}
       
   499 		
       
   500 		if(!isFound) {
       
   501 			// Connection doesn't exist anymore. Setting current connection as null.
       
   502 			setCurrentConnection(null, false);
       
   503 		}
       
   504 	}
       
   505 
       
   506 	/* (non-Javadoc)
       
   507 	 * @see com.nokia.carbide.remoteconnections.interfaces.IConnectionsManager.IConnectionsManagerListener#displayChanged()
       
   508 	 */
       
   509 	public void displayChanged() {
       
   510 		// Not implemented.
       
   511 	}
       
   512 	
       
   513 	//
       
   514 	// Private classes.
       
   515 	//
       
   516 	
       
   517 	/**
       
   518 	 * Thread that tests connection.
       
   519 	 * Connection needs to be tested when new connection has been started
       
   520 	 * or there has been problems with current connection.
       
   521 	 */
       
   522 	private class ConnectionCheckerThread extends Thread {
       
   523 		
       
   524 		/**
       
   525 		 * Time in ms that is waited between testing the connection.
       
   526 		 */
       
   527 		private static final long TEST_DELAY = 1000;
       
   528 		
       
   529 		/**
       
   530 		 * Keeps track for first connection try. This is needed if there
       
   531 		 * happens connection error when testing connection first time.
       
   532 		 * On other times connection failure information comes from outside
       
   533 		 * of this class.
       
   534 		 */
       
   535 		private boolean firstConnection = true;
       
   536 		
       
   537 		/* (non-Javadoc)
       
   538 		 * @see java.lang.Thread#run()
       
   539 		 */
       
   540 		public void run() {
       
   541 			Thread thisThread = Thread.currentThread();
       
   542 			while(thisThread == connectionChecker) {
       
   543 				
       
   544 				if(getConnectionStatus() == ConnectionStatus.CONNECTING) {
       
   545 					testConnection();
       
   546 				}
       
   547 				
       
   548 				try {
       
   549 					Thread.sleep(TEST_DELAY);
       
   550 				} catch (InterruptedException e) {
       
   551 					// Not needed to handle. Just continuing polling in this case.
       
   552 				}
       
   553 			}
       
   554 		}
       
   555 		
       
   556 		/**
       
   557 		 * Tests if current connection works and modifies connection status
       
   558 		 * in HtiApiActivator class if needed.
       
   559 		 */
       
   560 		private void testConnection() {
       
   561 			try {
       
   562 				boolean connectionUp = RequestQueueManager.getInstance().testConnection();
       
   563 				
       
   564 				if(connectionUp) {
       
   565 					setConnectionStatus(ConnectionStatus.CONNECTED);
       
   566 				}
       
   567 				
       
   568 			} catch (ExecutionException e) {
       
   569 				if(firstConnection && getConnectionStatus() != ConnectionStatus.SHUTDOWN) {
       
   570 					// Other than first connection errors are reported from RequestQueueManager.
       
   571 					// This handles only first connection problem when trying to connect to the device.
       
   572 					reportConnectionError(e);
       
   573 				}
       
   574 			} catch (Exception e) {
       
   575 				// Catching other errors that doesn't need any specific actions.
       
   576 			}
       
   577 			
       
   578 			firstConnection = false;
       
   579 		}
       
   580 	}
       
   581 	
       
   582 	/**
       
   583 	 * Updates connection status and buttons in UI.
       
   584 	 */
       
   585 	private class ConnectionStatusUpdater implements Runnable {
       
   586 
       
   587 		/**
       
   588 		 * Connection that needs status update.
       
   589 		 */
       
   590 		private final IConnection onnectionToUpdate;
       
   591 
       
   592 		/**
       
   593 		 * Constructor.
       
   594 		 * @param onnectionToUpdate Connection that needs status update.
       
   595 		 */
       
   596 		public ConnectionStatusUpdater(IConnection onnectionToUpdate) {
       
   597 			this.onnectionToUpdate = onnectionToUpdate;
       
   598 		}
       
   599 
       
   600 		/* (non-Javadoc)
       
   601 		 * @see java.lang.Runnable#run()
       
   602 		 */
       
   603 		public void run() {
       
   604 			
       
   605 			// Connection status needs to be updated in connected service.
       
   606 			if(onnectionToUpdate != null) {
       
   607 				Collection<IConnectedService> services = RemoteConnectionsActivator.getConnectionsManager().getConnectedServices(onnectionToUpdate);
       
   608 				// Collection can be null if getting services for test connection.
       
   609 				if(services != null) {
       
   610 					for(IConnectedService service : services) {
       
   611 						if(service instanceof HTIConnectedService) {
       
   612 							((HTIConnectedService)service).refreshStatus();
       
   613 						}
       
   614 					}
       
   615 				}
       
   616 			}
       
   617 			
       
   618 			try {
       
   619 				MainView view = MainView.getViewInstance(false);
       
   620 				view.updateActionButtonStates();
       
   621 				
       
   622 				// Updating connection description.
       
   623 				switch (getConnectionStatus()) {
       
   624 				case CONNECTED:
       
   625 					view.updateDescription(Messages.getString("HtiConnection.Connected_ToolBar_Msg") + onnectionToUpdate.getDisplayName()); //$NON-NLS-1$
       
   626 					break;
       
   627 				case CONNECTING:
       
   628 					view.updateDescription(Messages.getString("HtiConnection.Connecting_ToolBar_Msg") + onnectionToUpdate.getDisplayName()); //$NON-NLS-1$
       
   629 					break;
       
   630 				case SHUTDOWN:
       
   631 					view.updateDescription(Messages.getString("HtiConnection.NotConnected_ToolBar_Msg")); //$NON-NLS-1$
       
   632 					break;
       
   633 				case TESTING:
       
   634 					view.updateDescription(Messages.getString("HtiConnection.Testing_ToolBar_Msg")); //$NON-NLS-1$
       
   635 					break;
       
   636 				}
       
   637 			} catch (PartInitException e) {
       
   638 				// No need to handle. Description doesn't need update if part is not visible.
       
   639 			}
       
   640 		}
       
   641 	}
       
   642 	
       
   643 	/**
       
   644 	 * Runnable that opens error message box.
       
   645 	 */
       
   646 	private class ErrorDialogRunnable implements Runnable {
       
   647 
       
   648 		/**
       
   649 		 * Error message.
       
   650 		 */
       
   651 		private final String errorMessage;
       
   652 
       
   653 		/**
       
   654 		 * Constructor.
       
   655 		 * @param errorMessage Message to be shown in dialog.
       
   656 		 */
       
   657 		public ErrorDialogRunnable(String errorMessage) {
       
   658 			this.errorMessage = errorMessage;
       
   659 		}
       
   660 		
       
   661 		/* (non-Javadoc)
       
   662 		 * @see java.lang.Runnable#run()
       
   663 		 */
       
   664 		public void run() {
       
   665 			
       
   666 			// No need to show error message if preferences page is already created.
       
   667 			if(HtiApiPreferencePage.isCreated()) {
       
   668 				// Showing plain error message if preferences page is open.
       
   669 				ErrorDialogWithHelp msgBox = new ErrorDialogWithHelp(errorMessage, SWT.OK);
       
   670 				msgBox.open();
       
   671 			} else {
       
   672 				// Asking if user wants to manage preferences.
       
   673 				String msgWithQuestionStr = errorMessage + Messages.getString("HtiConnection.ManageConnections_ErrMsg"); //$NON-NLS-1$
       
   674 				
       
   675 				ErrorDialogWithHelp msgBox = new ErrorDialogWithHelp(msgWithQuestionStr, SWT.YES | SWT.NO);
       
   676 				int result = msgBox.open();
       
   677 				if(result == SWT.YES && !HtiApiPreferencePage.isCreated()){
       
   678 					// Opening preferences if Yes is selected.
       
   679 					OpenPreferencePageAction openPreferencesAction = new OpenPreferencePageAction();
       
   680 					openPreferencesAction.run();
       
   681 				}
       
   682 			}
       
   683 		}
       
   684 	}
       
   685 }