[473086][dstore] enableProtocols() calls setEnabledCipherSuites(), not
setEnabledProtocols()
diff --git a/rse/plugins/org.eclipse.dstore.core/META-INF/MANIFEST.MF b/rse/plugins/org.eclipse.dstore.core/META-INF/MANIFEST.MF
index a301609..3acd1de 100644
--- a/rse/plugins/org.eclipse.dstore.core/META-INF/MANIFEST.MF
+++ b/rse/plugins/org.eclipse.dstore.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.dstore.core
-Bundle-Version: 3.2.21.qualifier
+Bundle-Version: 3.2.22.qualifier
 Bundle-Activator: org.eclipse.dstore.core.Activator
 Bundle-Localization: plugin
 Require-Bundle: org.eclipse.ui,
diff --git a/rse/plugins/org.eclipse.dstore.core/pom.xml b/rse/plugins/org.eclipse.dstore.core/pom.xml
index b02400d..8d23f07 100644
--- a/rse/plugins/org.eclipse.dstore.core/pom.xml
+++ b/rse/plugins/org.eclipse.dstore.core/pom.xml
@@ -10,7 +10,7 @@
   </parent> 
   <groupId>org.eclipse.tm</groupId>
   <artifactId>org.eclipse.dstore.core</artifactId>
-  <version>3.2.21-SNAPSHOT</version>
+  <version>3.2.22-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 </project>
  
\ No newline at end of file
diff --git a/rse/plugins/org.eclipse.dstore.core/src/org/eclipse/dstore/core/server/ConnectionEstablisher.java b/rse/plugins/org.eclipse.dstore.core/src/org/eclipse/dstore/core/server/ConnectionEstablisher.java
index db8a448..94962db 100644
--- a/rse/plugins/org.eclipse.dstore.core/src/org/eclipse/dstore/core/server/ConnectionEstablisher.java
+++ b/rse/plugins/org.eclipse.dstore.core/src/org/eclipse/dstore/core/server/ConnectionEstablisher.java
@@ -1,781 +1,782 @@
-/*******************************************************************************

- * Copyright (c) 2002, 2015 IBM Corporation and others.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- *

- * Initial Contributors:

- * The following IBM employees contributed to the Remote System Explorer

- * component that contains this file: David McKnight, Kushal Munir,

- * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,

- * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.

- *

- * Contributors:

- * David McKnight  (IBM)   [220123][dstore] Configurable timeout on irresponsiveness

- * David McKnight  (IBM)   [220892][dstore] Backward compatibility: Server and Daemon should support old clients

- * Noriaki Takatsu (IBM)  - [220126] [dstore][api][breaking] Single process server for multiple clients

- * David McKnight     (IBM)   [224906] [dstore] changes for getting properties and doing exit due to single-process capability

- * Jacob Garcowski    (IBM)   [225175] [dstore] error handling change for Client

- * David McKnight   (IBM) - [225507][api][breaking] RSE dstore API leaks non-API types

- * Noriaki Takatsu  (IBM) - [226074] process for getStatus() API

- * Noriaki Takatsu  (IBM) - [226237] [dstore] Move the place where the ServerLogger instance is made

- * David McKnight   (IBM) - [226561] [apidoc] Add API markup to RSE Javadocs where extend / implement is allowed

- * Noriaki Takatsu  (IBM) - [242968] [multithread] serverSocket must be closed when an exception happens in Accept

- * David McKnight   (IBM) - [257321] [dstore] "Error binding socket" should include port of the failed socket

- * Noriaki Takatsu  (IBM) - [283656] [dstore][multithread] Serviceability issue

- * Noriaki Takatsu  (IBM) - [289678][api][breaking] ServerSocket creation in multiple IP addresses

- * David McKnight   (IBM) - [368072] [dstore][ssl] no exception logged upon bind error

- * David McKnight   (IBM) - [371401] [dstore][multithread] avoid use of static variables - causes memory leak after disconnect

- * David McKnight    (IBM) - [388472] [dstore] need alternative option for getting at server hostname

- * David McKnight   (IBM)  - [390681] [dstore] need to merge differences between HEAD stream and 3.2 in ConnectionEstablisher.finished()

- * David McKnight  (IBM)   [439545][dstore] potential deadlock on senders during shutdown

- * David McKnight  (IBM)   [464736][dstore] need methods to disable ciphers and protocols

- *******************************************************************************/

-

-package org.eclipse.dstore.core.server;

-

-import java.io.BufferedWriter;

-import java.io.IOException;

-import java.io.OutputStreamWriter;

-import java.io.PrintWriter;

-import java.net.BindException;

-import java.net.InetAddress;

-import java.net.ServerSocket;

-import java.net.Socket;

-import java.net.UnknownHostException;

-import java.util.ArrayList;

-import java.util.List;

-

-import javax.net.ssl.SSLContext;

-import javax.net.ssl.SSLServerSocket;

-import javax.net.ssl.SSLSession;

-import javax.net.ssl.SSLSocket;

-

-import org.eclipse.dstore.core.model.Client;

-import org.eclipse.dstore.core.model.DE;

-import org.eclipse.dstore.core.model.DataElement;

-import org.eclipse.dstore.core.model.DataStore;

-import org.eclipse.dstore.core.model.DataStoreAttributes;

-import org.eclipse.dstore.core.model.ISSLProperties;

-import org.eclipse.dstore.internal.core.server.ServerAttributes;

-import org.eclipse.dstore.internal.core.server.ServerCommandHandler;

-import org.eclipse.dstore.internal.core.server.ServerReturnCodes;

-import org.eclipse.dstore.internal.core.server.ServerSSLProperties;

-import org.eclipse.dstore.internal.core.server.ServerUpdateHandler;

-import org.eclipse.dstore.internal.core.util.ExternalLoader;

-import org.eclipse.dstore.internal.core.util.Sender;

-import org.eclipse.dstore.internal.core.util.ssl.DStoreSSLContext;

-

-/**

- * ConnectionEstablisher is responsible for managing the server DataStore and

- * facilitating the communication between client and server DataStores.

- *

- * @noextend This class is not intended to be subclassed by clients.

- * @noinstantiate This class is not intended to be instantiated by clients.

- *

- * @since 3.0 moved from non-API to API

- */

-public class ConnectionEstablisher

-{

-

-

-	private ServerSocket _serverSocket;

-	private boolean _continue;

-

-	private ArrayList _receivers;

-

-	private ServerCommandHandler _commandHandler;

-	private ServerUpdateHandler _updateHandler;

-

-	private ServerAttributes _serverAttributes = new ServerAttributes();

-	private DataStore _dataStore;

-

-	private int _maxConnections;

-	private int _timeout;

-	private String _msg;

-	

-

-	private String[] _disabledCipherPatterns = null;

-	private String[] _disabledProtocolPatterns = null;

-	private String[] _enabledCiphers = null;

-	private String[] _enabledProtocols = null;

-	

-

-

-	/**

-	 * Creates the default ConnectionEstablisher.  Communication occurs

-	 * on a default port, there is no timeout and no ticket is required

-	 * for a client to work with the DataStore.

-	 *

-	 */

-	public ConnectionEstablisher()

-	{

-		String port = _serverAttributes.getAttribute(DataStoreAttributes.A_HOST_PORT);

-		setup(port, null, null);

-	}

-

-	/**

-	 * Creates a ConnectionEstablisher.  Communication occurs

-	 * on the specified port, there is no timeout and no ticket is required

-	 * for a client to work with the DataStore.

-	 *

-	 * @param port the number of the socket port

-	 */

-	public ConnectionEstablisher(String port)

-	{

-		setup(port, null, null);

-	}

-

-	/**

-	 * Creates a ConnectionEstablisher.  Communication occurs

-	 * on the specified port, a timeout value indicates the idle wait

-	 * time before shutting down, and no ticket is required

-	 * for a client to work with the DataStore.

-	 *

-	 * @param port the number of the socket port

-	 * @param timeout the idle duration to wait before shutting down

-	 */

-	public ConnectionEstablisher(String port, String timeout)

-	{

-		setup(port, timeout, null);

-	}

-

-	/**

-	 * Creates a ConnectionEstablisher.  Communication occurs

-	 * on the specified port, a timeout value indicates the idle wait

-	 * time before shutting down, and ticket specified the required

-	 * ticket for a client to present in order to work with the DataStore.

-	 *

-	 * @param port the number of the socket port

-	 * @param timeout the idle duration to wait before shutting down

-	 * @param ticket validation id required by the client to access the DataStore

-	 */

-	public ConnectionEstablisher(String port, String timeout, String ticket)

-	{

-		setup(port, timeout, ticket);

-	}

-	

-	/**

-	 * Creates a ConnectionEstablisher.  Communication occurs

-	 * on the specified port and the specified IP address, 

-	 * a timeout value indicates the idle wait time

-	 * before shutting down, and ticket specified the required

-	 * ticket for a client to present in order to work with the DataStore.

-	 *

-	 * @param port the number of the socket port

-	 * @param backlog listen backlog

-	 * @param bindAddr the local IP address to bind to

-	 * @param timeout the idle duration to wait before shutting down

-	 * @param ticket validation id required by the client to access the DataStore

-	 * @since 3.2

-	 */

-	public ConnectionEstablisher(String port, int backlog, InetAddress bindAddr, String timeout, String ticket)

-	{

-		setup(port, backlog, bindAddr, timeout, ticket);

-	}

-

-

-	/**

-	 * Starts the run loop for the ConnectionEstablisher.

-	 */

-	public void start()

-	{

-		run();

-	}

-

-

-

-	/**

-	 * Returns the DataStore.

-	 *

-	 * @return the DataStore

-	 */

-	public DataStore getDataStore()

-	{

-		return _dataStore;

-	}

-

-	/**

-	 * Return the Server port opened for this client

-	 *

-	 * @return the Server port opened for this client

-	 */

-	public int getServerPort()

-	{

-		if (_serverSocket != null)

-		{

-			return _serverSocket.getLocalPort();

-		}

-

-		return -1;

-	}

-

-	/**

-	 * Return the connection status for this client

-	 *

-	 * * @return the connection status for this client

-	 */

-	public String getStatus()

-	{

-		return _msg;

-	}

-

-	/**

-	 * Tells the connection establisher to clean up and shutdown

-	 */

-	public void finished(ServerReceiver receiver)

-	{

-		if (_dataStore.getClient() != null) {

-			_dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher.finished()"); //$NON-NLS-1$

-		}

-		

-		if (_dataStore.getClient() != null) {

-			_dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - removing receiver"); //$NON-NLS-1$

-		}

-		_receivers.remove(receiver);

-		

-		if (_dataStore.getClient() != null) {

-			_dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - removing preference listener"); //$NON-NLS-1$

-		}	

-		_dataStore.removeDataStorePreferenceListener(receiver);

-		//if (_receivers.size() == 0)

-		{

-			_continue = false;

-			_commandHandler.finish();			

-			

-			if (_dataStore.getClient() != null) {

-				_dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - finishing update handler"); //$NON-NLS-1$

-			}

-			_updateHandler.finish();

-			

-			if (_dataStore.getClient() != null) {

-				_dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - removing sender"); //$NON-NLS-1$

-			}

-			_updateHandler.removeSenderWith(receiver.socket());

-			

-			if (_dataStore.getClient() != null) {

-				_dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - finishing DataStore"); //$NON-NLS-1$

-			}

-			_dataStore.finish();

-			System.out.println(ServerReturnCodes.RC_FINISHED);

-

-			if (SystemServiceManager.getInstance().getSystemService() == null)

-				System.exit(0);

-		}

-	}

-

-	private void waitForConnections()

-	{

-		while (_continue == true)

-		{

-			try

-			{

-				if (_dataStore.usingSSL())

-				{

-					SSLServerSocket sslServerSocket = (SSLServerSocket)_serverSocket;

-					// for security, disable ciphers and protocols we don't want

-					disableCiphers(sslServerSocket);

-					disableProtocols(sslServerSocket);

-					

-					// for security, enable only ciphers and protocols that are common

-					enableCiphers(sslServerSocket);

-					enableProtocols(sslServerSocket);

-					

-					logAvailableCiphersAndProtocols(sslServerSocket);

-				}

-				

-				Socket newSocket = _serverSocket.accept();

-				if (_dataStore.usingSSL())

-				{

-

-					// wait for connection

-					SSLSocket sslSocket = (SSLSocket)newSocket;

-					sslSocket.setUseClientMode(false);

-					sslSocket.setNeedClientAuth(false);

-					SSLSession session = sslSocket.getSession();

-

-					if (session == null)

-					{

-						System.out.println("handshake failed"); //$NON-NLS-1$

-						sslSocket.close();

-						return;

-					}

-				}

-

-				doHandShake(newSocket);

-				newSocket.setKeepAlive(true);

-

-				ServerReceiver receiver = new ServerReceiver(newSocket, this);

-				_dataStore.addDataStorePreferenceListener(receiver);

-

-				if (_dataStore.getClient() != null)

-				     _dataStore.getClient().setServerReceiver(receiver);

-

-				Sender sender = new Sender(newSocket, _dataStore);

-

-				// add this connection to list of elements

-				_receivers.add(receiver);

-				_updateHandler.addSender(sender);

-

-				receiver.start();

-

-				if (_receivers.size() == 1)

-				{

-					_updateHandler.start();

-					_commandHandler.start();

-				}

-

-				if (_receivers.size() == _maxConnections)

-				{

-					_continue = false;

-					_serverSocket.close();

-

-				}

-			}

-			catch (IOException ioe)

-			{

-				System.err.println(ServerReturnCodes.RC_CONNECTION_ERROR);

-				System.err.println("Server: error initializing socket: " + ioe); //$NON-NLS-1$

-				_msg = ioe.toString();

-				try

-				{

-					_serverSocket.close();

-				}

-				catch (Throwable e)

-				{

-					

-				}

-				_continue = false;

-			}

-		}

-	}

-

-

-

-

-	private ServerSocket createSocket(String portStr, int backlog, InetAddress bindAddr) throws UnknownHostException

-	{

-		ServerSocket serverSocket = null;

-		SSLContext sslContext = null;

-		// port

-		int port = 0;

-

-		if (_dataStore.usingSSL())

-		{

-			String keyStoreFileName = _dataStore.getKeyStoreLocation();

-			String keyStorePassword = _dataStore.getKeyStorePassword();

-

-			try

-			{

-				sslContext = DStoreSSLContext.getServerSSLContext(keyStoreFileName, keyStorePassword);

-			}

-			catch (Exception e)

-			{

-

-			}

-		}

-

-		// determine if portStr is a port range or just a port

-		String[] range = portStr.split("-"); //$NON-NLS-1$

-		if (range.length == 2)

-		{

-			int lPort = 0;

-			int hPort = 0;

-			try

-			{

-				lPort = Integer.parseInt(range[0]);

-				hPort = Integer.parseInt(range[1]);

-			}

-			catch (Exception e)

-			{

-			}

-

-			for (int i = lPort; i < hPort; i++)

-			{

-				// create server socket from port

-				try

-				{

-					if (_dataStore.usingSSL() && sslContext != null)

-					{

-						try

-						{

-							serverSocket = sslContext.getServerSocketFactory().createServerSocket(i, backlog, bindAddr);

-						}

-						catch (BindException e)

-						{

-							_msg = ServerReturnCodes.RC_BIND_ERROR  + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$

-							System.err.println(_msg);

-							_dataStore.trace(_msg);

-						}

-						catch (Exception e)

-						{

-						}

-					}

-					else

-					{

-						try

-						{

-							serverSocket = new ServerSocket(i, backlog, bindAddr);

-						}						

-						catch (BindException e)

-						{

-							_msg = ServerReturnCodes.RC_BIND_ERROR  + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$

-							System.err.println(_msg);

-							_dataStore.trace(_msg);

-						}

-						catch (Exception e)

-						{

-						}

-					}

-				}

-				catch (Exception e)

-				{

-					_dataStore.trace(e);

-				}

-				if (serverSocket != null && serverSocket.getLocalPort() > 0)

-				{

-					return serverSocket;

-				}

-			}

-			if (serverSocket == null){

-				_msg = ServerReturnCodes.RC_BIND_ERROR  + " on ports " + portStr; //$NON-NLS-1$

-				System.err.println(_msg); 				

-			}

-		}

-		else

-		{

-			port = Integer.parseInt(portStr);

-

-

-			// create server socket from port

-			if (_dataStore.usingSSL() && sslContext != null)

-			{

-				try

-				{

-					serverSocket = sslContext.getServerSocketFactory().createServerSocket(port, backlog, bindAddr);

-				}

-				catch (BindException e){

-					_msg = ServerReturnCodes.RC_BIND_ERROR  + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$

-					System.err.println(_msg);

-					_dataStore.trace(_msg);

-				}

-				catch (Exception e)

-				{

-					_dataStore.trace(e);

-				}

-			}

-			else

-			{

-				try

-				{

-					serverSocket = new ServerSocket(port, backlog, bindAddr);

-				}

-				catch (BindException e){

-					_msg = ServerReturnCodes.RC_BIND_ERROR  + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$

-					System.err.println(_msg);

-					_dataStore.trace(_msg);

-				}

-				catch (Exception e)

-				{

-					_dataStore.trace(e);

-				}

-			}

-		}

-		return serverSocket;

-	}

-	

-	/**

-	 * Create the DataStore and initializes it's handlers and communications.

-	 *

-	 * @param portStr the number of the socket port

-	 * @param timeoutStr the idle duration to wait before shutting down

-	 * @param ticketStr validation id required by the client to access the DataStore

-	 */

-	private void setup(String portStr, String timeoutStr, String ticketStr)

-	{

-		setup(portStr, 50, null, timeoutStr, ticketStr);

-	}

-

-	/**

-	 * Create the DataStore and initializes it's handlers and communications.

-	 *

-	 * @param portStr the number of the socket port

-	 * @param backlog listen backlog

-	 * @param bindAddr the local IP address to bind to

-	 * @param timeoutStr the idle duration to wait before shutting down

-	 * @param ticketStr validation id required by the client to access the DataStore

-	 */

-	private void setup(String portStr, int backlog, InetAddress bindAddr, String timeoutStr, String ticketStr)

-	{

-		_maxConnections = 1;

-

-

-		ArrayList loaders = new ArrayList();

-		loaders.add(new ExternalLoader(getClass().getClassLoader(), "*")); //$NON-NLS-1$

-		_commandHandler = new ServerCommandHandler(loaders);

-		_updateHandler = new ServerUpdateHandler();

-

-		ISSLProperties sslProperties = new ServerSSLProperties();

-

-		_dataStore = new DataStore(_serverAttributes, _commandHandler, _updateHandler, null);

-		_dataStore.setSSLProperties(sslProperties);

-

-		DataElement ticket = _dataStore.getTicket();

-		ticket.setAttribute(DE.A_NAME, ticketStr);

-

-		_updateHandler.setDataStore(_dataStore);

-		_commandHandler.setDataStore(_dataStore);

-

-		if (SystemServiceManager.getInstance().getSystemService() == null)

-		{

-			Client client = new Client();

-			_dataStore.setClient(client);

-		     ServerLogger logger = new ServerLogger(_dataStore.getUserPreferencesDirectory());

-    		client.setLogger(logger);

-		}

-

-		_receivers = new ArrayList();

-		_continue = true;

-

-		try

-		{

-

-			_serverSocket = createSocket(portStr, backlog, bindAddr);

-			if (_serverSocket == null)

-			{

-				_continue = false;

-			}

-			else

-			{

-				// timeout

-				if (timeoutStr != null)

-				{

-					_timeout = Integer.parseInt(timeoutStr);

-				}

-				else

-				{

-					_timeout = 120000;

-				}

-

-				if (_timeout > 0)

-				{

-					_serverSocket.setSoTimeout(_timeout);

-				}

-

-				System.err.println(ServerReturnCodes.RC_SUCCESS);

-				System.err.println(_serverSocket.getLocalPort());

-				_msg = ServerReturnCodes.RC_SUCCESS;

-				System.err.println("Server running on: " + ServerAttributes.getHostName()); //$NON-NLS-1$

-			}

-		}

-		catch (UnknownHostException e)

-		{

-			System.err.println(ServerReturnCodes.RC_UNKNOWN_HOST_ERROR + ':' + e.getMessage());

-			_msg = ServerReturnCodes.RC_UNKNOWN_HOST_ERROR;

-			_continue = false;

-		}

-	   catch (BindException e)

-		{

-			System.err.println(ServerReturnCodes.RC_BIND_ERROR + ':' + e.getMessage());

-			_msg = ServerReturnCodes.RC_BIND_ERROR;

-			_continue = false;

-		}

-		catch (IOException e)

-		{

-			System.err.println(ServerReturnCodes.RC_GENERAL_IO_ERROR + ':' + e.getMessage());

-			_msg = ServerReturnCodes.RC_GENERAL_IO_ERROR;

-			_continue = false;

-		}

-		catch (SecurityException e)

-		{

-			System.err.println(ServerReturnCodes.RC_SECURITY_ERROR + ':' + e.getMessage());

-			_msg = ServerReturnCodes.RC_SECURITY_ERROR;

-			_continue = false;

-		}

-	}

-

-	private void run()

-	{

-		waitForConnections();

-	}

- 

-	private void doHandShake(Socket socket)

-	{

-	   	try

-	   	{

-		BufferedWriter bwriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), DE.ENCODING_UTF_8));

-	   		PrintWriter writer = new PrintWriter(bwriter);

-

-	   		String version = DataStoreAttributes.DATASTORE_VERSION;

-	   		String preferenceVersion = System.getProperty("DSTORE_VERSION"); //$NON-NLS-1$

-	   		if (preferenceVersion != null && preferenceVersion.length() > 0){

-	   			version = preferenceVersion;

-	   		}

-			writer.println(version);

-			writer.flush();

-			

-		   if (socket instanceof SSLSocket){ // log the protocol and cipher suite used

-			   SSLSocket sslSocket = (SSLSocket)socket;

-			   SSLSession session = sslSocket.getSession();

-			   String protocol = session.getProtocol();		   

-			   String cipherSuite = session.getCipherSuite();

-			   IServerLogger logger = _dataStore.getClient().getLogger();

-

-			   String cn = getClass().toString();

-			   

-			   logger.logInfo(cn, "SSL/TLS Protocol: "+protocol); //$NON-NLS-1$

-			   logger.logInfo(cn, "SSL/TLS Cipher Suite: " + cipherSuite); //$NON-NLS-1$

-		   }			

-	   	}

-	   	catch (IOException e)

-	   	{

-	   		if (_dataStore.getClient() != null) {

-				_dataStore.getClient().getLogger().logError(this.getClass().toString(), e.toString(), e);

-			}

-	   		System.out.println(e);

-	   	}

