All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.ims.connect.impl.ConnectionImpl Maven / Gradle / Ivy

The newest version!
/*
 * File: ConnectionImpl.java                                               
 * ==========================================================================
 * Licensed Material - Property of IBM
 *  
 * IBM Confidential
 * 
 * OCO Source Materials
 * 
 * 5655-TDA
 * 
 * (C) Copyright IBM Corp. 2009,2014 All Rights Reserved. 
 * 
 * The source code for this program is not published or  
 * otherwise divested of its trade secrets, irrespective 
 * of what has been deposited with the U.S. Copyright 
 * Office.
 * 
 * US Government Users Restricted Rights - Use, duplication or
 * disclosure restricted by GSA ADP Schedule Contract with
 * IBM Corp.
 * =========================================================================== 
 */
package com.ibm.ims.connect.impl;

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.security.KeyStore;
import java.util.logging.Logger;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import com.ibm.ims.connect.ApiProperties;
import com.ibm.ims.connect.Connection;
import com.ibm.ims.connect.ConnectionAttributes;
import com.ibm.ims.connect.ConnectionFactory;
import com.ibm.ims.connect.ImsConnectApiException;
import com.ibm.ims.connect.ImsConnectCommunicationException;
import com.ibm.ims.connect.ImsConnectErrorMessage;
import com.ibm.ims.connect.NumberConversion;
import com.ibm.ims.connect.PropertiesFileLoader;
import com.ibm.ims.connect.TmInteraction;
import com.ibm.ims.connect.TmInteractionAttributes;

/**
 * This interface represents the TCP/IP socket connection for communicating with
 * IMS Connect.
 * 
 * @author hfung
 * 
 */
public final class ConnectionImpl implements Connection, Runnable {
	@SuppressWarnings("unused")
	private static final String copyright = "Licensed Material - Property of IBM "
			+ "5655-TDA"
			+ "(C) Copyright IBM Corp. 2009,2013  All Rights Reserved. "
			+ "US Government Users Restricted Rights - Use, duplication or "
			+ "disclosure restricted by GSA ADP Schedule Contract with IBM Corp. ";

	private TmInteraction myTmInteraction = null;

	// private int connectionRequestWaitTime; // for debug only

	Connection myConnection = null;

	// private ConnectionPool connPool = null;

	/*** Connection properties ***/

	
	/**
	 * hostName is a String variable whose value is the hostname (or IP
	 * address???) of the target IMS Connect for this connection. The default
	 * value is "myHostNm". Values must be a 1 to 8 character String set to the
	 * correct hostname of the target IMS Connect (or a string containing the IP
	 * address of the target IMS Connect (e.g., nnn.nnn.nnn.nnn or
	 * nnnn.nnnn.nnnn.nnnn.nnnn.nnnn or some permutations of these)
	 */
	private String hostName = DEFAULT_HOSTNAME;

	/**
	 * portNumber is an int variable whose value is the port number of the
	 * target IMS Connect for this connection. The default value is 9999. Values
	 * must be a valid port number set to the port number on which the target
	 * IMS Connect is listening.
	 */
	private int portNumber = DEFAULT_PORTNUMBER;

	/**
	 * socketType is an int variable whose value is used to determine whether a
	 * socket connection is a transaction socket which can only be disconnected
	 * by IMS Connect (either after a single non-conversational IMS transaction
	 * interaction has completed), after an IMS conversation (most likely
	 * including multiple iterations of the conversation) has completed, or
	 * after IMS itself has terminated or after an error has occured) or a
	 * persistent socket (left connected by IMS Connect until a fatal error has
	 * occured on that connection while IMS Connect is processing an interaction
	 * or until a disconnect request has been received by IMS Connect.) valid
	 * values for socketType: SOCKET_TYPE_TRANSACTION SOCKET_TYPE_PERSISTENT
	 * DEFAULT_SOCKET_TYPE (SOCKET_TYPE_PERSISTENT)
	 */
	private byte socketType = DEFAULT_SOCKET_TYPE;

	/**
	 * clientID is a String variable whose value is used to identify a
	 * connection. This value can either be created by the client application
	 * or, if not specified (that is, the string is set to 1 to 8 blanks,) or if
	 * setGenerateClientID is set to "true," the clientID will be assigned by
	 * IMS Connect.
	 */
	private String clientId = DEFAULT_CLIENTID;

	/*** SSL properties ***/

	/**
	 * sslEncryptionType is the Encryption Type for the SSL connection. It can
	 * have a value of "Strong" for strong encryption, i.e encryption with
	 * ciphers that have large key sizes or it can have a value of "Weak" for
	 * weak encryption with ciphers that have small key sizes, or "none" for no
	 * encryption.
	 */
	private byte sslEncryptionType = DEFAULT_SSL_ENCRYPTIONTYPE;

	/**
	 * sslKeystoreInputStream is an InputStream which wraps a keystore file that
	 * contains keys required during an SSL handshake. It usually holds public
	 * keys or certificates but it can also be used to store private keys and
	 * trusted certificates for the client. When TmInteraction.execute() is
	 * called, if a value is specified for the sslKeystoreName, the
	 * sslKeystoreUrl and the sslKeystoreInputStream, the sslKeystoreInputStream
	 * value takes precedence and will be used by the Connect API to load the
	 * keystore. If the sslKeystoreInputStream value is null, the sslKeystoreUrl
	 * value, if non-null, will be used. Only if both the sslKeystoreInputStream
	 * and sslKeystoreUrl values are null will the sslKeystoreName be used by
	 * the Connect API to load the keystore.
	 */
	private InputStream sslKeystoreInputStream = DEFAULT_SSL_KEYSTORE_INPUT_STREAM;

	/**
	 * sslKeystoreUrl is a URL that wraps a keystore file which contains keys
	 * required during an SSL handshake. It usually holds public keys or
	 * certificates but it can also be used to store private keys and trusted
	 * certificates client. When TmInteraction.execute() is called, if a value
	 * is specified for the sslKeystoreName, the sslKeystoreUrl and the
	 * sslKeystoreInputStream, the sslKeystoreInputStream value takes precedence
	 * and will be used by the Connect API to load the keystore. If the
	 * sslKeystoreInputStream value is null, the sslKeystoreUrl value, if
	 * non-null, will be used. Only if both the sslKeystoreInputStream and
	 * sslKeystoreUrl values are null will the sslKeystoreName be used by the
	 * API to load the keystore.
	 */
	private URL sslKeystoreUrl = DEFAULT_SSL_KEYSTORE_URL;

	/**
	 * sslKeystoreName is the filename (qualified or un-qualified) of a keyStore
	 * which contains keys required during the SSL handshake. It usually holds
	 * public keys or certificates but it can also be used to store private keys
	 * and trusted certificates for the client. When TmInteraction.execute() is
	 * called, if a value is specified for the sslKeystoreName, the
	 * sslKeystoreUrl and the sslKeystoreInputStream, the sslKeystoreInputStream
	 * value takes precedence and will be used by the Connect API to load the
	 * keystore. If the sslKeystoreInputStream value is null, the sslKeystoreUrl
	 * value, if non-null, will be used. Only if both the sslKeystoreInputStream
	 * and sslKeystoreUrl values are null will the sslKeystoreName be used by
	 * the API to load the keystore.
	 */
	private String sslKeystoreName = DEFAULT_SSL_KEYSTORE_NAME;

	/**
	 * sslKeystorePassword is the password for the keyStore file which contains
	 * keys.
	 */
	private String sslKeystorePassword = DEFAULT_SSL_KEYSTORE_PASSWORD;

	/**
	 * sslTruststoreInputStream is an InputStream that wraps a truststore file
	 * which contains keys required during an SSL handshake. It usually holds
	 * private or trusted keys or certificates, but can also be used to store
	 * public keys and and certificates for the client. When
	 * TmInteraction.execute() is called, if a value is specified for the
	 * sslKeystoreName, the sslKeystoreUrl and the sslKeystoreInputStream, the
	 * sslKeystoreInputStream value takes precedence and will be used by the
	 * Connect API to load the keystore. If the sslKeystoreInputStream value is
	 * null, the sslKeystoreUrl value, if non-null, will be used. Only if both
	 * the sslKeystoreInputStream and sslKeystoreUrl values are null will the
	 * sslKeystoreName be used by the API to load the keystore.
	 */
	private InputStream sslTruststoreInputStream = DEFAULT_SSL_TRUSTSTORE_INPUT_STREAM;

	/**
	 * sslTruststoreUrl is a URL which wraps a truststore file that contains
	 * keys required during an SSL handshake. It usually holds private or
	 * trusted keys or certificates, but it can also be used to store private
	 * keys for the client. If a value is specified for the sslTruststoreName,
	 * the sslTruststoreUrl and the sslTruststoreInputStream, the
	 * sslTruststoreInputStream value takes precedence and will be used by the
	 * Connect API to load the truststore. If the sslTruststoreInputStream value
	 * is null, the sslTruststoreUrl value, if non-null, will be used. Only if
	 * both the sslTruststoreInputStream and sslTruststoreUrl values are null
	 * will the sslTruststoreName be used.
	 */
	private URL sslTruststoreUrl = DEFAULT_SSL_TRUSTSTORE_URL;

	/**
	 * sslTruststoreName is the filename (qualified or un-qualified) of a
	 * keystore which contains keys required during an SSL handshake. It usually
	 * holds private or trusted keys or certificates, but it can also be used to
	 * store private keys for the client. If a value is specified for the
	 * sslTruststoreName, the sslTruststoreUrl and the sslTruststoreInputStream,
	 * the sslTruststoreInputStream value takes precedence and will be used by
	 * the Connect API to load the truststore. If the sslTruststoreInputStream
	 * value is null, the sslTruststoreUrl value, if non-null, will be used.
	 * Only if both the sslTruststoreInputStream and sslTruststoreUrl values are
	 * null will the sslTruststoreName be used.
	 */
	private String sslTruststoreName = DEFAULT_SSL_TRUSTSTORE_NAME;

	/**
	 * sslTruststorePassword is the password for the keyStore file which
	 * contains keys for trusted entities.
	 */
	private String sslTruststorePassword = DEFAULT_SSL_TRUSTSTORE_PASSWORD;

	/**
	 * useSslConnection is a Boolean variable whose value indictes whether or
	 * not this connection is an SSL connection. A true value indicates that
	 * this connection is or will be an SSL connection while a false value
	 * indicates that SSL is not being or will not be used.
	 */
	private boolean useSslConnection = DEFAULT_USE_SSL_CONNECTION;

	/**
	 * sslContext is an instance of a class that represents a secure socket
	 * protocol implementation which acts as a factory for secure socket
	 * factories. This class is initialized with an optional set of key and
	 * trust managers Note that the same SSLContext can be use for the creation
	 * of multiple SSLSockets.
	 */
	private SSLContext sslContext = null;

	/**
	 * sslCertType contains a JVM provider-specific String which designates the
	 * type of SSL certificates being used.
	 */
	private String sslCertType = null;

	/**
	 * sslSocket is an instance of a class that extends Sockets and provides a
	 * secure socket using protocols such as the SSL or IETF
	 * "Transport Layer Security" (TLS) protocols.
	 */
	private SSLSocket sslSocket = null;

	/*** Timeout properties ***/

	/*
	 * The value of interactionTimeout will be set automatically during an
	 * TmInteraction.execute() call to the value of the interactionTimeout
	 * property of that TmInteraction instance. This value will be used to
	 * control the amount of time that the API will wait for a response from IMS
	 * Connect for interactions such as a resumeTpipe or receive interaction.
	 * Note that a receive interaction is invoked internally as part of a
	 * sendreceive interaction.
	 */
	private int interactionTimeout = DEFAULT_INTERACTION_TIMEOUT;

	private boolean setSoTimeoutRequired = false;

	/*
	 * The value of socketConnectTimeout will be used internally by the API
	 * during a Connection.connect() call set the time that TCP/IP should wait
	 * for a socket connect request to complete successfully. However it should
	 * be noted that this value is used by TCP/IP in conjunction with the TCP/IP
	 * maximum socket connect retries value (which may or may not be
	 * user-customizable depending on runtime platform) to determine the amount
	 * of time that TCP/IP will actually wait for a socket connect request to
	 * complete successfully. Whichever event occurs first, the socket connect
	 * timeout or the maximum socket connect retries exceeded will determine
	 * when the connect attemp will be aborted by TCP/IP and an error returned
	 * to the calling program.
	 */
	private int socketConnectTimeout = DEFAULT_SOCKET_CONNECT_TIMEOUT;

	private boolean isConnected = false;

	/*** Connection management properties ***/

	/**
	 * useConnectionManager is a boolean variable whose value determines whether
	 * the IMS Connect API runtime instantiates a Connection Manager to manage
	 * connection pools.
	 */
	// private boolean useConnectionPoolManager =
	// DEFAULT_USE_CONNECTION_POOL_MANAGER;
	// private boolean staleConnection = false;
	/*** Other properties ***/

	private final static String validChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-";

	private static final String validLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

	private static final int s = 0;

	private String imsConnectCodepage;

	private Socket socket = null;

	private Logger logger;
	
	Thread hook = null;

	// Booleans for ON OFF to improve performance
	protected boolean updateIrmClientId = false;
	protected boolean returnedClientID = false;
	// private ApiLoggingConfiguration loggingConfig = new
	// ApiLoggingConfiguration();

	protected ConnectionImpl() throws ImsConnectApiException {
		logger = Logger.getLogger("com.ibm.ims.connect");
		if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) {
			logger.finer("<-> ConnectionImpl()...");
		}
		
