![JAR search and dependency download from the Maven repository](/logo.png)
com.ibm.ims.connect.impl.ConnectionImpl Maven / Gradle / Ivy
Show all versions of IMSConnectAPI Show documentation
/*
* 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;
}
}
}