-

-	}

-	

-	

-	

-	private void logAvailableCiphersAndProtocols(SSLServerSocket sslSocket){

-	   IServerLogger logger = _dataStore.getClient().getLogger();

-

-	   String cn = getClass().toString();

-	   // list the supported and available ciphers and protocols

-	   logger.logDebugMessage(cn, "SSL/TLS Enabled Cipher Suites:"); //$NON-NLS-1$

-	   String[] enabledSuites = sslSocket.getEnabledCipherSuites();			   

-	   for (int i = 0; i < enabledSuites.length; i++){

-		   String suite = enabledSuites[i];

-		   logger.logDebugMessage(cn, '\t' + suite);

-	   }			   			   

-	   

-	   String[] supportedSuites = sslSocket.getSupportedCipherSuites();

-	   logger.logDebugMessage(cn, "SSL/TLS Supported Cipher Suites:"); //$NON-NLS-1$	   

-	   for (int i = 0; i < supportedSuites.length; i++){

-		   String suite = supportedSuites[i];

-		   logger.logDebugMessage(cn, '\t' + suite);

-	   }		

-	   

-	   String[] enabledProtocols = sslSocket.getEnabledProtocols();

-	   logger.logDebugMessage(cn, "SSL/TLS Enabled Protocols:"); //$NON-NLS-1$		   

-	   for (int i = 0; i < enabledProtocols.length; i++){

-		   String eprotocol = enabledProtocols[i];

-		   logger.logDebugMessage(cn, '\t' + eprotocol);

-	   }		

-	   

-	   String[] supportedProtocols = sslSocket.getSupportedProtocols();

-	   logger.logDebugMessage(cn, "SSL/TLS Supported Protocols:"); //$NON-NLS-1$		   

-	   for (int i = 0; i < supportedProtocols.length; i++){

-		   String sprotocol = supportedProtocols[i];

-		   logger.logDebugMessage(cn, '\t' + sprotocol);

-	   }		

-	}

-	

-	/**

-	 * Specify cipher patterns to be disabled when using SSL sockets

-	 * @param cipherPatterns regex patterns of ciphers to disable

-	 */

-	public void setDisabledCipherPatterns(String[] cipherPatterns){

-		_disabledCipherPatterns = cipherPatterns;

-	}

-	

-	/**

-	 * Specify protocol patterns to be disabled when using SSL sockets

-	 * @param protocolPatterns regex patterns of protocols to disable

-	 */

-	public void setDisabledProtocolPatterns(String[] protocolPatterns){

-		_disabledProtocolPatterns = protocolPatterns;

-	}

-	

-	/**

-	 * Specify ciphers to be enabled when using SSL sockets

-	 * @param ciphers to enable

-	 */

-	public void setEnabledCiphers(String[] ciphers){

-		_enabledCiphers = ciphers;

-	}

-	

-	/**

-	 * Specify protocols to be enabled when using SSL sockets

-	 * @param protocols to enable

-	 */

-	public void setEnabledProtocols(String[] protocols){

-		_enabledProtocols = protocols;

-	}

-	

-	private String[] filterNames(String[] inNames, String[] filters){

-		List outNames = new ArrayList();

-		for (int n = 0; n < inNames.length; n++){

-			String inName = inNames[n];

-			boolean match = false;

-			for (int i = 0; i < filters.length && !match; i++){

-				String filter = filters[i];

-				match = inName.matches(filter);

-			}

-			if (!match){

-				outNames.add(inName);

-			}

-			else {

-				String cn = getClass().toString();

-				IServerLogger logger = _dataStore.getClient().getLogger();

-				logger.logDebugMessage(cn, "Filtering out: " + inName); //$NON-NLS-1$	

-			}

-		}

-		return (String[])outNames.toArray(new String[outNames.size()]);

-	}

-	

-	private void disableCiphers(SSLServerSocket socket){

-		if (_disabledCipherPatterns != null){

-			String[] enabledSuites = socket.getEnabledCipherSuites();

-			String[] newEnabledSuites = filterNames(enabledSuites, _disabledCipherPatterns);			

-			

-			socket.setEnabledCipherSuites(newEnabledSuites);

-		}

-	}

-	

-	private void disableProtocols(SSLServerSocket socket){

-		if (_disabledProtocolPatterns != null){

-			String[] enabledProtocols = socket.getEnabledProtocols();

-			String[] newEnabledProtocols = filterNames(enabledProtocols, _disabledProtocolPatterns);

-			socket.setEnabledProtocols(newEnabledProtocols);

-		}

-	}

-

