com.ibm.as400.access.PxClientConnectionAdapter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jt400 Show documentation
Show all versions of jt400 Show documentation
The Open Source version of the IBM Toolbox for Java
The newest version!
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: PxClientConnectionAdapter.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2000 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.NotSerializableException;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.*;
//
// Tunneling is another mechanism to get to the server. This class now
// has two ways to get to the server:
// Traditional -- a socket connection is made to the server and a
// deamon thread is started to handly data coming back on the connection.
// Tunnel -- A URL connection is made for each data flow. The connection
// is made to our tunnel servelet running in the http server.
//
/**
The PxClientConnectionAdapter class represents the connection
to a proxy server.
**/
public abstract class PxClientConnectionAdapter
{
private static final String copyright = "Copyrixght (C) 1997-2000 International Business Machines Corporation and others.";
// Private data.
private boolean closed_ = false;
private InputStream input_ = null;
private OutputStream output_ = null;
private PxClientReadDaemon readDaemon_ = null;
private PxSocketContainerAdapter socket_ = null;
private SSLOptions sslOptions_ = null;
// tunnel_ is used by the
// subclass ProxyClientConnection
// so it cannot be private
boolean tunnel_ = false; // @D1a
private long clientId_ = -1; // @D1a @D2C
private URL tunnelURL_ = null; // @D1a
private String localName = null;
protected PxClientConnectionAdapter (String proxyServer, SSLOptions secure)
{
// @D2D clientId_ = new byte[8];
sslOptions_ = secure;
open (proxyServer);
}
/**
Closes the connection to the proxy server.
// @D1a question -- should we do something in the tunneling case
// to clean up the server?
**/
public void close ()
{
if (!tunnel_) // @D1a
{
if (Trace.isTraceProxyOn ())
Trace.log (Trace.PROXY, "Closing a connection to proxy server.");
readDaemon_.stopSafely();
// I am using separate try-catch blocks to make sure
// that everything gets closed.
try {
input_.close ();
}
catch (IOException e) {
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, e.getMessage (), e);
throw new ProxyException (ProxyException.CONNECTION_DROPPED,e);
}
try {
output_.close ();
}
catch (IOException e) {
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, e.getMessage (), e);
throw new ProxyException (ProxyException.CONNECTION_DROPPED,e);
}
// $$ Question for Jim, his new class skipped the above
// two funtions -- input_.close() and output_.close().
// If a good idea then remove from here as well.
try {
socket_.close ();
}
catch (IOException e) {
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, e.getMessage (), e);
throw new ProxyException (ProxyException.CONNECTION_DROPPED,e);
}
}
closed_ = true;
}
protected void finalize ()
throws Throwable
{
if (closed_ == false)
close ();
super.finalize ();
}
public PxDSFactory getFactory()
{
return readDaemon_.getFactory();
}
public void open (String proxyServer)
{
boolean secure = (sslOptions_ != null && sslOptions_.proxyEncryptionMode_ != SecureAS400.PROXY_SERVER_TO_SERVER);
if (Trace.isTraceOn()) Trace.log(Trace.PROXY, "Opening a connection to proxy server "
+ proxyServer
+ " (secure=" + secure + ").");
// Parse the proxy server name, port number (and protocol if tunneling)
localName = proxyServer;
String protocolName = null;
int port = -1;
// determine if we are going with traditional or tunnel proxy.
// Assume any string with a :// wants to use the tunnel. This would
// be http://, https://, etc.
if (proxyServer.indexOf("://") > 0) // @D1a
{
tunnel_ = true;
// the name of the server is everything beyond the ://
localName = proxyServer.substring(proxyServer.indexOf(":") + 3);
protocolName = proxyServer.substring(0, proxyServer.indexOf(":"));
}
// now strip the port of the end of the server name (if one exists)
int colon = localName.indexOf(':');
if (colon >= 0)
{
if (colon < localName.length() - 1)
port = Integer.parseInt(localName.substring (colon + 1));
localName = localName.substring(0, colon);
}
if (! tunnel_) // @D1a
{
if (port < 0)
port = secure ? ProxyConstants.SECURE_PORT_NUMBER : ProxyConstants.PORT_NUMBER; //$B1C
openTraditional(localName, port, secure);
}
else
{
// when openTunnel comes back move creating tunnelURL_ to the try/catch.
openTunnel(protocolName, localName, port); // @D1a
}
}
// this method used to be part of open. It was split out when
// tunneling was added.
void openTraditional(String name, int port, boolean secure) // @D1a
{
// Open the socket and streams.
try {
if (secure) {
// Call view reflection to remove dependency on sslight.zip
Class classPxSecureSocketContainer = Class.forName("com.ibm.as400.access.PxSecureSocketContainer");
Class[] parameterTypes = new Class[3];
parameterTypes[0] = "".getClass();
parameterTypes[1] = Integer.TYPE;
parameterTypes[2] = Class.forName("com.ibm.as400.access.SSLOptions");
Constructor constructor = classPxSecureSocketContainer.getConstructor(parameterTypes);
Object[] initargs = new Object[3];
initargs[0] = name;
initargs[1] = Integer.valueOf(port);
initargs[2] = sslOptions_;
socket_ = (PxSocketContainerAdapter) constructor.newInstance(initargs);
} else
socket_ = new PxSocketContainer (name, port);
output_ = new BufferedOutputStream (socket_.getOutputStream());
input_ = new BufferedInputStream(new RetryInputStream(socket_.getInputStream())); // @A2C
readDaemon_ = new PxClientReadDaemon(input_);
readDaemon_.start();
if (Trace.isTraceProxyOn ())
Trace.log (Trace.PROXY, "Connection established.");
}
catch (ClassNotFoundException e) {
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, "Error when opening connection to proxy server (ClassNotFound", e);
throw new ProxyException (ProxyException.CONNECTION_NOT_ESTABLISHED,e);
}
catch (NoSuchMethodException e) {
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, "Error when opening connection to proxy server (NoSuchMethodException", e);
throw new ProxyException (ProxyException.CONNECTION_NOT_ESTABLISHED,e);
}
catch (IllegalAccessException e) {
if (Trace.isTraceErrorOn () || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, "Error when opening connection to proxy server (IllegalAccessException", e);
throw new ProxyException (ProxyException.CONNECTION_NOT_ESTABLISHED,e);
}
catch (IOException e) {
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, "Error when opening connection to proxy server (openio", e);
throw new ProxyException (ProxyException.CONNECTION_NOT_ESTABLISHED,e);
} catch (IllegalArgumentException e) {
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, "Error when opening connection to proxy server (IllegalArgumentException", e);
throw new ProxyException (ProxyException.CONNECTION_NOT_ESTABLISHED,e);
} catch (InstantiationException e) {
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, "Error when opening connection to proxy server (InstantiationException", e);
throw new ProxyException (ProxyException.CONNECTION_NOT_ESTABLISHED,e);
} catch (InvocationTargetException e) {
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, "Error when opening connection to proxy server (InvocationTargetException", e);
throw new ProxyException (ProxyException.CONNECTION_NOT_ESTABLISHED,e);
}
}
// @D1a New method
void openTunnel(String protocol, String name, int port)
{
try
{
readDaemon_ = new PxClientReadDaemon();
readDaemon_.register(new PxAcceptRepCV());
if (port < 0)
tunnelURL_ = new URL(protocol, name, "/servlet/com.ibm.as400.access.TunnelProxyServer");
else
tunnelURL_ = new URL(protocol, name, port, "/servlet/com.ibm.as400.access.TunnelProxyServer");
}
catch (IOException e)
{
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, "Error when opening connection to proxy server", e);
throw new ProxyException (ProxyException.CONNECTION_NOT_ESTABLISHED,e);
}
}
// @D1a New method
private URLConnection tunnelSend(PxReqCV request)
{
try
{
URLConnection connection_;
// @D2D if (clientId_ == null)
// @D2D request.setClientId(new byte[8]);
// @D2D else
request.setClientId(clientId_);
// connection_ = (HttpURLConnection) tunnelURL_.openConnection();
connection_ = tunnelURL_.openConnection();
connection_.setUseCaches(false);
connection_.setDoOutput(true);
connection_.setDoInput(true);
connection_.setRequestProperty("Content-type", "application/octet-stream");
connection_.setRequestProperty("Connection", "Keep-Alive");
// connection_.setRequestMethod("POST");
// connection_.setFollowRedirects(false);
// connection.setRequestProperty("Content-length", " " + bytes.length)
// connection_.connect();
OutputStream connectionOut = connection_.getOutputStream();
if (Trace.isTraceProxyOn())
request.dump (Trace.getPrintWriter ());
request.writeTo(connectionOut);
connectionOut.flush();
// connectionOut.close();
return connection_;
}
catch (Exception e)
{
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, "Error when opening connection to proxy server", e);
throw new ProxyException (ProxyException.CONNECTION_NOT_ESTABLISHED,e);
}
}
Object tunnelReceive(long correlationId, URLConnection connection_)
throws InvocationTargetException
{
try
{
InputStream connectionIn = connection_.getInputStream();
PxRepCV reply;
Object returnValue;
try
{
reply = (PxRepCV) readDaemon_.getReply(correlationId, connectionIn);
returnValue = reply.process ();
clientId_ = reply.getClientId();
return returnValue;
}
catch (IOException e) {
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, "Error when receiving reply from proxy server", e);
ProxyException px = new ProxyException (ProxyException.CONNECTION_DROPPED,e);
throw px;
}
}
catch (InvocationTargetException ite)
{
throw ite;
}
catch (Exception e)
{
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, "Error when opening connection to proxy server", e);
ProxyException px = new ProxyException (ProxyException.CONNECTION_NOT_ESTABLISHED,e);
throw px;
}
}
// Note: This method should NOT be synchronized. If a thread is waiting to // @A1A
// receive a reply, it should not block other threads from sending requests. // @A1A
// (This is the point of the read daemon thread.) // @A1A
private Object receive (long correlationId) // @A1C
throws InvocationTargetException
{
Object returnValue = null;
PxRepCV reply;
try {
reply = (PxRepCV) readDaemon_.getReply(correlationId);
returnValue = reply.process ();
if (Trace.isTraceProxyOn())
Trace.log (Trace.PROXY, this, "received "+returnValue);
}
catch (IOException e) {
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn() )
Trace.log (Trace.ERROR, "Error when receiving reply from proxy server", e);
if (e instanceof NotSerializableException) {
throw new ProxyException (ProxyException.VERSION_MISMATCH,e);
} else {
throw new ProxyException (ProxyException.CONNECTION_DROPPED,e);
}
}
return returnValue;
}
/**
Sends a request to the proxy server. No reply is expected.
@param request The request.
**/
protected synchronized void send (PxReqCV request)
{
if (! tunnel_) // @D1a
{
if (Trace.isTraceProxyOn())
request.dump (Trace.getPrintWriter ());
try {
request.writeTo (output_);
output_.flush ();
}
catch (IOException e) {
if (Trace.isTraceErrorOn() || Trace.isTraceProxyOn())
Trace.log (Trace.ERROR, e.getMessage (), e);
throw new ProxyException (ProxyException.CONNECTION_DROPPED,e);
}
}
else
{
URLConnection connection_ = tunnelSend(request); // @D1a
// $$1 do something with the connection
}
}
/**
Sends a request to the proxy server and receives and processes a reply.
@param request The request.
@return The returned object, or null if none.
**/
// Note: This method should NOT be synchronized. If a thread is waiting to // @A1A
// receive a reply, it should not block other threads from sending requests. // @A1A
// (This is the point of the read daemon thread.) // @A1A
protected Object sendAndReceive (PxReqCV request) // @A1C
throws InvocationTargetException
{
if (! tunnel_) // @D1a
{
if (Trace.isTraceProxyOn()) {
Trace.log(Trace.PROXY, this, "Sending request with id "+request.getCorrelationId());
}
send (request);
if (Trace.isTraceProxyOn()) {
Trace.log(Trace.PROXY, this, "Receiving with id "+request.getCorrelationId());
}
return receive (request.getCorrelationId());
}
else // @D1a
{
// cannot use HttpURLConnection in IE or Netscape so use URLConnection instead
URLConnection connection_ = tunnelSend(request); // @D1a
Object o = tunnelReceive(request.getCorrelationId(), connection_); // @D1a
// return tunnelReceive(request.getCorrelationId(), connection_); // @D1a
return o;
} // @D1a
}
public String getSystemName() {
return localName;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy