R
Richard Maher
Hi,
Please help if you can (with probably a very basic OO newbie question): -
I have created a class that uses the java.net.Socket class to talk to my
server and everything is great. I then converted the code to use the
javax.net.SSLSocket class and (thanks to how easy Java makes it for us!)
everything is still great. What I want to do now is parameterize/optionalize
the use of SSL or in-the-clear Sockets within my class, and I'm struggling
to find a modular, let alone elegant, solution.
At the moment I plan to add another Applet parameter called SSL_REQD and I
will pass that to my constructor, but because of Java's compile-time
resolution of methods-to-objects, I find myself having to duplicate code
that is erstwhile 99% identical or common. Is there some way (short of
Reflection) that I can leverage the fact SSLSocket class inherits most of
its methods from the Socket class so that I only need one method for each
socket function regardless of what flavour socket is in use?
For example: -
private someSocket t3Sock;
if (sssReqd)
t3Sock = (SSLSocket)sockFactory.createSocket();
else
t3Sock = new Socket();
t3Sock.setKeepAlive(true);
Am I stuck with "One's an Apple and the other's an Orange (albeit painted
red "?
If few of the Socket methods are overridden by SSLSocket (and the
value-added encryption stuff happens at a lower/other level) can I just cast
my way around some of this? Just stick in a few "if" statements and stop
moanin'?
Cheers Richard Maher
Here is the complete Tier3Socket class definition: -
import java.io.BufferedOutputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.net.SocketTimeoutException;
import java.lang.System;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class Tier3Socket
{
public static final
String T3ID="T3$";
public static final
int USERSIZ=40;
public static final
int T3IDBUFSIZ=48;
public static final
int CREDBUFSIZ=80;
public static final
int CONTIMOUT=10000;
public byte [] t3IdBuf;
public byte [] readBuf;
public byte [] writeBuf;
private String host;
private int port;
private int maxBufSiz;
private int bytesIn;
private String hostCharSet;
private SSLSocket t3Sock;
private SSLSocketFactory sockFactory;
private BufferedInputStream in;
private BufferedOutputStream out;
private byte [] outUser;
private byte [] outPwd;
private byte [] credBuf;
private String inMsg;
private String stringOut;
Tier3Socket (String host, int port, int maxBufSiz, String hostCharSet)
{
this.host = host;
this.port = port;
this.maxBufSiz = maxBufSiz;
this.hostCharSet = hostCharSet;
this.bytesIn = 0;
t3IdBuf = new byte[T3IDBUFSIZ];
readBuf = new byte[maxBufSiz];
sockFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
}
public void open() throws UnknownHostException, IOException
{
t3Sock = (SSLSocket)sockFactory.createSocket();
t3Sock.setKeepAlive(true);
t3Sock.setReuseAddress(true);
t3Sock.setTcpNoDelay(true);
t3Sock.connect(new InetSocketAddress(host,port), CONTIMOUT);
System.out.println("Connected OK");
in = new BufferedInputStream (t3Sock.getInputStream() ,maxBufSiz);
out = new BufferedOutputStream (t3Sock.getOutputStream(),maxBufSiz);
t3Sock.setUseClientMode(true);
System.out.println("Going for SSL");
try {t3Sock.startHandshake();}
catch (IOException e)
{
System.out.println("Failed SSL Handshake");
throw new IOException("Can't SSL on Socket");
}
}
public void handShake(String username, String password) throws IOException
{
credBuf = new byte[CREDBUFSIZ];
outUser = username.getBytes(hostCharSet);
System.arraycopy(outUser, 0, credBuf, 0, outUser.length);
outPwd = password.getBytes(hostCharSet);
System.arraycopy(outPwd, 0, credBuf, USERSIZ, outPwd.length);
out.write(credBuf, 0, CREDBUFSIZ);
out.flush();
if (in.read(t3IdBuf) < t3IdBuf.length)
{
System.out.println("Read < " + Integer.toString(t3IdBuf.length) + "
bytes");
throw new IOException();
}
inMsg = new String(t3IdBuf, 0, 3, hostCharSet);
if (!inMsg.equals(T3ID))
{
throw new IOException();
}
}
public void sendUrgentData (int oob) throws IOException
{
t3Sock.sendUrgentData(oob);
}
public void setTimeout(int msecs) throws UnknownHostException, IOException
{
t3Sock.setSoTimeout(msecs);
}
public void close () throws IOException
{
if (t3Sock != null && !t3Sock.isClosed())
{
try {t3Sock.close();}
catch (Exception e)
{e.printStackTrace();}
}
}
public void buffMessage (String message) throws IOException
{
byte [] msg = message.getBytes(hostCharSet);
out.write(msg);
}
public void sendMessage (String message) throws IOException
{
byte [] msg = message.getBytes(hostCharSet);
out.write(msg);
flush();
}
public void flush () throws IOException
{
out.flush();
}
public int readMessage () throws IOException
{
return readMessage(readBuf.length);
}
public int readMessage (int bytes) throws IOException
{
try
{
bytesIn = in.read(readBuf, 0, bytes);
}
catch (SocketTimeoutException e)
{
return 0;
}
return bytesIn;
}
public String getString () throws ArrayIndexOutOfBoundsException
{
return getString(0, bytesIn);
}
public String getString (int offset, int length) throws
ArrayIndexOutOfBoundsException
{
if ((offset + length) > bytesIn)
{
throw new ArrayIndexOutOfBoundsException();
}
try
{
stringOut = new String(readBuf, offset, length, hostCharSet);
}
catch (Exception e)
{
return null;
}
return stringOut;
}
}
Please help if you can (with probably a very basic OO newbie question): -
I have created a class that uses the java.net.Socket class to talk to my
server and everything is great. I then converted the code to use the
javax.net.SSLSocket class and (thanks to how easy Java makes it for us!)
everything is still great. What I want to do now is parameterize/optionalize
the use of SSL or in-the-clear Sockets within my class, and I'm struggling
to find a modular, let alone elegant, solution.
At the moment I plan to add another Applet parameter called SSL_REQD and I
will pass that to my constructor, but because of Java's compile-time
resolution of methods-to-objects, I find myself having to duplicate code
that is erstwhile 99% identical or common. Is there some way (short of
Reflection) that I can leverage the fact SSLSocket class inherits most of
its methods from the Socket class so that I only need one method for each
socket function regardless of what flavour socket is in use?
For example: -
private someSocket t3Sock;
if (sssReqd)
t3Sock = (SSLSocket)sockFactory.createSocket();
else
t3Sock = new Socket();
t3Sock.setKeepAlive(true);
Am I stuck with "One's an Apple and the other's an Orange (albeit painted
red "?
If few of the Socket methods are overridden by SSLSocket (and the
value-added encryption stuff happens at a lower/other level) can I just cast
my way around some of this? Just stick in a few "if" statements and stop
moanin'?
Cheers Richard Maher
Here is the complete Tier3Socket class definition: -
import java.io.BufferedOutputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.net.SocketTimeoutException;
import java.lang.System;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class Tier3Socket
{
public static final
String T3ID="T3$";
public static final
int USERSIZ=40;
public static final
int T3IDBUFSIZ=48;
public static final
int CREDBUFSIZ=80;
public static final
int CONTIMOUT=10000;
public byte [] t3IdBuf;
public byte [] readBuf;
public byte [] writeBuf;
private String host;
private int port;
private int maxBufSiz;
private int bytesIn;
private String hostCharSet;
private SSLSocket t3Sock;
private SSLSocketFactory sockFactory;
private BufferedInputStream in;
private BufferedOutputStream out;
private byte [] outUser;
private byte [] outPwd;
private byte [] credBuf;
private String inMsg;
private String stringOut;
Tier3Socket (String host, int port, int maxBufSiz, String hostCharSet)
{
this.host = host;
this.port = port;
this.maxBufSiz = maxBufSiz;
this.hostCharSet = hostCharSet;
this.bytesIn = 0;
t3IdBuf = new byte[T3IDBUFSIZ];
readBuf = new byte[maxBufSiz];
sockFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
}
public void open() throws UnknownHostException, IOException
{
t3Sock = (SSLSocket)sockFactory.createSocket();
t3Sock.setKeepAlive(true);
t3Sock.setReuseAddress(true);
t3Sock.setTcpNoDelay(true);
t3Sock.connect(new InetSocketAddress(host,port), CONTIMOUT);
System.out.println("Connected OK");
in = new BufferedInputStream (t3Sock.getInputStream() ,maxBufSiz);
out = new BufferedOutputStream (t3Sock.getOutputStream(),maxBufSiz);
t3Sock.setUseClientMode(true);
System.out.println("Going for SSL");
try {t3Sock.startHandshake();}
catch (IOException e)
{
System.out.println("Failed SSL Handshake");
throw new IOException("Can't SSL on Socket");
}
}
public void handShake(String username, String password) throws IOException
{
credBuf = new byte[CREDBUFSIZ];
outUser = username.getBytes(hostCharSet);
System.arraycopy(outUser, 0, credBuf, 0, outUser.length);
outPwd = password.getBytes(hostCharSet);
System.arraycopy(outPwd, 0, credBuf, USERSIZ, outPwd.length);
out.write(credBuf, 0, CREDBUFSIZ);
out.flush();
if (in.read(t3IdBuf) < t3IdBuf.length)
{
System.out.println("Read < " + Integer.toString(t3IdBuf.length) + "
bytes");
throw new IOException();
}
inMsg = new String(t3IdBuf, 0, 3, hostCharSet);
if (!inMsg.equals(T3ID))
{
throw new IOException();
}
}
public void sendUrgentData (int oob) throws IOException
{
t3Sock.sendUrgentData(oob);
}
public void setTimeout(int msecs) throws UnknownHostException, IOException
{
t3Sock.setSoTimeout(msecs);
}
public void close () throws IOException
{
if (t3Sock != null && !t3Sock.isClosed())
{
try {t3Sock.close();}
catch (Exception e)
{e.printStackTrace();}
}
}
public void buffMessage (String message) throws IOException
{
byte [] msg = message.getBytes(hostCharSet);
out.write(msg);
}
public void sendMessage (String message) throws IOException
{
byte [] msg = message.getBytes(hostCharSet);
out.write(msg);
flush();
}
public void flush () throws IOException
{
out.flush();
}
public int readMessage () throws IOException
{
return readMessage(readBuf.length);
}
public int readMessage (int bytes) throws IOException
{
try
{
bytesIn = in.read(readBuf, 0, bytes);
}
catch (SocketTimeoutException e)
{
return 0;
}
return bytesIn;
}
public String getString () throws ArrayIndexOutOfBoundsException
{
return getString(0, bytesIn);
}
public String getString (int offset, int length) throws
ArrayIndexOutOfBoundsException
{
if ((offset + length) > bytesIn)
{
throw new ArrayIndexOutOfBoundsException();
}
try
{
stringOut = new String(readBuf, offset, length, hostCharSet);
}
catch (Exception e)
{
return null;
}
return stringOut;
}
}