-	private String[] mergeCommon(String[] inNames1, String[] inNames2){

-		List merged = new ArrayList();

-		for (int n = 0; n < inNames1.length; n++){

-			String inName1 = inNames1[n];

-			boolean match = false;

-			for (int i = 0; i < inNames2.length && !match; i++){

-				match = inName1.equals(inNames2[i]);

-			}

-			if (match){

-				merged.add(inName1);

-			}

-		}

-		return (String[])merged.toArray(new String[merged.size()]);

-	}

-	

-	private void enableCiphers(SSLServerSocket socket){

-		if (_enabledCiphers != null){

-			String[] enabledSuites = socket.getEnabledCipherSuites();

-			String[] newEnabledSuites = mergeCommon(enabledSuites, _enabledCiphers);

-			if (newEnabledSuites.length > 0){				

-				socket.setEnabledCipherSuites(newEnabledSuites);

-			}

-		}

-	}

-

-	private void enableProtocols(SSLServerSocket socket){

-		if (_enabledProtocols != null){

-			String[] enabledProtocols = socket.getEnabledProtocols();

-			String[] newEnabledProtocols = mergeCommon(enabledProtocols, _enabledProtocols);

-			if (newEnabledProtocols.length > 0){

-				socket.setEnabledCipherSuites(newEnabledProtocols);

-			}

-		}

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2002, 2015 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Initial Contributors:
+ * The following IBM employees contributed to the Remote System Explorer
+ * component that contains this file: David McKnight, Kushal Munir,
+ * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
+ * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
+ *
+ * Contributors:
+ * David McKnight  (IBM)   [220123][dstore] Configurable timeout on irresponsiveness
+ * David McKnight  (IBM)   [220892][dstore] Backward compatibility: Server and Daemon should support old clients
+ * Noriaki Takatsu (IBM)  - [220126] [dstore][api][breaking] Single process server for multiple clients
+ * David McKnight     (IBM)   [224906] [dstore] changes for getting properties and doing exit due to single-process capability
+ * Jacob Garcowski    (IBM)   [225175] [dstore] error handling change for Client
+ * David McKnight   (IBM) - [225507][api][breaking] RSE dstore API leaks non-API types
+ * Noriaki Takatsu  (IBM) - [226074] process for getStatus() API
+ * Noriaki Takatsu  (IBM) - [226237] [dstore] Move the place where the ServerLogger instance is made
+ * David McKnight   (IBM) - [226561] [apidoc] Add API markup to RSE Javadocs where extend / implement is allowed
+ * Noriaki Takatsu  (IBM) - [242968] [multithread] serverSocket must be closed when an exception happens in Accept
+ * David McKnight   (IBM) - [257321] [dstore] "Error binding socket" should include port of the failed socket
+ * Noriaki Takatsu  (IBM) - [283656] [dstore][multithread] Serviceability issue
+ * Noriaki Takatsu  (IBM) - [289678][api][breaking] ServerSocket creation in multiple IP addresses
+ * David McKnight   (IBM) - [368072] [dstore][ssl] no exception logged upon bind error
+ * David McKnight   (IBM) - [371401] [dstore][multithread] avoid use of static variables - causes memory leak after disconnect
+ * David McKnight    (IBM) - [388472] [dstore] need alternative option for getting at server hostname
+ * David McKnight   (IBM)  - [390681] [dstore] need to merge differences between HEAD stream and 3.2 in ConnectionEstablisher.finished()
+ * David McKnight  (IBM)   [439545][dstore] potential deadlock on senders during shutdown
+ * David McKnight  (IBM)   [464736][dstore] need methods to disable ciphers and protocols
+ * David McKnight  (IBM)   [473086][dstore] enableProtocols() calls setEnabledCipherSuites(), not setEnabledProtocols()
+ *******************************************************************************/
+
+package org.eclipse.dstore.core.server;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.BindException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
+import org.eclipse.dstore.core.model.Client;
+import org.eclipse.dstore.core.model.DE;
+import org.eclipse.dstore.core.model.DataElement;
+import org.eclipse.dstore.core.model.DataStore;
+import org.eclipse.dstore.core.model.DataStoreAttributes;
+import org.eclipse.dstore.core.model.ISSLProperties;
+import org.eclipse.dstore.internal.core.server.ServerAttributes;
+import org.eclipse.dstore.internal.core.server.ServerCommandHandler;
+import org.eclipse.dstore.internal.core.server.ServerReturnCodes;
+import org.eclipse.dstore.internal.core.server.ServerSSLProperties;
+import org.eclipse.dstore.internal.core.server.ServerUpdateHandler;
+import org.eclipse.dstore.internal.core.util.ExternalLoader;
+import org.eclipse.dstore.internal.core.util.Sender;
+import org.eclipse.dstore.internal.core.util.ssl.DStoreSSLContext;
+
+/**
+ * ConnectionEstablisher is responsible for managing the server DataStore and
+ * facilitating the communication between client and server DataStores.
+ *
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ *
+ * @since 3.0 moved from non-API to API
+ */
+public class ConnectionEstablisher
+{
+
+
+	private ServerSocket _serverSocket;
+	private boolean _continue;
+
+	private ArrayList _receivers;
+
+	private ServerCommandHandler _commandHandler;
+	private ServerUpdateHandler _updateHandler;
+
+	private ServerAttributes _serverAttributes = new ServerAttributes();
+	private DataStore _dataStore;
+
+	private int _maxConnections;
+	private int _timeout;
+	private String _msg;
+	
+
+	private String[] _disabledCipherPatterns = null;
+	private String[] _disabledProtocolPatterns = null;
+	private String[] _enabledCiphers = null;
+	private String[] _enabledProtocols = null;
+	
+
+
+	/**
+	 * Creates the default ConnectionEstablisher.  Communication occurs
+	 * on a default port, there is no timeout and no ticket is required
+	 * for a client to work with the DataStore.
+	 *
+	 */
+	public ConnectionEstablisher()
+	{
+		String port = _serverAttributes.getAttribute(DataStoreAttributes.A_HOST_PORT);
+		setup(port, null, null);
+	}
+
+	/**
+	 * Creates a ConnectionEstablisher.  Communication occurs
+	 * on the specified port, there is no timeout and no ticket is required
+	 * for a client to work with the DataStore.
+	 *
+	 * @param port the number of the socket port
+	 */
+	public ConnectionEstablisher(String port)
+	{
+		setup(port, null, null);
+	}
+
+	/**
+	 * Creates a ConnectionEstablisher.  Communication occurs
+	 * on the specified port, a timeout value indicates the idle wait
+	 * time before shutting down, and no ticket is required
+	 * for a client to work with the DataStore.
+	 *
+	 * @param port the number of the socket port
+	 * @param timeout the idle duration to wait before shutting down
+	 */
+	public ConnectionEstablisher(String port, String timeout)
+	{
+		setup(port, timeout, null);
+	}
+
+	/**
+	 * Creates a ConnectionEstablisher.  Communication occurs
+	 * on the specified port, a timeout value indicates the idle wait
+	 * time before shutting down, and ticket specified the required
+	 * ticket for a client to present in order to work with the DataStore.
+	 *
+	 * @param port the number of the socket port
+	 * @param timeout the idle duration to wait before shutting down
+	 * @param ticket validation id required by the client to access the DataStore
+	 */
+	public ConnectionEstablisher(String port, String timeout, String ticket)
+	{
+		setup(port, timeout, ticket);
+	}
+	
+	/**
+	 * Creates a ConnectionEstablisher.  Communication occurs
+	 * on the specified port and the specified IP address, 
+	 * a timeout value indicates the idle wait time
+	 * before shutting down, and ticket specified the required
+	 * ticket for a client to present in order to work with the DataStore.
+	 *
+	 * @param port the number of the socket port
+	 * @param backlog listen backlog
+	 * @param bindAddr the local IP address to bind to
+	 * @param timeout the idle duration to wait before shutting down
+	 * @param ticket validation id required by the client to access the DataStore
+	 * @since 3.2
+	 */
+	public ConnectionEstablisher(String port, int backlog, InetAddress bindAddr, String timeout, String ticket)
+	{
+		setup(port, backlog, bindAddr, timeout, ticket);
+	}
+
+
+	/**
+	 * Starts the run loop for the ConnectionEstablisher.
+	 */
+	public void start()
+	{
+		run();
+	}
+
+
+
+	/**
+	 * Returns the DataStore.
+	 *
+	 * @return the DataStore
+	 */
+	public DataStore getDataStore()
+	{
+		return _dataStore;
+	}
+
+	/**
+	 * Return the Server port opened for this client
+	 *
+	 * @return the Server port opened for this client
+	 */
+	public int getServerPort()
+	{
+		if (_serverSocket != null)
+		{
+			return _serverSocket.getLocalPort();
+		}
+
+		return -1;
+	}
+
+	/**
+	 * Return the connection status for this client
+	 *
+	 * * @return the connection status for this client
+	 */
+	public String getStatus()
+	{
+		return _msg;
+	}
+
+	/**
+	 * Tells the connection establisher to clean up and shutdown
+	 */
+	public void finished(ServerReceiver receiver)
+	{
+		if (_dataStore.getClient() != null) {
+			_dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher.finished()"); //$NON-NLS-1$
+		}
+		
+		if (_dataStore.getClient() != null) {
+			_dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - removing receiver"); //$NON-NLS-1$
+		}
+		_receivers.remove(receiver);
+		
+		if (_dataStore.getClient() != null) {
+			_dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - removing preference listener"); //$NON-NLS-1$
+		}	
+		_dataStore.removeDataStorePreferenceListener(receiver);
+		//if (_receivers.size() == 0)
+		{
+			_continue = false;
+			_commandHandler.finish();			
+			
+			if (_dataStore.getClient() != null) {
+				_dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - finishing update handler"); //$NON-NLS-1$
+			}
+			_updateHandler.finish();
+			
+			if (_dataStore.getClient() != null) {
+				_dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - removing sender"); //$NON-NLS-1$
+			}
+			_updateHandler.removeSenderWith(receiver.socket());
+			
+			if (_dataStore.getClient() != null) {
+				_dataStore.getClient().getLogger().logInfo(this.getClass().toString(), "ConnectionEstablisher - finishing DataStore"); //$NON-NLS-1$
+			}
+			_dataStore.finish();
+			System.out.println(ServerReturnCodes.RC_FINISHED);
+
+			if (SystemServiceManager.getInstance().getSystemService() == null)
+				System.exit(0);
+		}
+	}
+
+	private void waitForConnections()
+	{
+		while (_continue == true)
+		{
+			try
+			{
+				if (_dataStore.usingSSL())
+				{
+					SSLServerSocket sslServerSocket = (SSLServerSocket)_serverSocket;
+					// for security, disable ciphers and protocols we don't want
+					disableCiphers(sslServerSocket);
+					disableProtocols(sslServerSocket);
+					
+					// for security, enable only ciphers and protocols that are common
+					enableCiphers(sslServerSocket);
+					enableProtocols(sslServerSocket);
+					
+					logAvailableCiphersAndProtocols(sslServerSocket);
+				}
+				
+				Socket newSocket = _serverSocket.accept();
+				if (_dataStore.usingSSL())
+				{
+
+					// wait for connection
+					SSLSocket sslSocket = (SSLSocket)newSocket;
+					sslSocket.setUseClientMode(false);
+					sslSocket.setNeedClientAuth(false);
+					SSLSession session = sslSocket.getSession();
+
+					if (session == null)
+					{
+						System.out.println("handshake failed"); //$NON-NLS-1$
+						sslSocket.close();
+						return;
+					}
+				}
+
+				doHandShake(newSocket);
+				newSocket.setKeepAlive(true);
+
+				ServerReceiver receiver = new ServerReceiver(newSocket, this);
+				_dataStore.addDataStorePreferenceListener(receiver);
+
+				if (_dataStore.getClient() != null)
+				     _dataStore.getClient().setServerReceiver(receiver);
+
+				Sender sender = new Sender(newSocket, _dataStore);
+
+				// add this connection to list of elements
+				_receivers.add(receiver);
+				_updateHandler.addSender(sender);
+
+				receiver.start();
+
+				if (_receivers.size() == 1)
+				{
+					_updateHandler.start();
+					_commandHandler.start();
+				}
+
+				if (_receivers.size() == _maxConnections)
+				{
+					_continue = false;
+					_serverSocket.close();
+
+				}
+			}
+			catch (IOException ioe)
+			{
+				System.err.println(ServerReturnCodes.RC_CONNECTION_ERROR);
+				System.err.println("Server: error initializing socket: " + ioe); //$NON-NLS-1$
+				_msg = ioe.toString();
+				try
+				{
+					_serverSocket.close();
+				}
+				catch (Throwable e)
+				{
+					
+				}
+				_continue = false;
+			}
+		}
+	}
+
+
+
+
+	private ServerSocket createSocket(String portStr, int backlog, InetAddress bindAddr) throws UnknownHostException
+	{
+		ServerSocket serverSocket = null;
+		SSLContext sslContext = null;
+		// port
+		int port = 0;
+
+		if (_dataStore.usingSSL())
+		{
+			String keyStoreFileName = _dataStore.getKeyStoreLocation();
+			String keyStorePassword = _dataStore.getKeyStorePassword();
+
+			try
+			{
+				sslContext = DStoreSSLContext.getServerSSLContext(keyStoreFileName, keyStorePassword);
+			}
+			catch (Exception e)
+			{
+
+			}
+		}
+
+		// determine if portStr is a port range or just a port
+		String[] range = portStr.split("-"); //$NON-NLS-1$
+		if (range.length == 2)
+		{
+			int lPort = 0;
+			int hPort = 0;
+			try
+			{
+				lPort = Integer.parseInt(range[0]);
+				hPort = Integer.parseInt(range[1]);
+			}
+			catch (Exception e)
+			{
+			}
+
+			for (int i = lPort; i < hPort; i++)
+			{
+				// create server socket from port
+				try
+				{
+					if (_dataStore.usingSSL() && sslContext != null)
+					{
+						try
+						{
+							serverSocket = sslContext.getServerSocketFactory().createServerSocket(i, backlog, bindAddr);
+						}
+						catch (BindException e)
+						{
+							_msg = ServerReturnCodes.RC_BIND_ERROR  + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$
+							System.err.println(_msg);
+							_dataStore.trace(_msg);
+						}
+						catch (Exception e)
+						{
+						}
+					}
+					else
+					{
+						try
+						{
+							serverSocket = new ServerSocket(i, backlog, bindAddr);
+						}						
+						catch (BindException e)
+						{
+							_msg = ServerReturnCodes.RC_BIND_ERROR  + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$
+							System.err.println(_msg);
+							_dataStore.trace(_msg);
+						}
+						catch (Exception e)
+						{
+						}
+					}
+				}
+				catch (Exception e)
+				{
+					_dataStore.trace(e);
+				}
+				if (serverSocket != null && serverSocket.getLocalPort() > 0)
+				{
+					return serverSocket;
+				}
+			}
+			if (serverSocket == null){
+				_msg = ServerReturnCodes.RC_BIND_ERROR  + " on ports " + portStr; //$NON-NLS-1$
+				System.err.println(_msg); 				
+			}
+		}
+		else
+		{
+			port = Integer.parseInt(portStr);
+
+
+			// create server socket from port
+			if (_dataStore.usingSSL() && sslContext != null)
+			{
+				try
+				{
+					serverSocket = sslContext.getServerSocketFactory().createServerSocket(port, backlog, bindAddr);
+				}
+				catch (BindException e){
+					_msg = ServerReturnCodes.RC_BIND_ERROR  + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$
+					System.err.println(_msg);
+					_dataStore.trace(_msg);
+				}
+				catch (Exception e)
+				{
+					_dataStore.trace(e);
+				}
+			}
+			else
+			{
+				try
+				{
+					serverSocket = new ServerSocket(port, backlog, bindAddr);
+				}
+				catch (BindException e){
+					_msg = ServerReturnCodes.RC_BIND_ERROR  + " on port " + port + ": " + e.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$
+					System.err.println(_msg);
+					_dataStore.trace(_msg);
+				}
+				catch (Exception e)
+				{
+					_dataStore.trace(e);
+				}
+			}
+		}
+		return serverSocket;
+	}
+	
+	/**
+	 * Create the DataStore and initializes it's handlers and communications.
+	 *
+	 * @param portStr the number of the socket port
+	 * @param timeoutStr the idle duration to wait before shutting down
+	 * @param ticketStr validation id required by the client to access the DataStore
+	 */
+	private void setup(String portStr, String timeoutStr, String ticketStr)
+	{
+		setup(portStr, 50, null, timeoutStr, ticketStr);
+	}
+
+	/**
+	 * Create the DataStore and initializes it's handlers and communications.
+	 *
+	 * @param portStr the number of the socket port
+	 * @param backlog listen backlog
+	 * @param bindAddr the local IP address to bind to
+	 * @param timeoutStr the idle duration to wait before shutting down
+	 * @param ticketStr validation id required by the client to access the DataStore
+	 */
+	private void setup(String portStr, int backlog, InetAddress bindAddr, String timeoutStr, String ticketStr)
+	{
+		_maxConnections = 1;
+
+
+		ArrayList loaders = new ArrayList();
+		loaders.add(new ExternalLoader(getClass().getClassLoader(), "*")); //$NON-NLS-1$
+		_commandHandler = new ServerCommandHandler(loaders);
+		_updateHandler = new ServerUpdateHandler();
+
+		ISSLProperties sslProperties = new ServerSSLProperties();
+
+		_dataStore = new DataStore(_serverAttributes, _commandHandler, _updateHandler, null);
+		_dataStore.setSSLProperties(sslProperties);
+
+		DataElement ticket = _dataStore.getTicket();
+		ticket.setAttribute(DE.A_NAME, ticketStr);
+
+		_updateHandler.setDataStore(_dataStore);
+		_commandHandler.setDataStore(_dataStore);
+
+		if (SystemServiceManager.getInstance().getSystemService() == null)
+		{
+			Client client = new Client();
+			_dataStore.setClient(client);
+		     ServerLogger logger = new ServerLogger(_dataStore.getUserPreferencesDirectory());
+    		client.setLogger(logger);
+		}
+
+		_receivers = new ArrayList();
+		_continue = true;
+
+		try
+		{
+
+			_serverSocket = createSocket(portStr, backlog, bindAddr);
+			if (_serverSocket == null)
+			{
+				_continue = false;
+			}
+			else
+			{
+				// timeout
+				if (timeoutStr != null)
+				{
+					_timeout = Integer.parseInt(timeoutStr);
+				}
+				else
+				{
+					_timeout = 120000;
+				}
+
+				if (_timeout > 0)
+				{
+					_serverSocket.setSoTimeout(_timeout);
+				}
+
+				System.err.println(ServerReturnCodes.RC_SUCCESS);
+				System.err.println(_serverSocket.getLocalPort());
+				_msg = ServerReturnCodes.RC_SUCCESS;
+				System.err.println("Server running on: " + ServerAttributes.getHostName()); //$NON-NLS-1$
+			}
+		}
+		catch (UnknownHostException e)
+		{
+			System.err.println(ServerReturnCodes.RC_UNKNOWN_HOST_ERROR + ':' + e.getMessage());
+			_msg = ServerReturnCodes.RC_UNKNOWN_HOST_ERROR;
+			_continue = false;
+		}
+	   catch (BindException e)
+		{
+			System.err.println(ServerReturnCodes.RC_BIND_ERROR + ':' + e.getMessage());
+			_msg = ServerReturnCodes.RC_BIND_ERROR;
+			_continue = false;
+		}
+		catch (IOException e)
+		{
+			System.err.println(ServerReturnCodes.RC_GENERAL_IO_ERROR + ':' + e.getMessage());
+			_msg = ServerReturnCodes.RC_GENERAL_IO_ERROR;
+			_continue = false;
+		}
+		catch (SecurityException e)
+		{
+			System.err.println(ServerReturnCodes.RC_SECURITY_ERROR + ':' + e.getMessage());
+			_msg = ServerReturnCodes.RC_SECURITY_ERROR;
+			_continue = false;
+		}
+	}
+
+	private void run()
+	{
+		waitForConnections();
+	}
+ 
+	private void doHandShake(Socket socket)
+	{
+	   	try
+	   	{
+		BufferedWriter bwriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), DE.ENCODING_UTF_8));
+	   		PrintWriter writer = new PrintWriter(bwriter);
+
+	   		String version = DataStoreAttributes.DATASTORE_VERSION;
+	   		String preferenceVersion = System.getProperty("DSTORE_VERSION"); //$NON-NLS-1$
+	   		if (preferenceVersion != null && preferenceVersion.length() > 0){
+	   			version = preferenceVersion;
+	   		}
+			writer.println(version);
+			writer.flush();
+			
+		   if (socket instanceof SSLSocket){ // log the protocol and cipher suite used
+			   SSLSocket sslSocket = (SSLSocket)socket;
+			   SSLSession session = sslSocket.getSession();
+			   String protocol = session.getProtocol();		   
+			   String cipherSuite = session.getCipherSuite();
+			   IServerLogger logger = _dataStore.getClient().getLogger();
+
+			   String cn = getClass().toString();
+			   
+			   logger.logInfo(cn, "SSL/TLS Protocol: "+protocol); //$NON-NLS-1$
+			   logger.logInfo(cn, "SSL/TLS Cipher Suite: " + cipherSuite); //$NON-NLS-1$
+		   }			
+	   	}
+	   	catch (IOException e)
+	   	{
+	   		if (_dataStore.getClient() != null) {
+				_dataStore.getClient().getLogger().logError(this.getClass().toString(), e.toString(), e);
+			}
+	   		System.out.println(e);
+	   	}
+
+	}
+	
+	
+	
+	private void logAvailableCiphersAndProtocols(SSLServerSocket sslSocket){
+	   IServerLogger logger = _dataStore.getClient().getLogger();
+
+	   String cn = getClass().toString();
+	   // list the supported and available ciphers and protocols
+	   logger.logDebugMessage(cn, "SSL/TLS Enabled Cipher Suites:"); //$NON-NLS-1$
+	   String[] enabledSuites = sslSocket.getEnabledCipherSuites();			   
+	   for (int i = 0; i < enabledSuites.length; i++){
+		   String suite = enabledSuites[i];
+		   logger.logDebugMessage(cn, '\t' + suite);
+	   }			   			   
+	   
+	   String[] supportedSuites = sslSocket.getSupportedCipherSuites();
+	   logger.logDebugMessage(cn, "SSL/TLS Supported Cipher Suites:"); //$NON-NLS-1$	   
+	   for (int i = 0; i < supportedSuites.length; i++){
+		   String suite = supportedSuites[i];
+		   logger.logDebugMessage(cn, '\t' + suite);
+	   }		
+	   
+	   String[] enabledProtocols = sslSocket.getEnabledProtocols();
+	   logger.logDebugMessage(cn, "SSL/TLS Enabled Protocols:"); //$NON-NLS-1$		   
+	   for (int i = 0; i < enabledProtocols.length; i++){
+		   String eprotocol = enabledProtocols[i];
+		   logger.logDebugMessage(cn, '\t' + eprotocol);
+	   }		
+	   
+	   String[] supportedProtocols = sslSocket.getSupportedProtocols();
+	   logger.logDebugMessage(cn, "SSL/TLS Supported Protocols:"); //$NON-NLS-1$		   
+	   for (int i = 0; i < supportedProtocols.length; i++){
+		   String sprotocol = supportedProtocols[i];
+		   logger.logDebugMessage(cn, '\t' + sprotocol);
+	   }		
+	}
+	
+	/**
+	 * Specify cipher patterns to be disabled when using SSL sockets
+	 * @param cipherPatterns regex patterns of ciphers to disable
+	 */
+	public void setDisabledCipherPatterns(String[] cipherPatterns){
+		_disabledCipherPatterns = cipherPatterns;
+	}
+	
+	/**
+	 * Specify protocol patterns to be disabled when using SSL sockets
+	 * @param protocolPatterns regex patterns of protocols to disable
+	 */
+	public void setDisabledProtocolPatterns(String[] protocolPatterns){
+		_disabledProtocolPatterns = protocolPatterns;
+	}
+	
+	/**
+	 * Specify ciphers to be enabled when using SSL sockets
+	 * @param ciphers to enable
+	 */
+	public void setEnabledCiphers(String[] ciphers){
+		_enabledCiphers = ciphers;
+	}
+	
+	/**
+	 * Specify protocols to be enabled when using SSL sockets
+	 * @param protocols to enable
+	 */
+	public void setEnabledProtocols(String[] protocols){
+		_enabledProtocols = protocols;
+	}
+	
+	private String[] filterNames(String[] inNames, String[] filters){
+		List outNames = new ArrayList();
+		for (int n = 0; n < inNames.length; n++){
+			String inName = inNames[n];
+			boolean match = false;
+			for (int i = 0; i < filters.length && !match; i++){
+				String filter = filters[i];
+				match = inName.matches(filter);
+			}
+			if (!match){
+				outNames.add(inName);
+			}
+			else {
+				String cn = getClass().toString();
+				IServerLogger logger = _dataStore.getClient().getLogger();
+				logger.logDebugMessage(cn, "Filtering out: " + inName); //$NON-NLS-1$	
+			}
+		}
+		return (String[])outNames.toArray(new String[outNames.size()]);
+	}
+	
+	private void disableCiphers(SSLServerSocket socket){
+		if (_disabledCipherPatterns != null){
+			String[] enabledSuites = socket.getEnabledCipherSuites();
+			String[] newEnabledSuites = filterNames(enabledSuites, _disabledCipherPatterns);			
+			
+			socket.setEnabledCipherSuites(newEnabledSuites);
+		}
+	}
+	
+	private void disableProtocols(SSLServerSocket socket){
+		if (_disabledProtocolPatterns != null){
+			String[] enabledProtocols = socket.getEnabledProtocols();
+			String[] newEnabledProtocols = filterNames(enabledProtocols, _disabledProtocolPatterns);
+			socket.setEnabledProtocols(newEnabledProtocols);
+		}
+	}
+
+	private String[] mergeCommon(String[] inNames1, String[] inNames2){
+		List merged = new ArrayList();
+		for (int n = 0; n < inNames1.length; n++){
+			String inName1 = inNames1[n];
+			boolean match = false;
+			for (int i = 0; i < inNames2.length && !match; i++){
+				match = inName1.equals(inNames2[i]);
+			}
+			if (match){
+				merged.add(inName1);
+			}
+		}
+		return (String[])merged.toArray(new String[merged.size()]);
+	}
+	
+	private void enableCiphers(SSLServerSocket socket){
+		if (_enabledCiphers != null){
+			String[] enabledSuites = socket.getEnabledCipherSuites();
+			String[] newEnabledSuites = mergeCommon(enabledSuites, _enabledCiphers);
+			if (newEnabledSuites.length > 0){				
+				socket.setEnabledCipherSuites(newEnabledSuites);
+			}
+		}
+	}
+
+	private void enableProtocols(SSLServerSocket socket){
+		if (_enabledProtocols != null){
+			String[] enabledProtocols = socket.getEnabledProtocols();
+			String[] newEnabledProtocols = mergeCommon(enabledProtocols, _enabledProtocols);
+			if (newEnabledProtocols.length > 0){
+				socket.setEnabledProtocols(newEnabledProtocols);
+			}
+		}
+	}
+}