		/*
		this.hook = new Thread() {
			public void run() {
				if (myConnection.isConnected())
					((ConnectionImpl) myConnection).close();
			}
		};
		Runtime.getRuntime().addShutdownHook(this.hook);
		*/
	}

	public ConnectionImpl(ConnectionFactory aConnectionFactory)
			throws ImsConnectApiException {
		super();

		myConnection = this;

		logger = Logger.getLogger("com.ibm.ims.connect");

		if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT))
			logger.finer("--> ConnectionImpl(ConnectionFactory)...");
		
		//PMR 45208,100,338 - Commented out shutdown hooks because of memory leak -JL
		/*
		
			public void run() {
				if (myConnection.isConnected())
					((ConnectionImpl) myConnection).close();
			}
		};
		
		Runtime.getRuntime().addShutdownHook(this.hook);
		 */

		if (aConnectionFactory != null) {
			/*** Connection properties ***/

			this.setClientId(aConnectionFactory.getClientId());

			this.setHostName(aConnectionFactory.getHostName());

			this.setPortNumber(aConnectionFactory.getPortNumber());

			this.setInteractionTimeout(aConnectionFactory
					.getInteractionTimeout());

			this.setSocketConnectTimeout(aConnectionFactory
					.getSocketConnectTimeout());

			setSocketType(aConnectionFactory.getSocketType());
			if (logger.isLoggable(ApiProperties.TRACE_LEVEL_INTERNAL)) {
				logger.finer("     Connection.clientID set to ["
						+ this.getClientId() + "]");

				logger.finer("     Connection.hostName set to ["
						+ this.getHostName() + "]");

				logger.finer("     Connection.portNumber set to ["
						+ this.getPortNumber() + "]");

				logger.finer("     Connection.interactionTimeout set to ["
						+ this.getInteractionTimeout() + "]");

				logger.finer("     Connection.socketConnectTimeout set to ["
						+ this.getSocketConnectTimeout() + "]");

				logger.finer("     Connection.socketType set to ["
						+ this.getSocketType() + "]");
			}

			/*** SSL properties ***/

			if (aConnectionFactory.isUseSslConnection()) {
				this.setSslEncryptionType(aConnectionFactory
						.getSslEncryptionType());

				this.setSslKeystoreInputStream(aConnectionFactory
						.getSslKeystoreInputStream());

				this.setSslKeystoreUrl(aConnectionFactory.getSslKeystoreUrl());

				this.setSslKeystoreName(aConnectionFactory.getSslKeystoreName());

				this.setSslKeystorePassword(aConnectionFactory
						.getSslKeystorePassword());

				this.setSslTruststoreInputStream(aConnectionFactory
						.getSslTruststoreInputStream());

				this.setSslTruststoreUrl(aConnectionFactory
						.getSslTruststoreUrl());

				this.setSslTruststoreName(aConnectionFactory
						.getSslTruststoreName());

				this.setSslTruststorePassword(aConnectionFactory
						.getSslTruststorePassword());

				this.setUseSslConnection(aConnectionFactory
						.isUseSslConnection());
				if (logger.isLoggable(ApiProperties.TRACE_LEVEL_INTERNAL)) {
					logger.finer("     Connection.sslEncryptionType set to ["
							+ this.getSslEncryptionType() + "]");

					logger.finer("     Connection.sslKeystoreInputStream set to ["
							+ this.getSslKeystoreInputStream() + "]");

					logger.finer("     Connection.sslKeystoreUrl set to ["
							+ this.getSslKeystoreUrl() + "]");

					logger.finer("     Connection.sslKeystoreName set to ["
							+ this.getSslKeystoreName() + "]");
					logger.finer("     Connection.sslKeystorePassword set to ["
							+ new String("********") + "]");

					logger.finer("     Connection.sslTruststoreInputStream set to ["
							+ this.getSslTruststoreInputStream() + "]");
					logger.finer("     Connection.sslTruststoreUrl set to ["
							+ this.getSslTruststoreUrl() + "]");

					logger.finer("     Connection.sslTruststoreName set to ["
							+ this.getSslTruststoreName() + "]");

					logger.finer("     Connection.sslTruststorePassword set to ["
							+ new String("********") + "]");

					logger.finer("     Connection.useSslConnection set to ["
							+ this.isUseSslConnection() + "]");
				}

			}

			/*** Connection management properties ***/

			// if(myConnection.getUseConnectionPoolManager() ==
			// USE_CONNECTION_POOL_MANAGER)
			// {
			// setUseConnectionPoolManager(conn.isUseConnectionPoolManager());
			// }
			/*** Other properties ***/

			// setGenerateClientID(conn.getGenerateClientID());
			// setStaleConnection(connAttrib.isStaleConnection());
		}
		if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT))
			logger.finer("<-- ConnectionImpl(Connection)...");
	}

	/**
	 * Closes the TCP/IP socket connection represented by this
	 * Connection object and cleans up the Connection
	 * object. Socket and client ID members are set to null and the
	 * setSocketTimeout field is restored to its default value,
	 * false.)
	 */
	public void close() {
		if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT))
			logger.finer("--> ConnectionImpl.close()...");

		try {
			if (this.socket != null) {
				String socketTypeString = new String("    Socket ");
				if (this.socket.equals(this.sslSocket))
					socketTypeString = new String("    SSL socket ");
				this.socket.close();
				if (logger.isLoggable(ApiProperties.TRACE_LEVEL_INTERNAL))
					logger.finer(socketTypeString
							+ "connection with clientId ["
							+ this.clientId
							+ "] to hostname ["
							+ this.hostName
							+ "], portNumber ["
							+ this.portNumber
							+ "] now "
							+ (this.socket.isClosed() ? "closed" : "not closed"));
				this.socket = null;
				if (logger.isLoggable(ApiProperties.TRACE_LEVEL_INTERNAL))
					logger.finer("    Socket object now set to null");
			}
			this.setSetSoTimeoutRequired(false);
		} catch (Exception e) {
			this.socket = null;
			if (logger.isLoggable(ApiProperties.TRACE_LEVEL_INTERNAL))
				logger.finer("    Socket object now set to null");

			if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION))
				logger.severe("    Exception caught in Connection.close().  Exception caught was: "
						+ e.toString());
		} finally {
			this.setIsConnected(false);
			if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT))
				logger.finer("<-- ConnectionImpl.close()...");
		}
	}

	/**
	 * Connects the TCP/IP socket connection represented by this
	 * Connection object
	 * 
	 * @throws Exception
	 */
	public void connect() throws ImsConnectApiException,
			ImsConnectCommunicationException, SocketException {
		if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT))
			logger.finer("--> ConnectionImpl.connect()...");

		if (isConnected()) // Do we want to ping the host instead of just
		// returning exception???
		{
			String errMsg = ImsConnectErrorMessage.getString(
					ImsConnectErrorMessage.HWS0034E,
					new Object[] { this.clientId });
			ImsConnectApiException e = new ImsConnectApiException(
					ImsConnectErrorMessage.HWS0034E, errMsg);

			if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION))
				logger.severe("    Exception thrown in Connection.connect().  Exception thrown was: "
						+ e.toString());

			throw e;
		}

		if (!this.useSslConnection) {
			try {
				if (this.socket == null) {
					this.socket = new Socket();
				}

				SocketAddress endpoint = new InetSocketAddress(this.hostName,
						this.portNumber);
				if (this.socketConnectTimeout == -1)
					this.socket.connect(endpoint);
				else
					this.socket.connect(endpoint, socketConnectTimeout);
			} catch (SocketTimeoutException e1) {
				String errMsg = ImsConnectErrorMessage
						.getString(
								ImsConnectErrorMessage.HWS0025E,
								new Object[] {
										"Socket connect",
										this.socketConnectTimeout,
										ImsConnectErrorMessage
												.getExceptionMessage(e1) });

				ImsConnectCommunicationException e2 = new ImsConnectCommunicationException(
						ImsConnectErrorMessage.HWS0025E, errMsg);

				if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION))
					logger.severe("    Exception caught in Connection.connect().  Exception caught was: "
							+ e1.toString());

				throw e2;
			} catch (Exception e2) {
				this.setIsConnected(false);

				String errMsg = ImsConnectErrorMessage
						.getString(
								ImsConnectErrorMessage.HWS0006E,
								new Object[] {
										this.hostName,
										String.valueOf(this.portNumber),
										ImsConnectErrorMessage
												.getExceptionMessage(e2) });

				ImsConnectCommunicationException e3 = new ImsConnectCommunicationException(
						ImsConnectErrorMessage.HWS0006E, errMsg);

				if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION))
					logger.severe("    Exception caught in Connection.connect().  Exception caught was: "
							+ e3.toString());

				throw e3;
			}

			if (logger.isLoggable(ApiProperties.TRACE_LEVEL_INTERNAL))
				logger.finest("    ConnectionImpl.connect() - Non-SSL connection for clientId ["
						+ this.clientId
						+ "] to hostname ["
						+ this.hostName
						+ "], portNumber ["
						+ this.portNumber
						+ "] "
						+ (this.socket.isClosed() ? "not open" : "now open"));
		} else // this.useSslConnection is true
		{
			SSLSession sslSession = null;

			initContext(this.sslKeystoreInputStream, this.sslKeystoreUrl,
					this.sslKeystoreName, this.sslKeystorePassword,
					this.sslTruststoreInputStream, this.sslTruststoreUrl,
					this.sslTruststoreName, this.sslTruststorePassword);

			SSLSocketFactory factory = sslContext.getSocketFactory();
			try {
				// Returns a socket layered over an existing socket, connected
				// to
				// the named host, at the given portNumber.

				this.sslSocket = (SSLSocket) factory.createSocket(
						validateHostName(this.hostName),
						this.validatePortNumber(this.portNumber));

				setSupportedCipherSuites(sslEncryptionType); // sets cipher
				// suites
				// available to
				// be used on
				// sslSocket
				// this.sslSocket.startHandshake(); // invoked by getSession if
				// needed
				sslSession = this.sslSocket.getSession();
				if (!sslSession.isValid()) {
					String invalidSslSessionString = "";
					try {
						invalidSslSessionString = ImsConnectErrorMessage
								.getString(ImsConnectErrorMessage.INVALID_SSLSESSION);
					} catch (Exception e2) {

					}

					throw new Exception(invalidSslSessionString);
				}
				if (logger.isLoggable(ApiProperties.TRACE_LEVEL_INTERNAL)) {
					logger.finest("   ConnectionImpl.connect() - SSL connection for clientId ["
							+ this.clientId
							+ "] to hostname ["
							+ this.hostName
							+ "], portNumber ["
							+ this.portNumber
							+ "] "
							+ (this.sslSocket.isClosed() ? "not open"
									: "now open"));
					logger.finest("   ConnectionImpl.connect() - SSL Cipher Suite used is : "
							+ sslSession.getCipherSuite());
				}
			} catch (Exception e4) {
				String errMsg = ImsConnectErrorMessage
						.getString(
								ImsConnectErrorMessage.HWS0010E,
								new Object[] {
										hostName,
										Integer.toString(portNumber)
												.replaceAll("'", ""),
										ImsConnectErrorMessage
												.getExceptionMessage(e4) });

				ImsConnectCommunicationException e5 = new ImsConnectCommunicationException(
						ImsConnectErrorMessage.HWS0010E, errMsg);

				if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION))
					logger.severe("    Exception caught in Connection.connect().  Exception caught was: "
							+ e5.toString());

				throw e5;
			}

			/*
			 * if (e1 instanceof java.io.IOException) {
			 * IMSTrace.logException((java.io.IOException) e1, this.logWriter,
			 * this.traceLevel); throw (java.io.IOException) e1; } //if
			 */

			this.socket = this.sslSocket;

		} // end else SSL

		if (this.isSetSoTimeoutRequired()) {
			this.setSoTimeout();
			this.setSetSoTimeoutRequired(false);
		}

		this.setIsConnected(true);

		this.socket.setTcpNoDelay(true); // disables Nagle's algorithm (sends
		// are not held for aggregation)
		// this.socket.setKeepAlive(true); // allows early detection of
		// unreachable peer

		if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT))
			// if
			// (logger.getLevel().intValue()<=ApiProperties.TRACE_LEVEL_ENTRY_EXIT.intValue())
			logger.finer("<-- ConnectionImpl.connect()...");
	}

	/**
	 * Releases a connection back to its connection pool or closes the TCP/IP
	 * socket connection.
	 * 

*

    *
  • If connection pooling is enabled for the associated connection pool, * calling the disconnect() method cleans up and release a * connection back to its connection pool for reuse. *
  • If connection pooling is not enabled for the associated connection * pool, calling the disconnect() method closes the underlying * TCP/IP socket connection and destroys the Connection object. * * @throws ImsConnectApiException *
*/ public void disconnect() throws ImsConnectApiException { if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) logger.finer("--> ConnectionImpl.disconnect()..."); /* * if(useConnectionPoolManager == USE_CONNECTION_POOL_MANAGER) { * ConnectionManager.releaseConnection(this); } else */{ //Removing the object from shutdownhook Runtime.getRuntime().removeShutdownHook(this.hook); //to close the socket this.close(); } if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) logger.finer("<-- ConnectionImpl.disconnect()..."); } /** * Intantiates a new TmInteraction instance that characterizes * the interaction with IMS Connect that will be performed on this * Connection instance. Calling the * createInteraction() method sets the connection field of the * new interaction to this Connection instance. * * @throws ImsConnectApiException */ public TmInteraction createInteraction() throws ImsConnectApiException { if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) logger.finer("--> ConnectionImpl.createInteraction()..."); myTmInteraction = (TmInteraction) new TmInteractionImpl(); ((TmInteractionImpl) myTmInteraction).setConnection(this); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) logger.finer("<-- ConnectionImpl.createInteraction()..."); return myTmInteraction; } /** * Instantiates a new TmInteraction instance that characterizes * the interaction with IMS Connect that will be performed on this * Connection instance. Calling the * createInteraction(TmInteractionAttributes) method sets the * connection field of the new interaction to this Connection * instance and the interactionSpec field of the new interaction to the * specified InteractionProfile. * * @param iSpec * the specified IMSConnectInteractionProfile that describes the * interaction with IMS Connect to be performed on this * connection * @return a new TmInteraction instance * @throws ImsConnectApiException */ public TmInteraction createInteraction( TmInteractionAttributes aTMInteractionAttributes) throws ImsConnectApiException { if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) logger.finer("--> ConnectionImpl.createInteraction(TmInteractionAttributes)..."); myTmInteraction = (TmInteraction) new TmInteractionImpl( aTMInteractionAttributes); ((TmInteractionImpl) myTmInteraction).setConnection(this); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) logger.finer("<-- ConnectionImpl.createInteraction(TmInteractionAttributes)..."); return myTmInteraction; } /** * Builds a unique identifier string to be used as a client ID for a * connection when the client rather than IMS Connect is creating the client * ID. *

* The client ID has the value of "XXXYYYYY" where XXX is the client ID * prefix that is product-dependent and comes from the prefix input * parameter and YYYYY is a random value generated based on the IP address * and portNumber value of the socket connection. * * @param prefix * product-dependent client ID prefix * @return the generated client ID to be used for this connection * @throws ImsConnectApiException */ /* * public synchronized String generateClientID(String prefix) { if * (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) // if * (logger.getLevel * ().intValue()<=ApiProperties.TRACE_LEVEL_ENTRY_EXIT.intValue()) * logger.finer("--> ConnectionImpl.generateClientID(String prefix)..."); * Random aRandomGenerator; * * // The IP address and the Port of the connected socket is used to * generate // the Client ID by default. The IP address and portNumber * number are combined // as if they are a single long number e.g. IP * (101.102.103.104) and Port // (5000) -> 1011021031045000. This long * number will be used as a seed to // generate a random number which will . * try { int localPort = this.socket.getLocalPort(); InetAddress localAddr = * this.socket.getLocalAddress(); * * byte[] address = localAddr.getAddress(); * * StringBuffer addBuf = new StringBuffer(address.length * 3 + 100); * * // Each array element contains each dotted section of the IP // address. * // (e.g. 1.2.3.4, 1st array element is "1", 2nd is "2", etc..) // Concate * all the array elements to a single String. // (e.g the resulting String * is "1234") for (int i = 0; i < address.length; i++) { int unsignedByte = * address[i] < 0 ? address[i] + 256 : address[i]; * * String str = Integer.toString(unsignedByte); * * // Padded "0" in front of the address such // that it always contains 3 * digit. // eg. if address is "3", then, it's padded to "003". if (i > 0) { * for (int j = 0; j < 3 - str.length(); j++) addBuf.append("0"); } * addBuf.append(str); } * * addBuf.append(localPort); * * // The Address+Port is treated as a long integer, which is // used as a * seed to the RandomGenerator Long addAsLong = new Long(addBuf.toString()); * aRandomGenerator = new Random(addAsLong.longValue()); * * } catch (Exception e) { // If any exception occurs, using the current * time as the seed. aRandomGenerator = new Random(); } * * int aRandomNumber = aRandomGenerator.nextInt(); StringBuffer clientID = * new StringBuffer(); * * // The Client ID is created with a product-specific // prefix. * clientID.append(prefix); * * // Generate a random alphanumeric string and append to the Client ID // * until it is 8 chars long. for (; clientID.length() < 8; aRandomNumber = * aRandomGenerator.nextInt()) { String genStr = * (Integer.toString(Math.abs(aRandomNumber), 36)).toUpperCase(); * clientID.append(genStr); } * * if (logger.isLoggable(ApiProperties.TRACE_LEVEL_INTERNAL)) * logger.finest(" Generated clientID = [" + clientID + "]"); * * if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) * logger.finer("<-- ConnectionImpl.generateClientID(String prefix)..."); * * // return clientID.substring(0, 8); return new String(clientID); } */ /** * Returns a hash key for this connection which is used to determine the * connection pool to which this connection is (or will be) assigned if * connection management is configured and enabled. * * @return the hash key value as a String */ @SuppressWarnings("unused") private String hashKey() { if ((hostName != null) && (portNumber != -1)) return this.hostName + String.valueOf(this.portNumber) + String.valueOf(this.useSslConnection) + this.sslEncryptionType; else return null; } /** * Validates the input Object. * * @param inObj * the input String object to be tested. * @return true if the input string is not null * and has a length greater than 0 after leading and trailing * whitespace is removed. Otherwise, it returns false . */ private boolean hasValue(Object inObj) { if (inObj != null) { if (inObj.getClass().equals(java.lang.String.class)) { if (((String) inObj).trim().length() > 0) return true; else return false; } else // if (inObj.getClass().equals(java.io.InputStream.class)) { return true; } } else return false; } /** * initContext is used only for SSL connections. This method takes the * required SSL parameters such as keystore, truststore etc., and creates * the SSLContext needed by TCP/IP for the SSL handshaking process. * * @param aKeystoreName * Optional. Name of Keystore to be used for this connection. * @param aKeyStorePasswd * Optional (required if a valid keystore name is specified in * aKeyStoreName.) Password for keystore pointed to by * aKeyStoreName. * @param aTruststoreName * Optional. Name of truststore to be used for this connection * @param aTrustStorePassword * Optional (required if a valid truststore name is specified in * aTrustStoreName.) Password for truststore pointed to by * aTrustStoreName. */ private void initContext(InputStream aKeystoreInputStream, URL aKeystoreUrl, String aKeystoreName, String aKeyStorePasswd, InputStream aTruststoreInputStream, URL aTruststoreUrl, String aTruststoreName, String aTrustStorePasswd) throws ImsConnectApiException { if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) logger.finer("--> ConnectionImpl.initContext(String aKeyStoreName, String aKeyStorePasswd, String aTrustStoreName, String aTrustStorePasswd)..."); KeyManagerFactory kmf; InputStream keystoreInputStream = null; TrustManagerFactory tmf; InputStream truststoreInputStream = null; TrustManager[] tm = null; KeyManager[] km = null; // Determine which name to use to designate the X.509 // SSL certificate type. IBM's JSSE uses "IbmX509" while // Sun's JSSE uses "SunX509". if (!System.getProperty("java.vendor").equals("IBM Corporation")) sslCertType = ApiProperties.SUN_SSL_CERT_TYPE; else sslCertType = ApiProperties.IBM_SSL_CERT_TYPE; KeyStore ks = null; KeyStore ts = null; try { System.setProperty("javax.net.debug", "false"); kmf = KeyManagerFactory.getInstance(sslCertType); tmf = TrustManagerFactory.getInstance(sslCertType); if (hasValue(aKeyStorePasswd)) { char[] ksPass = aKeyStorePasswd.toCharArray(); ks = KeyStore.getInstance(ApiProperties.SSL_STORE_TYPE_JKS); if (hasValue(aKeystoreInputStream)) { keystoreInputStream = aKeystoreInputStream; } else if (hasValue(aKeystoreUrl)) { keystoreInputStream = aKeystoreUrl.openStream(); } else { keystoreInputStream = new FileInputStream(aKeystoreName); } ks.load(keystoreInputStream, ksPass); if (!hasValue(aKeystoreInputStream)) // close the // keystoreInputStream // if the API opened it keystoreInputStream.close(); kmf.init(ks, ksPass); km = kmf.getKeyManagers(); } if (hasValue(aTrustStorePasswd)) { char[] tsPass = aTrustStorePasswd.toCharArray(); ts = KeyStore.getInstance(ApiProperties.SSL_STORE_TYPE_JKS); if (hasValue(aTruststoreInputStream)) { truststoreInputStream = aTruststoreInputStream; } else if (hasValue(aTruststoreUrl)) { truststoreInputStream = aTruststoreUrl.openStream(); } else { truststoreInputStream = new FileInputStream(aTruststoreName); } ts.load(truststoreInputStream, tsPass); if (!hasValue(aTruststoreInputStream)) // close the // truststoreInputStream // if the API opened it truststoreInputStream.close(); tmf.init(ts); tm = tmf.getTrustManagers(); } // The following statements are intended to ensure that the keystore // and truststore values are used. // System.setProperty("javax.net.ssl.keyStore", aKeyStoreName); // System.setProperty("javax.net.ssl.keyStorePassword", // aKeyStorePasswd); // System.setProperty("javax.net.ssl.trustStore", aTrustStoreName); // System.setProperty("javax.net.ssl.trustStorePassword", // aTrustStorePasswd); sslContext = SSLContext.getInstance("TLS"); sslContext.init(km, tm, null); } catch (Exception e1) { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0009E, new Object[] { ImsConnectErrorMessage .getExceptionMessage(e1) }); ImsConnectApiException e2 = new ImsConnectApiException( ImsConnectErrorMessage.HWS0009E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception caught in Connection.initContext(). Exception caught was: " + e1.toString()); throw e2; } finally { try { // if (!hasValue(aKeystoreInputStream)) // close the // keystoreInputStream if the API opened it // keystoreInputStream.close(); } catch (Exception e) { } try { // if (!hasValue(aTruststoreInputStream)) // close the // truststoreInputStream if the API opened it // truststoreInputStream.close(); } catch (Exception e) { } } if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) logger.finer("<-- ConnectionImpl.initContext(String aKeyStoreName, String aKeyStorePasswd, String aTrustStoreName, String aTrustStorePasswd)..."); } /** * Sets Connection properties with values read in from a * connection attributes file * * @param aConnectionAttributesFileName * text file containing the connection attributes * @throws Exception */ public void loadConnectionAttributesFromFile( String aConnectionAttributesFileName) throws Exception { PropertiesFileLoader myPropertiesFileLoader = new PropertiesFileLoader(); myPropertiesFileLoader.loadPropertiesFile(this, aConnectionAttributesFileName); } /** * Sets the connection attributes of this Connection object. * * @param aConnectionAttributes * a ConnectionAttributes object with connection * properties specified. */ public void loadConnectionAttributesFromObject( ConnectionAttributes aConnectionAttributes) { /*** Connection properties ***/ clientId = aConnectionAttributes.getClientId(); hostName = aConnectionAttributes.getHostName(); portNumber = aConnectionAttributes.getPortNumber(); interactionTimeout = aConnectionAttributes.getInteractionTimeout(); socketType = aConnectionAttributes.getSocketType(); /*** SSL properties ***/ useSslConnection = DEFAULT_USE_SSL_CONNECTION; sslKeystoreName = aConnectionAttributes.getSslKeystoreName(); sslKeystorePassword = aConnectionAttributes.getSslKeystorePassword(); sslTruststoreName = aConnectionAttributes.getSslTruststoreName(); sslTruststorePassword = aConnectionAttributes .getSslTruststorePassword(); sslEncryptionType = aConnectionAttributes.getSslEncryptionType(); /*** Connection management properties ***/ // useConnectionPoolManager = // aConnectionAttributes.getUseConnectionPoolManager(); } /** * setSupportedCipherSuites is used to obtain the list of locally supported * cipher suites at the specified encryption level which can be used during * the SSL handshaking process while initializing the context for this SSL * socket connection. The list obtained is then used to set the enabled * cipher suites for this SSL socket before returning to the caller. * * @param encrypType * Optional (default encryption type - weak - used if encrypType * not specified.) Specifies the level of encryption to be used * on this SSL connection */ private void setSupportedCipherSuites(byte aEncrypType) { if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) logger.finer("--> ConnectionImpl.setSupportedCipherSuites(byte aEncrypType)..."); // variables used in the for loop to load the cipher spec array int i, ci_nonanon, s, w, n; String[] cipherSuites = this.sslContext.getSocketFactory() .getSupportedCipherSuites(); String[] tmpStrongCipherSuites = new String[cipherSuites.length]; String[] tmpWeakCipherSuites = new String[cipherSuites.length]; String[] tmpNullCipherSuites = new String[cipherSuites.length]; String tempString = null; // Load the strong and weak cipher suites. The weak ciphers are those // meant for EXPORT. They have the word "EXPORT" in them. Look for the // word "EXPORT" in the name of the cipher to distinguish between strong // and weak ciphers. for (i = 0, s = 0, w = 0, n = 0, ci_nonanon = 0; i < cipherSuites.length; i++) { if (cipherSuites[i].indexOf("anon") < 0) { ci_nonanon++; // Create a String (tempString) and then copy that to the array. if (cipherSuites[i].indexOf("EXPORT") > 0) { tempString = cipherSuites[i]; tmpWeakCipherSuites[w++] = tempString; // System.out.println(" Weak Ciphers " + cipherSuites[i]); } else if (cipherSuites[i].indexOf("NULL") > 0) { tempString = cipherSuites[i]; tmpNullCipherSuites[n++] = cipherSuites[i]; // System.out.println(" NULL Ciphers " + cipherSuites[i]); } else { tempString = cipherSuites[i]; tmpStrongCipherSuites[s++] = cipherSuites[i]; // System.out.println(" Strong Ciphers " + cipherSuites[i]); } } } /* * if (s == 0 && w == 0 && n == 0) { // System.out.println( * "No non-anonymous Cipher Suites found."); } */ String[] strongCipherSuites = new String[s]; String[] weakCipherSuites = new String[w]; String[] nullCipherSuites = new String[n]; i = 0; if ((0 <= aEncrypType) && (aEncrypType <= 2)) this.sslEncryptionType = aEncrypType; if (sslEncryptionType == SSL_ENCRYPTIONTYPE_STRONG) { System.arraycopy(tmpStrongCipherSuites, 0, strongCipherSuites, 0, s); this.sslSocket.setEnabledCipherSuites(strongCipherSuites); } else if (sslEncryptionType == SSL_ENCRYPTIONTYPE_WEAK) { System.arraycopy(tmpWeakCipherSuites, 0, weakCipherSuites, 0, w); this.sslSocket.setEnabledCipherSuites(weakCipherSuites); } else if (sslEncryptionType == SSL_ENCRYPTIONTYPE_NONE) { System.arraycopy(tmpNullCipherSuites, 0, nullCipherSuites, 0, n); this.sslSocket.setEnabledCipherSuites(nullCipherSuites); } if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) logger.finer("<-- ConnectionImpl.setSupportedCipherSuites(byte aEncrypType)..."); } /** * Reads data received on the socket associated with this * Connection object. * * @return byte[] a byte array containing the data returned by IMS Connect * @throws ImsConnectApiException */ public byte[] receive() throws Exception { int len = 0; byte[] inBytes = null; byte[] tempBytes = null; byte[] llllBytes = { 0, 0, 0, 0 }; byte[] llBytes = { 0, 0 }; byte[] secondLlBytes = { 0, 0 }; // StringBuffer bytesAsStringBuffer = new StringBuffer(""); // int stringBufferLen = 0; DataInputStream responseDataInputStream = null; // BufferedInputStream in = null; String bytesAsString = null; if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) logger.finer("--> ConnectionImpl.receive()..."); imsConnectCodepage = this.myTmInteraction.getImsConnectCodepage(); // logger.fine("shali--> after imsconnectcodepage"); int interactionTimeoutValue = this.getInteractionTimeout(); boolean interactionTimeoutWaitForever = (interactionTimeoutValue == -1 ? true : false); long interactionTimeoutTime = (interactionTimeoutWaitForever ? 0 : System.currentTimeMillis() + interactionTimeoutValue); boolean exceptionCaught = false; try { if (!this.isConnected()) { // System.out.println("\n...in if (!isConnected()) block..."); // logger.fine("Shali--> inside is connected "); String internalMsg = ImsConnectErrorMessage .getString(ImsConnectErrorMessage.NO_CONN); // logger.fine("Shali--> internal message" + internalMsg); String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0008E, new Object[] { this.hostName, String.valueOf(this.portNumber), internalMsg }); ImsConnectCommunicationException e = new ImsConnectCommunicationException( ImsConnectErrorMessage.HWS0008E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.receive(). Exception thrown was: " + e.toString()); throw e; } // System.out.println("\n...creating dInStr..."); responseDataInputStream = new DataInputStream( this.socket.getInputStream()); // in = new BufferedInputStream(this.socket.getInputStream()); if (this.myTmInteraction.isResponseIncludesLlll()) { // in.read(llllBytes, 0, 4); responseDataInputStream.readFully(llllBytes, 0, 4); len = NumberConversion.parseByteArrayToInt(llllBytes, 0); inBytes = new byte[len]; System.arraycopy(llllBytes, 0, inBytes, 0, 4); // --------Adding for Kevin Hite - NEED TO BE // REMOVED-----------------------------------------// /* * if (myTmInteraction.getResponseTimeStatistics() != null) * myTmInteraction.getResponseTimeStatistics() * .addReadStartTime(System.nanoTime()); */ // System.out.println("Start of Second Read : " // + System.nanoTime()); // --------END OF CODE - NEED TO BE // REMOVED-----------------------------------------// responseDataInputStream.readFully(inBytes, 4, len - 4); // int byteCount = 4; // // while (byteCount < len - 4) { // int availableBytes = in.available(); // int iReturn = in.read(inBytes, byteCount, availableBytes); // byteCount += iReturn; // } // System.out.println("End of Second Read : " + // System.nanoTime()); // --------Adding for Kevin Hite - NEED TO BE // REMOVED-----------------------------------------// /* * if (myTmInteraction.getResponseTimeStatistics() != null) * myTmInteraction.getResponseTimeStatistics().addReadEndTime( * System.nanoTime()); */ // --------END OF CODE - NEED TO BE // REMOVED-----------------------------------------// // throw new java.io.IOException("test IOException w/ LLLL"); } else { int sleepTime = 1; int numberOfCalloutRequestSegments = 0; // first segment, could be callout cortkn or non-callout - in // either case, segment format will be LLZZData responseDataInputStream.readFully(llBytes); // in.read(llBytes);// read 2 byte LL from // responseDataInputStream into llBytes len = NumberConversion.parseByteArrayToShort(llBytes, 0); if (len > 3) { inBytes = new byte[len]; System.arraycopy(llBytes, 0, inBytes, 0, 2); // in.read(inBytes, 2, len - 2); responseDataInputStream.readFully(inBytes, 2, len - 2); bytesAsString = new String(inBytes, this.imsConnectCodepage); // bytesAsStringBuffer.append(bytesAsString); // stringBufferLen += len; } // logger.fine("Shali--> length process complete"+bytesAsString); int bytesAsStringLen = bytesAsString.length(); while ((bytesAsStringLen < 12) || // message incomplete so read another segment ((bytesAsString.substring(4, 12)).indexOf("*REQSTS*") == -1) && ((bytesAsString.substring((bytesAsStringLen - 8))) .indexOf("*CSMOKY*") == -1)) { if ((!interactionTimeoutWaitForever) & (System.currentTimeMillis() >= interactionTimeoutTime)) { this.disconnect(); // throw interactionTimeout exception String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0025E, new Object[] { "Interaction", new Integer(this.interactionTimeout), "" }); ImsConnectCommunicationException e = new ImsConnectCommunicationException( ImsConnectErrorMessage.HWS0025E, errMsg); if (logger .isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.receive(). Exception thrown was: " + e.toString()); throw e; } if ((bytesAsStringLen > 12) && (bytesAsString.substring(4, 12).indexOf( "*CORTKN*") == 0) && (numberOfCalloutRequestSegments == 0)) { // Checking ifisreturnModname is set by client if (this.myTmInteraction.isReturnMfsModname()) { // Reading the LLZZ*REQMOD*MODNAME(total 20 bytes) responseDataInputStream.readFully(llBytes);// Reading 2bytes len = NumberConversion.parseByteArrayToShort( llBytes, 0);// Finding the len tempBytes = new byte[inBytes.length + len];// creating temp buffer for holding the all the data that has // been retrieved +new segment System.arraycopy(inBytes, 0, tempBytes, 0, inBytes.length);// Copying already retrieved data to tempBytes System.arraycopy(llBytes, 0, tempBytes, inBytes.length, 2);// Copying the retrieved LLbytes into the tempBytes responseDataInputStream.readFully(tempBytes, inBytes.length + 2, len - 2);// reading from stream the segment with modname // into tempBytes // in.read(tempBytes, inBytes.length + 4, len - 4); inBytes = new byte[tempBytes.length];// creating inBytes with new size System.arraycopy(tempBytes, 0, inBytes, 0, tempBytes.length);// Copying tempBytes to // inBytes } // Checking ifisreturnClientId is set by client if (this.myTmInteraction.isReturnClientId()) { // Reading the LLZZ*GENCID*CLIENTID(total 20 bytes) responseDataInputStream.readFully(llBytes);// Reading 2bytes len = NumberConversion.parseByteArrayToShort( llBytes, 0);// Finding the len tempBytes = new byte[inBytes.length + len];// creating temp buffer for holding the all the data that has // been retrieved +new segment System.arraycopy(inBytes, 0, tempBytes, 0, inBytes.length);// Copying already retrieved data to tempBytes System.arraycopy(llBytes, 0, tempBytes, inBytes.length, 2);// Copying the retrieved LLbytes into the tempBytes responseDataInputStream.readFully(tempBytes, inBytes.length + 2, len - 2);// reading from stream the segment with clientId // into tempBytes // in.read(tempBytes, inBytes.length + 4, len - 4); inBytes = new byte[tempBytes.length];// creating inBytes with new size System.arraycopy(tempBytes, 0, inBytes, 0, tempBytes.length);// Copying tempBytes to // inBytes } // processing 2nd segment and 1st segment included // corTkn so 2nd segment must be LLLLData (a callout // message with no data makes no sense) responseDataInputStream.readFully(llllBytes);// read 4 // byte LLLL from responseDataInputStream into llllBytes // in.read(llllBytes);// read 4 byte LLLL from // responseDataInputStream into llllBytes len = NumberConversion .parseByteArrayToInt(llllBytes, 0); tempBytes = new byte[inBytes.length + len]; System.arraycopy(inBytes, 0, tempBytes, 0, inBytes.length); System.arraycopy(llllBytes, 0, tempBytes, inBytes.length, 4); responseDataInputStream.readFully(tempBytes, inBytes.length + 4, len - 4); // in.read(tempBytes, inBytes.length + 4, len - 4); inBytes = new byte[tempBytes.length]; System.arraycopy(tempBytes, 0, inBytes, 0, tempBytes.length); bytesAsString = new String(inBytes, this.imsConnectCodepage); // bytesAsStringBuffer.append(bytesAsString); // stringBufferLen += len; numberOfCalloutRequestSegments++; } else if ((bytesAsStringLen > 12) && (bytesAsString.substring(4, 12).indexOf( "*CORTKN*") == 0) && (numberOfCalloutRequestSegments > 0)) { // processing 3rd or later callout segment so this // segment could be LLLLData (callout data) or LLZZData // (CSMOKY) responseDataInputStream.readFully(llBytes);// read 2 // byte LL from responseDataInputStream into llBytes // (regardless of whether it is LLLL for sync callout // request data or LLZZ for CSMOKY) // in.read(llBytes);// read 2 byte LL from // responseDataInputStream into llBytes (regardless of // whether it is LLLL for sync callout request data or // LLZZ for CSMOKY) if ((llBytes[0] == 0) && (llBytes[1] == 0)) // must be // LLLL since first two bytes cannot both be 0's for // LLZZ) { responseDataInputStream.readFully(secondLlBytes); // in.read(secondLlBytes); System.arraycopy(llBytes, 0, llllBytes, 0, 2); System.arraycopy(secondLlBytes, 0, llllBytes, 2, 2); len = NumberConversion.parseByteArrayToInt( llllBytes, 0); tempBytes = new byte[inBytes.length + len]; System.arraycopy(inBytes, 0, tempBytes, 0, inBytes.length); System.arraycopy(llllBytes, 0, tempBytes, inBytes.length, 4); responseDataInputStream.readFully(tempBytes, inBytes.length + 4, len - 4); // in.read(tempBytes, inBytes.length + 4, len - 4); inBytes = new byte[tempBytes.length]; System.arraycopy(tempBytes, 0, inBytes, 0, tempBytes.length); bytesAsString = new String(inBytes, this.imsConnectCodepage); // bytesAsStringBuffer.append(bytesAsString); // stringBufferLen += len; numberOfCalloutRequestSegments++; } else // could be LLZZ for CSMOKY segment or first two // bytes of llll for subsequent callout data segment { // try and see if it works out as CSMOKY segment len = NumberConversion.parseByteArrayToShort( llBytes, 0); if (len == 12) // could be CSMOKY segment (LLZZ) or // callout data segment (LLLL) { tempBytes = new byte[inBytes.length + len]; System.arraycopy(inBytes, 0, tempBytes, 0, inBytes.length); System.arraycopy(llBytes, 0, tempBytes, inBytes.length, 2); responseDataInputStream.readFully(tempBytes, inBytes.length + 2, len - 2); inBytes = new byte[tempBytes.length]; System.arraycopy(tempBytes, 0, inBytes, 0, tempBytes.length); bytesAsString = new String(inBytes, this.imsConnectCodepage); // bytesAsStringBuffer.append(bytesAsString); // stringBufferLen += len; if ((bytesAsString.indexOf("*CSMOKY*") > 0) && (llBytes[0] == 0) && (llBytes[1] == 0x0C)) // this is the // CSMOKY segment so we are done with this // receive { break; } else // LLLL = 000CXXXX - we've already read // and saved the first 12 bytes so just // read in remaining LLLL - 12 bytes { System.arraycopy(inBytes, 0, llllBytes, 0, 4); len = NumberConversion.parseByteArrayToInt( llllBytes, 0) - 12; inBytes = new byte[len]; // in.read(tempBytes, 0, len); responseDataInputStream.readFully( tempBytes, 0, len); inBytes = new byte[tempBytes.length]; System.arraycopy(tempBytes, 0, inBytes, 0, tempBytes.length); bytesAsString = new String(inBytes, this.imsConnectCodepage); // bytesAsStringBuffer.append(bytesAsString); // stringBufferLen += len; numberOfCalloutRequestSegments++; } } else // can't be CSMOKY so must be LLLL for // subsequent callout data segment { System.arraycopy(llBytes, 0, llllBytes, 0, 2); responseDataInputStream .readFully(secondLlBytes); // in.read(secondLlBytes); System.arraycopy(secondLlBytes, 0, llllBytes, 2, 2); len = NumberConversion.parseByteArrayToInt( llllBytes, 0); tempBytes = new byte[inBytes.length + len]; System.arraycopy(inBytes, 0, tempBytes, 0, inBytes.length); System.arraycopy(llllBytes, 0, tempBytes, inBytes.length, 4); // in.read(tempBytes, inBytes.length + 4, len - // 4); responseDataInputStream.readFully(tempBytes, inBytes.length + 4, len - 4); inBytes = new byte[tempBytes.length]; System.arraycopy(tempBytes, 0, inBytes, 0, tempBytes.length); bytesAsString = new String(inBytes, this.imsConnectCodepage); // bytesAsStringBuffer.append(bytesAsString); // stringBufferLen += len; numberOfCalloutRequestSegments++; } } } else // not callout request so must be LLZZdata of // subsequent non-callout data segment (could be // CSMOKY) { responseDataInputStream.readFully(llBytes);// read 2 // byte LL // from // responseDataInputStream // into // llBytes // in.read(llBytes);// read 2 byte LL from // responseDataInputStream into llBytes len = NumberConversion .parseByteArrayToShort(llBytes, 0); tempBytes = new byte[inBytes.length + len]; System.arraycopy(inBytes, 0, tempBytes, 0, inBytes.length); System.arraycopy(llBytes, 0, tempBytes, inBytes.length, 2); // in.read(tempBytes, inBytes.length + 2, len - 2); responseDataInputStream.readFully(tempBytes, inBytes.length + 2, len - 2); inBytes = new byte[tempBytes.length]; System.arraycopy(tempBytes, 0, inBytes, 0, tempBytes.length); bytesAsString = new String(inBytes, this.imsConnectCodepage); // bytesAsStringBuffer.append(bytesAsString); // stringBufferLen += len; } // logger.fine("before the length zero :" + len); if (len == 0) { Thread.sleep(sleepTime); if (sleepTime < 10) sleepTime += 1; else if (sleepTime < 50) sleepTime += 10; else if (sleepTime < 100) sleepTime += 25; else sleepTime += 100; } } // inBytes = // bytesAsStringBuffer.toString().getBytes(imsConnectCodepage); } return inBytes; // } } catch (SocketTimeoutException e1) { exceptionCaught = true; String sockTimeoutStr = ""; try { int sockTimeout = this.socket.getSoTimeout(); sockTimeoutStr = String.valueOf(sockTimeout); } catch (SocketException e) { if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) { logger.severe(" Exception caught while processing SocketTimeoutException in Connection.receive()"); logger.severe(" Exception caught was: [" + e.toString() + "]"); logger.severe(" Original SocketExceptionTimeout was: [" + e1.toString() + "]"); } } String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0025E, new Object[] { "Interaction", sockTimeoutStr, ImsConnectErrorMessage.getExceptionMessage(e1) }); ImsConnectCommunicationException e2 = new ImsConnectCommunicationException( ImsConnectErrorMessage.HWS0025E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" SocketTimeoutException caught in Connection.receive(). Exception caught was: " + e2.toString()); throw e2; } catch (IOException e3) { exceptionCaught = true; String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0008E, new Object[] { this.hostName, String.valueOf(this.portNumber), ImsConnectErrorMessage.getExceptionMessage(e3) }); ImsConnectCommunicationException e4 = new ImsConnectCommunicationException( ImsConnectErrorMessage.HWS0008E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" IOException caught in Connection.receive(). Exception caught was: " + e4.toString()); throw e4; } catch (ImsConnectCommunicationException e5) { throw e5; } catch (Exception e6) { exceptionCaught = true; String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0001E, new Object[] { ImsConnectErrorMessage .getExceptionMessage(e6) }); ImsConnectCommunicationException e7 = new ImsConnectCommunicationException( ImsConnectErrorMessage.HWS0001E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception caught in Connection.receive(). Exception caught was: " + e7.toString()); throw e6; } finally { if ((logger.isLoggable(ApiProperties.TRACE_LEVEL_INTERNAL)) && (exceptionCaught == true)) { if ((bytesAsString != null) && (bytesAsString.length() > 0)) { int inBytesLength = inBytes.length; boolean obfuscatePassword = true; String bufferReceived = null; String[] bufferReceivedStringArray = null; bufferReceived = ((TmInteractionImpl) myTmInteraction) .formatBufferForTracing(inBytes, obfuscatePassword); bufferReceivedStringArray = ((TmInteractionImpl) myTmInteraction) .stringToStringArray(bufferReceived); logger.finest(" Connection.receive() - Buffer received from stringbuffer: (may be corrupt or incomplete)"); for (int i = 0; i < bufferReceivedStringArray.length; i++) { logger.finest(bufferReceivedStringArray[i]); } bufferReceived = null; bufferReceivedStringArray = null; if (inBytesLength > 0) { bufferReceived = ((TmInteractionImpl) myTmInteraction) .formatBufferForTracing(inBytes, obfuscatePassword); bufferReceivedStringArray = ((TmInteractionImpl) myTmInteraction) .stringToStringArray(bufferReceived); logger.finest(" Connection.receive() - Buffer received from receive byte array: (may be corrupt or incomplete)"); for (int i = 0; i < bufferReceivedStringArray.length; i++) { logger.finest(bufferReceivedStringArray[i]); } bufferReceived = null; bufferReceivedStringArray = null; } } } if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) logger.finer("<-- ConnectionImpl.receive()..."); } } /** * Writes data to be sent to IMS Connect to the socket associated with this * Connection object. * * @param outBytes * a byte array containing the data to be sent to IMS Connect * @throws ImsConnectApiException */ public void send(byte[] outBytes) throws ImsConnectApiException { if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) // if // (logger.getLevel().intValue()<=ApiProperties.TRACE_LEVEL_ENTRY_EXIT.intValue()) logger.finer("--> ConnectionImpl.send(byte[])..."); try { if (!isConnected()) { // System.out.println("\n...in if (!isConnected()) block..."); String internalMsg = ImsConnectErrorMessage .getString(ImsConnectErrorMessage.NO_CONN); String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0008E, new Object[] { this.hostName, String.valueOf(this.portNumber), internalMsg }); ImsConnectCommunicationException e = new ImsConnectCommunicationException( ImsConnectErrorMessage.HWS0008E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.send(byte[]). Exception thrown was: " + e.toString()); throw e; } // --------Adding for Kevin Hite - NEED TO BE // REMOVED-----------------------------------------// // System.out.println("Start of First Write : " + // System.nanoTime()); /* * if (myTmInteraction.getResponseTimeStatistics() != null) * myTmInteraction.getResponseTimeStatistics().addWriteStartTime( * System.nanoTime()); */ // --------END OF CODE - NEED TO BE // REMOVED-----------------------------------------// OutputStream out = this.socket.getOutputStream(); // OutputStream out = new // BufferedOutputStream(this.socket.getOutputStream()); out.write(outBytes); // out.flush(); // --------Adding for Kevin Hite - NEED TO BE // REMOVED-----------------------------------------// // System.out.println("End of First Write : " + System.nanoTime()); /* * if (myTmInteraction.getResponseTimeStatistics() != null) * myTmInteraction.getResponseTimeStatistics().addWriteEndTime( * System.nanoTime()); */ // --------END OF CODE - NEED TO BE // REMOVED-----------------------------------------// } catch (IOException e1) { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0008E, new Object[] { this.hostName, String.valueOf(this.portNumber), ImsConnectErrorMessage.getExceptionMessage(e1) }); ImsConnectCommunicationException e2 = new ImsConnectCommunicationException( ImsConnectErrorMessage.HWS0008E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" IOException caught in Connection.send(byte[]). Exception caught was: " + e2.toString()); throw e2; } finally { if (logger.isLoggable(ApiProperties.TRACE_LEVEL_ENTRY_EXIT)) logger.finer("<-- ConnectionImpl.send(byte[])..."); } } /** * Gets the clientId property value. * * @return the clientId property value as a String. * @see Connection#setClientId(String) */ public String getClientId() { return this.clientId; } /** * Sets the clientId field of this Connection object, which is * used by IMS Connect and IMS to identify IMS Connect clients. The clientId * is also used for the names of asynchronous message queues (OTMA Tpipes) * and other internal data structures in IMS Connect and OTMA. *

* The clientId value is a string of 1 to 8 uppercase alphanumeric (A * through Z, 0 to 9) or special (@, #, $) characters, left justified, and * padded with blanks. *

* This value can be created by the client application or assigned by IMS * Connect. If, in the input message for the first request sent to IMS * Connect on a newly opened Connection, the clientId property value is all * blanks, a unique clientId (unique among all of the clients connected to a * given port on a specific IMS Connect) will be assigned by the user * message exit on the target IMS Connect. Because IMS Connect is not able * to return a generated clientId value to the client application in the * response message, for those situations in which generated clientIds are * used, the clientId property value in the Connection object (all blanks) * will be different than the clientId value used to identify this * connection in IMS Connect (the generated clientId value.) *

* The clientID value specified in this Connection object will only be used * by IMS Connect during processing of the first request message received on * this Connection. After that time, the clientId value specified by the * client during subsequent interactions on that connection will be ignored * by IMS Connect. However, if a Connection is disconnected, and then * reconnected, the Connection will be treated as a new Connection and the * current clientId value at the time the first request message is sent in * to IMS Connect on that "new" Connection will be used as described above. *

* If setClientId() is called after a connection has been established (in * other words, after the connect() method has been called either by the API * client application explicitly or by the API interally,) an exception will * be thrown by the API indicating that an attempt was made to change the * clientId of an already-connected Connection, which is not allowed. * * @param clientID * the clientId to be used for this interaction. * @see ApiProperties#DEFAULT_CLIENTID * @throws ImsConnectApiException */ public final void setClientId(String aClientId) throws ImsConnectApiException { if ((!this.isConnected())|| (returnedClientID == true)) { if (aClientId.trim().equals("")) { if (!clientId.equals(EIGHT_BLANKS)) { this.clientId = " "; this.updateIrmClientId = true; } } else if (PropertiesFileLoader.isValidHostStyleName(aClientId.trim())) { if (!aClientId.equals(clientId)) { this.clientId = aClientId.toUpperCase(); this.updateIrmClientId = true; } } else if (aClientId.length() > 8) { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0026E, new Object[] { aClientId, "clientId", "8" }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0026E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setClientId(String). Exception thrown was: " + e.toString()); throw e; } else { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0029E, new Object[] { "clientID", aClientId }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0029E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setClientId(String). Exception thrown was: " + e.toString()); throw e; } } else { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0033E, new Object[] { "clientId", this.clientId }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0033E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setClientId(String). Exception thrown was: " + e.toString()); throw e; } } /** * Gets the hostName property value. * * @return the hostName property value as a String. * @see Connection#setHostName(String) */ public String getHostName() { return this.hostName; } /** * Sets the value of the hostName field of this Connection. The * hostName property is a String variable whose value is the * hostname or IP address of the target IMS Connect for this connection. *

* The input String must be either: *

    *
  • a 1 to 8 character String set to the correct hostname of * the target IMS Connect, or *
  • a String containing the IP V4 or IP V6 address of the * target IMS Connect (e.g. "nnn.nnn.nnn.nnn" or "nnn.nnn.nnn.nnn.nnn.nnn"). *
*

* If a value for this property is not supplied by the client, the default * value ("HOSTNAME") will be used. * * @param aHostName * the hostName or IP address to be used for this interaction. * @see ApiProperties#DEFAULT_HOSTNAME * @throws ImsConnectApiException */ public void setHostName(String aHostName) throws ImsConnectApiException { if (!this.isConnected()) { int octet; String[] result = aHostName.split("\\."); // result is array of // octets as Strings boolean valid = true; boolean ipAddress = true; int i, numberOfNodes = result.length; // number of octets - should // be 4 for IPV4 and 6 fo // IPV6 for (i = 0; i < numberOfNodes; i++) // convert octets to intergers // and validate them { try { octet = Integer.parseInt(result[i]); if ((octet < 0) || (octet > 255)) { valid = false; break; } } catch (Exception e) { valid = false; ipAddress = false; break; } } if ((valid == true) && // nodes are all numbers between 0 and 255, // inclusive (ipAddress == true) && // hostname should be an IP address ((numberOfNodes != 4) && (numberOfNodes != 6))) // it is not // a valid IPV4 or IPV6 address { valid = false; } if (ipAddress == false) // aHostName is not valid IP address { char[] charBuf; int strLen; if ((aHostName.length() <= 255) && (validLetters.indexOf(aHostName.charAt(0)) != -1)) // aHostName // must be shorter than 256 { // characters and start with a letter if (numberOfNodes <= 127) { valid = true; for (i = 0; i < numberOfNodes; i++) // check each node { int j; strLen = result[i].length(); if (strLen > 63) // each octet must be shorter than // 64 characters { valid = false; i = numberOfNodes; } else { charBuf = new char[strLen]; result[i].getChars(0, strLen, charBuf, 0); // copy // characters in this node to charbuf for // // validation for (j = 0; j < strLen; j++) // loop to validate // characters in // current // node(in // charBuf) { if (validChars.indexOf(charBuf[j]) == -1) { valid = false; // not valid so no need // for further checking i = numberOfNodes; // to exit // numberOfNodes for // loop j = strLen; // to exit strLen for loop } } } } } } else valid = false; } if (valid) { this.hostName = aHostName; } else { String validHostnameString = ""; try { validHostnameString = ImsConnectErrorMessage .getString(ImsConnectErrorMessage.VALID_PROPERTY_VALUE_HOSTNAME); } catch (Exception e1) { } String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0030E, new Object[] { "hostName", aHostName, validHostnameString }); ImsConnectApiException e1 = new ImsConnectApiException( ImsConnectErrorMessage.HWS0030E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception caught in Connection.setHostName(String). Exception caught was: " + e1.toString()); throw e1; } } else { if (this.hostName.equalsIgnoreCase(aHostName)) { return; } else { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0033E, new Object[] { "hostName", this.clientId }); ImsConnectApiException e1 = new ImsConnectApiException( ImsConnectErrorMessage.HWS0033E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setHostName(String). Exception thrown was: " + e1.toString()); throw e1; } } } /** * Gets the interactionTimeout property value. * * @return the interactionTimeout property value as an int in * milliseconds. */ public int getInteractionTimeout() { return this.interactionTimeout; } /** * Sets the interactionTimeout field of this Connection * instance and the SO_TIMEOUT value of the underlying socket. *

* The interaction timeout value is in milliseconds. A positive non-zero * value for interactionTimeout causes the SO_TIMEOUT value to be set to * that number of milliseconds. An interactionTimeout value of -1 disables * the SO_TIMEOUT function. If the SO_TIMEOUT function is disabled, a socket * will block forever or until data available to be read on that socket by * the IMS Connect API on behalf of the client application. * * @param anInteractionTimeout * the interaction timeout value in milliseconds. You can specify * this parameter by using the constants defined in ApiProperties * or by providing a valid non-negative integer value. * @see ApiProperties#TIMEOUT_100_MILLISECONDS * @see ApiProperties#TIMEOUT_10_MILLISECONDS * @see ApiProperties#TIMEOUT_10_MINUTES * @see ApiProperties#TIMEOUT_10_SECONDS * @see ApiProperties#TIMEOUT_12_HOURS * @see ApiProperties#TIMEOUT_1_DAY * @see ApiProperties#TIMEOUT_1_HOUR * @see ApiProperties#TIMEOUT_1_MILLISECOND * @see ApiProperties#TIMEOUT_1_MINUTE * @see ApiProperties#TIMEOUT_1_SECOND * @see ApiProperties#TIMEOUT_1_WEEK * @see ApiProperties#TIMEOUT_200_MILLISECONDS * @see ApiProperties#TIMEOUT_20_MILLISECONDS * @see ApiProperties#TIMEOUT_2_DAYS * @see ApiProperties#TIMEOUT_2_HOURS * @see ApiProperties#TIMEOUT_2_MILLISECONDS * @see ApiProperties#TIMEOUT_2_MINUTES * @see ApiProperties#TIMEOUT_2_SECONDS * @see ApiProperties#TIMEOUT_2_WEEKS * @see ApiProperties#TIMEOUT_30_MINUTES * @see ApiProperties#TIMEOUT_30_SECONDS * @see ApiProperties#TIMEOUT_45_SECONDS * @see ApiProperties#TIMEOUT_45_MINUTES * @see ApiProperties#TIMEOUT_4_HOURS * @see ApiProperties#TIMEOUT_500_MILLISECONDS * @see ApiProperties#TIMEOUT_50_MILLISECONDS * @see ApiProperties#TIMEOUT_5_DAYS * @see ApiProperties#TIMEOUT_5_MILLISECONDS * @see ApiProperties#TIMEOUT_5_MINUTES * @see ApiProperties#TIMEOUT_5_SECONDS * @see ApiProperties#TIMEOUT_8_HOURS * @see ApiProperties#TIMEOUT_MAX * @see ApiProperties#TIMEOUT_WAIT_FOREVER * @throws ImsConnectCommunicationException */ public void setInteractionTimeout(int anInteractionTimeout) throws ImsConnectApiException { if (anInteractionTimeout <= 0 && anInteractionTimeout != -1) { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0007E, new Object[] { "ConnectionImpl.setInteractionTimeout(int)", String.valueOf(anInteractionTimeout) }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0007E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setInteractionTimeout(int). Exception thrown was: " + e.toString()); throw e; } else { this.interactionTimeout = anInteractionTimeout; if (isConnected()) this.setSoTimeout(); else this.setSetSoTimeoutRequired(true); } } /** * Gets the portNumber property value. * * @return the portNumber value. * @see Connection#setPortNumber(int) */ public int getPortNumber() { return this.portNumber; } /** * Sets the value of the portNumber field of this Connection object. The * portNumber property specifies a TCP/IP port where the target IMS Connect * is listening for requests for new connections from clients. *

* If a value for this property is not supplied by the client, the default * value (9999) will be used. * * @param aPortNumber * a valid port number on which the target IMS Connect is * listening for incoming requests from IMS Connnect clients. * @see ApiProperties#DEFAULT_PORTNUMBER * @throws ImsConnectApiException */ public void setPortNumber(int aPortNumber) throws ImsConnectApiException { if (aPortNumber > 0 && aPortNumber <= 65535) if (this.getPortNumber() == aPortNumber) return; else { if (!this.isConnected()) this.portNumber = aPortNumber; else { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0033E, new Object[] { "portNumber", this.clientId }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0033E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setPortNumber(int). Exception thrown was: " + e.toString()); throw e; } } else { String validPortNumberString = ""; try { validPortNumberString = ImsConnectErrorMessage .getString(ImsConnectErrorMessage.VALID_PROPERTY_VALUE_PORTNUMBER); } catch (Exception e1) { // do nothing - this exception should never occur unless the API // JAR is corrupted } String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0030E, new Object[] { "portNumber", String.valueOf(aPortNumber), validPortNumberString }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0030E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setPortNumber(int). Exception thrown was: " + e.toString()); throw e; } } /** * Returns the socket type property. * * @return the socketType. */ protected Socket getSocket() { return socket; } /** * @param socket * the socket to set */ protected void setSocket(Socket socket) { this.socket = socket; } /** * @return the socketConnectTimeout */ public int getSocketConnectTimeout() { return this.socketConnectTimeout; } /** * Sets the socketConnectTimeout field of this Connection. *

* The socketConnectTimeout determines the amount of time that the IMS * Connect API will wait for a socket.connect() call to complete. Only one * value can be specified per socket. The value *

* The valid input values, for some of which, constants are defined in * ApiProperties, are: *

    *
  • -1 - API will wait forever (or until the connect request times out * due to exceeding the maximum number of connection retry attempts defined * in the TCP/IP properties.) *
  • > 0 - API will wait either until the maximum number of connection * retry attempts defined in the TCP/IP properties has been attempted or * until the socketConnectTimeout period has elapsed before throwing a * java.net.SocketTimeoutException. *
*

* Specifying a value less than zero will result in an * ImsConnectCommunicationException being thrown back to the client * application. It should be noted that the actual timeout may be affected * by the maximum number of connect retries allowed by TCP/IP. If the * maximum number of connect retries is exceeded before the timeout pops, an * exception will be thrown by TCP/IP. * * @param aSocketConnectTimeout * the socketConnectTimeout value to set in milliseconds * @see ApiProperties#DEFAULT_SOCKET_CONNECT_TIMEOUT * @see ApiProperties#TIMEOUT_5_SECONDS * @see ApiProperties#TIMEOUT_10_SECONDS * @see ApiProperties#TIMEOUT_15_SECONDS * @see ApiProperties#TIMEOUT_30_SECONDS * @see ApiProperties#TIMEOUT_45_SECONDS * @see ApiProperties#TIMEOUT_1_MINUTE * @see ApiProperties#TIMEOUT_2_MINUTES * @throws ImsConnectApiException */ public void setSocketConnectTimeout(int aSocketConnectTimeout) throws ImsConnectApiException { if (aSocketConnectTimeout > 0 || aSocketConnectTimeout == -1) // allow // >= 0 in next release this.socketConnectTimeout = aSocketConnectTimeout; else { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0007E, new Object[] { "ConnectionImpl.setSocketConnectTimeout(int)", aSocketConnectTimeout }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0007E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setSocketConnectTimeout(). Exception thrown was: " + e.toString()); throw e; } } /** * Gets the socketType property value. * * @return the socketType value. * @see ApiProperties#SOCKET_TYPE_PERSISTENT * @see ApiProperties#SOCKET_TYPE_TRANSACTION */ public byte getSocketType() { return this.socketType; } /** * Sets the socketType field of this Connection. *

* The type of socket connection of a message is set by the client in the * initial input message and maintained in the message until the interaction * has completed. Only one value can be specified per interaction. *

* The valid input values, for which the following constants are defined in * ApiProperties, are: *

    *
  • SOCKET_TYPE_TRANSACTION = 0x00. A transaction socket can only be * disconnected by IMS Connect. Transaction sockets are used for one * transaction (including and required ACKs or NAKs) for non-conversational * transactions or for one complete conversation (until the conversation is * ended by the client or host application) for conversational transactions. * Once the non-conversational IMS transaction interaction or IMS * conversation has completed, the transaction socket is automatically * closed by both IMS Connect and the API. The transaction socket also * closes automatically after IMS itself has terminated or after an error * has occured. *
  • SOCKET_TYPE_PERSISTENT = 0x10. A persistent socket is left connected * by IMS Connect until a fatal error has occured on that connection while * IMS Connect is processing an interaction, or until a disconnect request * has been received by IMS Connect. Any open persistent connections will be * closed automatically by the API when the client application ends. *
  • DEFAULT_SOCKET_TYPE (same as SOCKET_TYPE_PERSISTENT) *
*

* If a value for this property is not supplied by the client, the default * value (SOCKET_TYPE_PERSISTENT) will be used. * * @param anSslEncryptionType * the socket type to be used for this interaction. Use the * constants defined in ApiProperties to specify this parameter. * @see ApiProperties#DEFAULT_SOCKET_TYPE * @see ApiProperties#SOCKET_TYPE_PERSISTENT * @see ApiProperties#SOCKET_TYPE_TRANSACTION * @throws ImsConnectApiException */ public void setSocketType(byte aSocketType) throws ImsConnectApiException { if (this.getSocketType() == aSocketType) return; else { if (this.isConnected()) { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0033E, new Object[] { "socketType", this.clientId }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0033E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setSocketType(byte). Exception thrown was: " + e.toString()); throw e; } else if ((aSocketType == ApiProperties.SOCKET_TYPE_PERSISTENT) || (aSocketType == ApiProperties.SOCKET_TYPE_TRANSACTION)) { this.socketType = aSocketType; } else { String validSocketTypeString = ""; try { validSocketTypeString = ImsConnectErrorMessage .getString(ImsConnectErrorMessage.VALID_PROPERTY_VALUE_SOCKETTYPE); } catch (Exception e1) { // do nothing - this exception should never occur unless the // API JAR is corrupted } String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0030E, new Object[] { "socketType", String.valueOf(aSocketType), validSocketTypeString }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0030E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setSocketType(byte). Exception thrown was: " + e.toString()); throw e; } } } /** * Returns the SSL encryption type property. * * @return the sslEncryptionType. */ public byte getSslEncryptionType() { return this.sslEncryptionType; } /** * Sets the sslEncryptionType field of this Connection. The * sslEncryptionType property is a byte value used to set the encryption * type for the underlying connection when that connnection is an SSL * connection. *

* The valid values, for which the following constants are defined in * ApiProperties, are: *

    *
  • SSL_ENCRYPTIONTYPE_STRONG = 0x02 *
  • SSL_ENCRYPTIONTYPE_WEAK = 0x01 *
  • SSL_ENCRYPTYPE_NONE = 0x00 *
  • DEFAULT_SSL_ENCRYPTIONTYPE (same as SSL_ENCRYPTIONTYPE_WEAK) *
*

* If a value for this property is not supplied by the client, the default * value (SSL_ENCRYPTIONTYPE_WEAK) will be used. *

* SSL_ENCRYPTIONTYPE_STRONG and SSL_ENCRYPTIONTYPE_WEAK reflect the * strength of the cipher used which is related to the key length. All those * ciphers that can be used for export are in the SSL_ENCRYPTIONTYPE_WEAK * category and the rest go into the strong category. The IMS Connect API * will negotiate with IMS Connect to use a strong (greater than 64-bit * encryption key) or weak (64-bit or smaller encryption key) cipher * specification accordingly if either of these two settings are specified. *

* When SSL_ENCRYPTIONTYPE_NONE is specified, the IMS Connect API will * negotiate with IMS Connect to use a cipher spec whose name contains the * string "NULL". Null encryption will allow for authentication to take * place during the SSL handshaking process. Once the handshaking process * for a socket has completed including authentication as required, all * messages will flow in the clear (without encryption) over that socket. * * @param anSslEncryptionType * the sslEncryptionType to be used for this interaction. Use the * constants defined in ApiProperties to specify this parameter. * @see ApiProperties#DEFAULT_SSL_ENCRYPTIONTYPE * @see ApiProperties#SSL_ENCRYPTIONTYPE_NONE * @see ApiProperties#SSL_ENCRYPTIONTYPE_STRONG * @see ApiProperties#SSL_ENCRYPTIONTYPE_WEAK * @throws ImsConnectApiException */ public void setSslEncryptionType(byte anSslEncryptionType) throws ImsConnectApiException { if (this.getSslEncryptionType() == anSslEncryptionType) return; else { if (this.isConnected()) { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0033E, new Object[] { "sslEncryptionType", this.clientId }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0033E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setSslEncryptionType(byte). Exception thrown was: " + e.toString()); throw e; } else if ((anSslEncryptionType == 0) || (anSslEncryptionType == 1) || (anSslEncryptionType == 2)) { this.sslEncryptionType = anSslEncryptionType; } else { String validSslEncryptionTypeString = ""; try { validSslEncryptionTypeString = ImsConnectErrorMessage .getString(ImsConnectErrorMessage.VALID_PROPERTY_VALUE_SSLENCRYPTIONTYPE); } catch (Exception e1) { // do nothing - this exception should never occur unless the // API JAR is corrupted } String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0030E, new Object[] { "socketType", String.valueOf(anSslEncryptionType), validSslEncryptionTypeString }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0030E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setSslEncryptionType(byte). Exception thrown was: " + e.toString()); throw e; } } } /** * @return the sslKeystoreInputStream */ public InputStream getSslKeystoreInputStream() { return this.sslKeystoreInputStream; } /** * Sets the sslKeystoreInputStream field of this Connection. *

* An SSL keystore is a password-protected database intended to contain * private key material, such as private keys and their associated private * key certificates. The private key in your keystore is used for * encrypting/signing outgoing messages that can then only be decrytped * using your public key which you have distributed to your partners. For * your convenience, the IMS Connect API allows both private keys (and their * associated private key certificates) as well as trusted certificates * (usually stored in your truststore) to be stored in the same keystore in * which case the sslTruststoreInputStream, sslTruststoreUrl and/or * sslTruststoreName property can either be null or can point to the * keystore InputStream, URL or file, respectively. Likewise, private keys * or certificates could be stored in the truststore along with your trusted * certificates, in which case the sslKeystoreInputStream, sslKeystoreUrl * and/or sslKeystoreName properties could either be null or could point to * the same or a different keystore or truststore InputStream, URL or file, * respectively. *

* The sslKeystoreInputStream property can be used to specify an InputStream * that wraps a JKS keystore file. When TmInteraction.execute() is called, * if a value is specified for the sslKeystoreName, the sslKeystoreUrl and * the sslKeystoreInputStream, the sslKeystoreInputStream value takes * precedence and will be used by the Connect API to load the keystore. If * the sslKeystoreInputStream value is null, the sslKeystoreUrl value, if * non-null, will be used. Only when both the sslKeystoreInputStream and * sslKeystoreUrl values are null, will the sslKeystoreName be used. If a * value for this property is not set by the client application, the default * value (null) will be used for this property. *

* It is important to note that an InputStream, because it does not support * the mark or reset features, can only be used once. In fact, due to this * restriction, the API internally closes an InputStream after it has loaded * the keystore from that InputStream. * * @param anSslKeystoreInputStream * a java.io.InputStream to be used to set the * sslKeystoreInputStream value for this interaction * @see ApiProperties#DEFAULT_SSL_KEYSTORE_INPUT_STREAM * @see Connection.setSslKeystoreName(String anSslKeystoreName) */ public void setSslKeystoreInputStream(InputStream anSslKeystoreInputStream) { this.sslKeystoreInputStream = anSslKeystoreInputStream; } /** * @return the sslKeystoreUrl */ public URL getSslKeystoreUrl() { return this.sslKeystoreUrl; } /** * Sets the sslKeystoreUrl field of this Connection. *

* An SSL keystore is a password-protected database intended to contain * private key material, such as private keys and their associated private * key certificates. The private key in your keystore is used for * encrypting/signing outgoing messages that can then only be decrytped * using your public key which you have distributed to your partners. For * your convenience, the IMS Connect API allows both private keys (and their * associated private key certificates) as well as trusted certificates * (usually stored in your truststore) to be stored in the same keystore in * which case the sslTruststoreInputStream, sslTruststoreUrl and/or * sslTruststoreName property can either be null or can point to the * keystore InputStream, URL or file, respectively. Likewise, private keys * or certificates could be stored in the truststore along with your trusted * certificates, in which case the sslKeystoreInputStream, sslKeystoreUrl * and/or sslKeystoreName properties could either be null or could point to * the same or a different keystore or truststore InputStream, URL or file, * respectively. *

* The sslKeystoreUrl property can be used to specify a URL that wraps a JKS * keystore file. When TmInteraction.execute() is called, if a value is * specified for the sslKeystoreName, the sslKeystoreUrl and the * sslKeystoreInputStream, the sslKeystoreInputStream value takes precedence * and will be used by the Connect API to load the keystore. If the * sslKeystoreInputStream value is null, the sslKeystoreUrl value, if * non-null, will be used. Only when both the sslKeystoreInputStream and * sslKeystoreUrl values are null, will the sslKeystoreName be used. If a * value for this property is not set by the client application, the default * value (null) will be used for this property. * * @param anSslKeystoreUrl * a java.net.URL to be used to set the * sslKeystoreUrl value for this interaction * @see ApiProperties#DEFAULT_SSL_KEYSTORE_URL * @see Connection.setSslKeystoreName(String anSslKeystoreName) */ public void setSslKeystoreUrl(URL anSslKeystoreUrl) { this.sslKeystoreUrl = anSslKeystoreUrl; } /** * Returns the SSL keystore name as a String. * * @return the sslKeystoreName. */ public String getSslKeystoreName() { return this.sslKeystoreName; } /** * Sets the sslKeystoreName field of this Connection. *

* An SSL keystore is a password-protected database intended to contain * private key material, such as private keys and their associated private * key certificates. The private key in your keystore is used for * encrypting/signing outgoing messages that can then only be decrytped * using your public key which you have distributed to your partners. For * your convenience, the IMS Connect API allows both private keys (and their * associated private key certificates) as well as trusted certificates * (usually stored in your truststore) to be stored in the same keystore in * which case the sslTruststoreInputStream, sslTruststoreUrl and/or * sslTruststoreName property can either be null or can point to the * keystore InputStream, URL or file, respectively. Likewise, private keys * or certificates could be stored in the truststore along with your trusted * certificates, in which case the sslKeystoreInputStream, sslKeystoreUrl * and/or sslKeystoreName properties could either be null or could point to * the same or a different keystore or truststore InputStream, URL or file, * respectively. *

* The sslKeystoreName property can be used to specify either a JKS keystore * or, when running on z/OS, a RACF keyring. For non-z/OS platforms, specify * the fully-qualified path name of your JKS keystore file. For z/OS, you * can specify either the name of your JKS keystore file or a special string * that provides the information needed to access your RACF keyring. *

* An example of a fully-qualified path name of your JKS keystore file is * "c:\keystore\MyKeystore.ks". *

* A RACF keyring is specified as: "keystore_type:keyring_name:racfid". The * keystore_type must be either JCERACFKS when software encryption is used * for SSL or JCE4758RACFKS if hardware encryption is used. Replace * keyring_name with the name of the RACF keyring that you are using as your * keystore and racfid with a RACF ID that is authorized to access the * specified keyring. Examples of RACF keyring specifications are * "JCERACFKS:myKeyring:kruser01" or "JCE4758RACFKS:myKeyring:kruser01". *

* When running on z/OS, if the sslKeystoreName matches the above RACF * keyring format, the IMS Connect API will use the specified RACF keyring * as its keystore. If the keystore type specified is anything other than * JCERACFKS or JCE4758RACFKS, the IMS Connect API attempts to interpret the * sslKeystoreName specified as the name and location of a JKS keystore * file. *

* When TmInteraction.execute() is called, if a value is specified for the * sslKeystoreName, the sslKeystoreUrl and the sslKeystoreInputStream, the * sslKeystoreInputStream value takes precedence and will be used by the * Connect API to load the keystore. If the sslKeystoreInputStream value is * null, the sslKeystoreUrl value, if non-null, will be used. Only when both * the sslKeystoreInputStream and sslKeystoreUrl values are null, will the * sslKeystoreName be used. If a value for this property is not supplied by * the client, nor are values supplied for the sslKeystoreInputStream or * sslKeystoreUrl, the default value from the ApiProperties.java file * (DEFAULT_SSL_KEYSTORE_NAME = "c:\\MySSLKeystores\\myKeystore.ks") will be * used. *

* Note that the JKS keystore file can have other file extensions; it does * not have to use the ".ks" file name extension. * * @param anSslKeystoreName * a java.lang.String containing the name of the JKS * keystore file to be used for this interaction * @see ApiProperties#DEFAULT_SSL_KEYSTORE_NAME * @throws ImsConnectApiException */ public void setSslKeystoreName(String anSslKeystoreName) throws ImsConnectApiException { if (this.getSslKeystoreName() == anSslKeystoreName) return; else { if (!this.isConnected()) { this.sslKeystoreName = anSslKeystoreName; } else { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0033E, new Object[] { "anSslKeystoreName", this.clientId }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0033E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setPortNumber(int). Exception thrown was: " + e.toString()); throw e; } } } /** * Returns the SSL keystore password as a String. * * @return the sslKeystorePassword. */ public String getSslKeystorePassword() { return this.sslKeystorePassword; } /** * Sets the sslKeystorePassword field of this Connection object. The * sslKeystorePassword specifies the password for the JKS keystore pointed * to by sslKeystoreInputStream, sslKeystoreUrl or sslKeystoreName. *

* If a value for this property is not supplied by the client, the default * value ("sslKeystorePassword") will be used. * * @param aSslKeystorePassword * a String specifying the SSL keystore password to * be used for this interaction * @see ApiProperties#DEFAULT_SSL_KEYSTORE_PASSWORD * @throws ImsConnectApiException */ public void setSslKeystorePassword(String anSslKeystorePassword) throws ImsConnectApiException { if (this.getSslKeystorePassword() == anSslKeystorePassword) return; else { if (!this.isConnected()) { this.sslKeystorePassword = anSslKeystorePassword; } else { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0033E, new Object[] { "anSslKeystorePassword", this.clientId }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0033E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setSslKeystorePassword(String). Exception thrown was: " + e.toString()); throw e; } } } /** * @return the sslTruststoreInputStream */ public InputStream getSslTruststoreInputStream() { return this.sslTruststoreInputStream; } /** * Sets the sslTruststoreInputStream field of this Connection. *

* An SSL truststore is a password-protected database intended to contain * certificates of trusted certificate authorities. These certificates are * used to validate the authenticity of a public key certificate during the * handshaking process. For your convenience, the IMS Connect API allows * both private key material as well as the trusted certificates usually * stored in a truststore to be stored in the same truststore, in which case * the sslKeystoreInputStream, sslKeytstoreUrl and/or sslKeystoreName * properties can either be null or can point to the truststore InputStream, * URL or file, respectively. Likewise, both private key material and * trusted certificates could be stored in the same keystore, in which case * the sslTruststoreInputStream, sslTruststoreUrl and/or sslTruststoreName * properties could either be null or could point to the same or a different * keystore or truststore InputStream, URL or file, respectively. *

* The sslTruststoreInputStream property can be used to specify an * InputStream that wraps a JKS keystore file which will be used as a * keystore which contains trusted certificates. When * TmInteraction.execute() is called, if a value is specified for the * sslTruststoreName, the sslTruststoreUrl and the sslTruststoreInputStream, * the sslTruststoreInputStream value takes precedence and will be used by * the Connect API to load the truststore. If the sslTruststoreInputStream * value is null, the sslTruststoreUrl value, if non-null, will be used. * Only when both the sslTruststoreInputStream and sslTruststoreUrl values * are null, will the sslTruststoreName be used. If a value for this * property is not supplied by the client, the default value (null) will be * used for this property. *

* It is important to note that an InputStream, because it does not support * the mark or reset features, can only be used once. In fact, due to this * restriction, the API internally closes an InputStream after it has loaded * the truststore from that InputStream. * * @param anSslTruststoreInputStream * an java.io.InputStream specifying the SSL * truststore to be used for this interaction. * @param sslTruststoreInputStream * the sslTruststoreInputStream to set * @see ApiProperties#DEFAULT_SSL_TRUSTSTORE_INPUT_STREAM * @see Connection.setSslTruststoreName(String anSslTruststoreName) */ public void setSslTruststoreInputStream(InputStream sslTruststoreInputStream) { this.sslTruststoreInputStream = sslTruststoreInputStream; } /** * @return the sslTruststoreUrl */ public URL getSslTruststoreUrl() { return this.sslTruststoreUrl; } /** * Sets the sslTruststoreUrl field of this Connection. *

* An SSL truststore is a password-protected database intended to contain * certificates of trusted certificate authorities. These certificates are * used to validate the authenticity of a public key certificate during the * handshaking process. For your convenience, the IMS Connect API allows * both private key material as well as the trusted certificates usually * stored in a truststore to be stored in the same truststore, in which case * the sslKeystoreInputStream, sslKeytstoreUrl and/or sslKeystoreName * properties can either be null or can point to the truststore InputStream, * URL or file, respectively. Likewise, both private key material and * trusted certificates could be stored in the same keystore, in which case * the sslTruststoreInputStream, sslTruststoreUrl and/or sslTruststoreName * properties could either be null or could point to the same or a different * keystore or truststore InputStream, URL or file, respectively. *

* The sslTruststoreUrl property can be used to specify a URL that wraps a * JKS keystore file. When TmInteraction.execute() is called, if a value is * specified for the sslTruststoreName, the sslTruststoreUrl and the * sslTruststoreInputStream, the sslTruststoreInputStream value takes * precedence and will be used by the Connect API to load the truststore. If * the sslTruststoreInputStream value is null, the sslTruststoreUrl value, * if non-null, will be used. Only when both the sslTruststoreInputStream * and sslTruststoreUrl values are null, will the sslTruststoreName be used. * If a value for this property is not supplied by the client, the default * value (null) will be used for this property. * * @param anSslTruststoreUrl * a java.net.URL pointing to the SSL truststore to * be used for this interaction. * @see ApiProperties#DEFAULT_SSL_TRUSTSTORE_URL * @see Connection.setSslTruststoreName(String anSslTruststoreName) */ public void setSslTruststoreUrl(URL anSslTruststoreUrl) { this.sslTruststoreUrl = anSslTruststoreUrl; } /** * Returns the SSL truststore name as a String. * * @return the sslTruststoreName. */ public String getSslTruststoreName() { return this.sslTruststoreName; } /** * Sets the sslTruststoreName field of this Connection. *

* An SSL truststore is a password-protected database intended to contain * certificates of trusted certificate authorities. These certificates are * used to validate the authenticity of a public key certificate during the * handshaking process. For your convenience, the IMS Connect API allows * both private key material as well as the trusted certificates usually * stored in a truststore to be stored in the same truststore, in which case * the sslKeystoreInputStream, sslKeytstoreUrl and/or sslKeystoreName * properties can either be null or can point to the truststore InputStream, * URL or file, respectively. Likewise, both private key material and * trusted certificates could be stored in the same keystore, in which case * the sslTruststoreInputStream, sslTruststoreUrl and/or sslTruststoreName * properties could either be null or could point to the same or a different * keystore or truststore InputStream, URL or file, respectively. *

* The same format is used for the values of the sslKeystoreName and * sslTruststoreName properties. See the description of * {@link ConnectionFactory#setSslKeystoreName(String)} for a discussion of * this format. The sslTruststoreName property can either be empty (all * blanks) or can point to the keystore file. *

* The sslTruststoreName property can be used to point to a JKS trusted * keystore file. When TmInteraction.execute() is called, if a value is * specified for the sslTruststoreName, the sslTruststoreUrl and the * sslTruststoreInputStream, the sslTruststoreInputStream value takes * precedence and will be used by the Connect API to load the truststore. If * the sslTruststoreInputStream value is null, the sslTruststoreUrl value, * if non-null, will be used. Only when both the sslTruststoreInputStream * and sslTruststoreUrl values are null, will the sslTruststoreName be used. *

* If a value for this property is not supplied by the client, nor are * values supplied for the sslKeystoreInputStream or sslKeystoreUrl, the * default value from the ApiProperties.java file (DEFAULT_SSL_KEYSTORE_NAME * = "c:\\MySSLKeystores\\myKeystore.ks") will be used. *

* Note that the JKS truststore file can have other file extensions; it does * not have to use the ".ks" file name extension. * * @param anSslTrustStoreName * a java.lang.String containing the name of the JKS * trust store file to be used for this interaction * @see ApiProperties#DEFAULT_SSL_TRUSTSTORE_NAME * @throws ImsConnectApiException */ public void setSslTruststoreName(String anSslTruststoreName) throws ImsConnectApiException { if (this.getSslTruststoreName() == anSslTruststoreName) return; else { if (!this.isConnected()) { this.sslTruststoreName = anSslTruststoreName; } else { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0033E, new Object[] { "anSslTruststoreName", this.clientId }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0033E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setSslTruststoreName(String). Exception thrown was: " + e.toString()); throw e; } } } /** * Returns the SSL trust store password as a String. * * @return the sslTruststorePassword. */ public String getSslTruststorePassword() { return this.sslTruststorePassword; } /** * Sets the sslTruststorePassword field of this Connection object which * specifies the password for the JKS truststore pointed to by * sslTruststoreName. This value is ignored if sslTruststoreName is null or * blanks or if sslTruststoreName points to a RACF keyring. The * sslTruststorePassword value is the password for the truststore file * specified in the truststore pointed to by the sslTruststoreName value. *

* If a value for this property is not supplied by the client, the default * value of "sslTruststorePassword" will be used. * * @param aSslTruststorePassword * the JKS truststore password to be used for this interaction. * @see ApiProperties#DEFAULT_SSL_TRUSTSTORE_PASSWORD * @throws ImsConnectApiException */ public void setSslTruststorePassword(String anSslTruststorePassword) throws ImsConnectApiException { if (this.getSslTruststorePassword() == anSslTruststorePassword) return; else { if (!this.isConnected()) { this.sslTruststorePassword = anSslTruststorePassword; } else { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0033E, new Object[] { "anSslTruststoreName", this.clientId }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0033E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setSslTruststorePassword(String). Exception thrown was: " + e.toString()); throw e; } } } /** * Returns true if the SOTimeout of the socket associated with * this connection has not yet been set. * * @return the setSoTimeoutRequired */ protected boolean isSetSoTimeoutRequired() { return this.setSoTimeoutRequired; } /** * setSetSoTimeoutRequired() is a private method that is used to tell the * API when the API needs to set the SO_TIMEOUT of the underlying socket. * setSoTimeout() can only be invoked on an already connected socket, so if * the socket is not connected when setInteractionTimeout() is called, this * method will be called to let the API know that it still needs to set the * SO_TIMEOUT of the socket. * * @param setSoTimeoutRequired * the setSoTimeoutRequired to set */ private void setSetSoTimeoutRequired(boolean setSoTimeoutRequired) { this.setSoTimeoutRequired = setSoTimeoutRequired; } /** * Obtains the list of locally supported cipher suites at the specified * encryption level, which can be used during the SSL handshaking process * while initializing the context for this SSL socket connection. The list * obtained is then used to set the enabled cipher suites for this SSL * socket before returning to the caller. * * @return list of supported optional cipher suites for the current * sslSocket. */ public String[] getSupportedCipherSuites() { if (sslSocket != null) { return this.sslSocket.getEnabledCipherSuites(); } else return null; } /** * Returns true if there is a connected socket associated with * this connection. * * @return true if this connection is connected, otherwise * false. */ public boolean isConnected() { return this.isConnected; } /** * Returns true if the connection is stale. * * @return true if the connection is stale, otherwise * false. */ /* * public boolean isStaleConnection() { return this.staleConnection; } */ /** * * @return true if connection pool management is enabled. * Otherwise, false. */ /* * public boolean isUseConnectionPoolManager() { return * this.useConnectionPoolManager; } */ /** * Gets the useSslConnection property value. If this method returns * true, the underlying connection is an SSL connection or will * be when connected. * * @return true if the connection uses SSL. Otherwise, * false. */ public boolean isUseSslConnection() { return this.useSslConnection; } /** * Configures this Connection instance to connect to IMS * Connect using an SSL connection. A true value sets the * connection as an SSL connection, while a false value * indicates that the connection will be a non-SSL TCP/IP connection. If a * value for this property is not supplied by the client, the default value * of false will be used. * * @param useSSL * Set the input to true to set the connection to be * an SSL connection. Set the input to false to set * the connection to be an non-SSL connection. * @see ApiProperties#DEFAULT_USE_SSL_CONNECTION * @throws ImsConnectApiException */ public void setUseSslConnection(boolean aUseSslConnection) throws ImsConnectApiException { if (this.isUseSslConnection() == aUseSslConnection) return; else { if (!this.isConnected()) { this.useSslConnection = aUseSslConnection; } else { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0033E, new Object[] { "useSslConnection", this.clientId }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0033E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setUseSslConnection(String). Exception thrown was: " + e.toString()); throw e; } } } /** * @param isStaleConnection * The isStaleConnection value to set. */ /* * protected void setStaleConnection(boolean isStaleConnection) { * this.staleConnection = isStaleConnection; } */ /** * Sets the internal connection manager to be enabled or disabled for this * interaction. * * @param aUseConnectionPoolManager * Set the input to true to enable the internal * connection manager. Set the input to false to * disable the internal connection manager. */ /* * public void setUseConnectionPoolManager(boolean * aUseConnectionPoolManager) { this.useConnectionPoolManager = * aUseConnectionPoolManager; } */ /** * Sets the value of the isConnected field of this Connection object. The * portNumber property specifies a TCP/IP port where the target IMS Connect * is listening for requests for new connections from clients. *

* If a value for this property is not supplied by the client, the default * value (9999) will be used. * * @param anIsConnected * Set the input to true to indicate that socket has * been successfully connected to the endpoint. Set the input to * false to indicate that socket is not connected to * the endpoint. */ private void setIsConnected(boolean anIsConnected) { if (this.isConnected() != anIsConnected) this.isConnected = anIsConnected; } /** * setSoTimeout() is a private method that is used by this Connection * object's setInteractionTimeout() or connect() method. setSoTimeout() * invokes the setSoTimeout() method of the underlying socket both enabling * or disabling SO_TIMEOUT for that socket, along with setting the * SO_TIMEOUT value of the socket to the value of the * interactionTimeout field of this Connection object. The * interactionTimeout value is specified in milliseconds. A * greater-than-zero value for interactionTimeout causes the SO_TIMEOUT * value to be set to that number of milliseconds which will in turn cause a * SocketTimeoutException to be thrown if a socket is still blocking on a * read call after this timeout expires. An interactionTimeout value of * zero, disables the SO_TIMEOUT function which allows a socket read call to * block forever or until data is available to be read. An * interactionTimeout value of -1 is changed to 0 for use in the setting the * SO_TIMEOUT value which causes a socket read call to block forever or * until data is available to be read. Any other negative value will cause a * SocketException to be thrown internally which will be converted to an * IMSConnectApiException which will in turn be thrown back to the client * application. * * @throws ImsConnectApiException */ private void setSoTimeout() throws ImsConnectCommunicationException { try { if (this.interactionTimeout == -1) this.socket.setSoTimeout(0); else if (this.interactionTimeout >= 0) this.socket.setSoTimeout(this.interactionTimeout); } catch (SocketException e1) { String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0037E, new Object[] { "socket.setSoTimeout()", e1.toString() }); ImsConnectCommunicationException e = new ImsConnectCommunicationException( ImsConnectErrorMessage.HWS0037E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setSoTimeout(). Exception thrown was: " + e.toString()); throw e; } } public void run() // added in order to be able to implement runnable so that // receive can use sleep() { } public String toString() { StringBuilder buf = new StringBuilder(); buf.append(this.hostName); buf.append(","); buf.append(this.portNumber); buf.append(","); buf.append(this.interactionTimeout); buf.append(","); buf.append(this.sslEncryptionType); buf.append(","); buf.append(this.sslKeystoreName); buf.append(","); buf.append(this.sslTruststoreName); buf.append(","); buf.append(this.useSslConnection); return (buf.toString()); // return this.hostName + "," + this.portNumber + ","+ // this.interactionTimeout + "," + this.sslEncryptionType + ","+ // this.sslKeystoreName + "," + this.sslTruststoreName + ","+ // this.useSslConnection; } // @SuppressWarnings("unused") // private class ShutdownHook extends Thread { // public void run(Connection aConnection) { // if (aConnection.isConnected()) // ((ConnectionImpl) aConnection).close(); // } // } public void finalize() { try { if (isUseSslConnection()) { sslKeystoreInputStream.close(); sslTruststoreInputStream.close(); } if (this.isConnected()) this.close(); } catch (Exception e) { if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.finalize() while removing unused Connection instance. Exception thrown was: " + e.toString()); } } private String validateHostName(String host) throws ImsConnectApiException { int octet; String[] result = host.split("\\."); // result is array of // octets as Strings boolean valid = true; boolean ipAddress = true; int i, numberOfNodes = result.length; // number of octets - should // be 4 for IPV4 and 6 fo // IPV6 for (i = 0; i < numberOfNodes; i++) // convert octets to intergers // and validate them { try { octet = Integer.parseInt(result[i]); if ((octet < 0) || (octet > 255)) { valid = false; break; } } catch (Exception e) { valid = false; ipAddress = false; break; } } if ((valid == true) && // nodes are all numbers between 0 and 255, // inclusive (ipAddress == true) && // hostname should be an IP address ((numberOfNodes != 4) && (numberOfNodes != 6))) // it is not // a valid IPV4 or IPV6 address { valid = false; } if (ipAddress == false) // aHostName is not valid IP address { char[] charBuf; int strLen; if ((host.length() <= 255) && (validLetters.indexOf(host.charAt(0)) != -1)) // aHostName // must be shorter than 256 { // characters and start with a letter if (numberOfNodes <= 127) { valid = true; for (i = 0; i < numberOfNodes; i++) // check each node { int j; strLen = result[i].length(); if (strLen > 63) // each octet must be shorter than // 64 characters { valid = false; i = numberOfNodes; } else { charBuf = new char[strLen]; result[i].getChars(0, strLen, charBuf, 0); // copy // characters in this node to charbuf for // // validation for (j = 0; j < strLen; j++) // loop to validate // characters in // current node(in // charBuf) { if (validChars.indexOf(charBuf[j]) == -1) { valid = false; // not valid so no need // for further checking i = numberOfNodes; // to exit // numberOfNodes for // loop j = strLen; // to exit strLen for loop } } } } } } else valid = false; } if (valid) { return host; } else { String validHostnameString = ""; try { validHostnameString = ImsConnectErrorMessage .getString(ImsConnectErrorMessage.VALID_PROPERTY_VALUE_HOSTNAME); } catch (Exception e1) { } String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0030E, new Object[] { "hostName", host, validHostnameString }); ImsConnectApiException e1 = new ImsConnectApiException( ImsConnectErrorMessage.HWS0030E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception caught in Connection.setHostName(String). Exception caught was: " + e1.toString()); throw e1; } } private int validatePortNumber(int port) throws ImsConnectApiException { if (port > 0 && port <= 65535) return port; else { String validPortNumberString = ""; try { validPortNumberString = ImsConnectErrorMessage .getString(ImsConnectErrorMessage.VALID_PROPERTY_VALUE_PORTNUMBER); } catch (Exception e1) { // do nothing - this exception should never occur unless the API // JAR is corrupted } String errMsg = ImsConnectErrorMessage.getString( ImsConnectErrorMessage.HWS0030E, new Object[] { "portNumber", String.valueOf(port), validPortNumberString }); ImsConnectApiException e = new ImsConnectApiException( ImsConnectErrorMessage.HWS0030E, errMsg); if (logger.isLoggable(ApiProperties.TRACE_LEVEL_EXCEPTION)) logger.severe(" Exception thrown in Connection.setPortNumber(int). Exception thrown was: " + e.toString()); throw e; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy