Re: Java/OO techniques for modularity and re-use
Hi Arne,
Thanks for the reply.
In the rest of this I'm not arguing against what you've said, I'm just
honestly trying to digest it
Since SSLSocket inherits from Socket then you can make your
t3sock of type Socket (you can assign from a subtype to a
super type).
But because SSLSocket "extends" Socket, surely I have to instantiate a
SSLSocket object somewhere don't I?
Really no need for this: -
sockFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
t3Sock = (SSLSocket)sockFactory.createSocket();
What about all the Value-Added SSL bits that the SSLSocket class must
bolt-on to a Socket?
If you need to use a SSL specific funtion you can use:
((SSLSocket)t3Sock).someSSLSOcketSpecificMethod()
You're casting t3Sock (a Socket object) as a SSLSocket object there right? I
haven't missed some abstract-class or Interface wizardry? So I've got a
vanilla Socket and cast it as a SSLSocket to call, say startHandshake(), and
it's not gonna complain about a bodgy brick-veneer job, absent any
certificate or crypto-algorithm info?
I'd find it easier to picture it the other way around where we have a
SSLSocket and our casting it as a Socket effectively masks out all the SSL
bits, but who cares? I'll just code it like you've said and see how I get
on.
But that is not "nice".
It's certainly more appealing than the attached code (look for "sslReqd")
I guess the least I can do is put the common stuff such as this. . .
inSock.setKeepAlive(true);
inSock.setReuseAddress(true);
inSock.setTcpNoDelay(true);
inSock.connect(new InetSocketAddress(host,port), CONTIMOUT);
in = new BufferedInputStream (inSock.getInputStream() ,maxBufSiz);
out = new BufferedOutputStream (inSock.getOutputStream(),maxBufSiz);
.. . . in a private method with a Socket parameter "inSock" and cast the
SSLSocket to that (or vica versa).
Cheers Richard Maher
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=3000;
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 Socket t3Sock;
private SSLSocket t3SSLSock;
private SSLSocketFactory sockFactory;
private BufferedInputStream in;
private BufferedOutputStream out;
private byte [] outUser;
private byte [] outPwd;
private byte [] credBuf;
private String inMsg;
private String stringOut;
private boolean sslReqd;
Tier3Socket (String host, int port, int maxBufSiz, String hostCharSet,
boolean sslReqd)
{
this.host = host;
this.port = port;
this.maxBufSiz = maxBufSiz;
this.hostCharSet = hostCharSet;
this.bytesIn = 0;
this.sslReqd = sslReqd;
t3IdBuf = new byte[T3IDBUFSIZ];
readBuf = new byte[maxBufSiz];
if (sslReqd)
sockFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
}
public void open() throws UnknownHostException, IOException
{
if (sslReqd)
{
t3SSLSock = (SSLSocket)sockFactory.createSocket();
t3SSLSock.setKeepAlive(true);
t3SSLSock.setReuseAddress(true);
t3SSLSock.setTcpNoDelay(true);
t3SSLSock.connect(new InetSocketAddress(host,port), CONTIMOUT);
in = new BufferedInputStream (t3SSLSock.getInputStream() ,maxBufSiz);
out = new BufferedOutputStream (t3SSLSock.getOutputStream(),maxBufSiz);
t3SSLSock.setUseClientMode(true);
try {t3SSLSock.startHandshake();}
catch (IOException e)
{
System.out.println("Failed SSL Handshake");
throw new IOException("Can't SSL on Socket");
}
}
else
{
t3Sock = new Socket();
t3Sock.setKeepAlive(true);
t3Sock.setReuseAddress(true);
t3Sock.setTcpNoDelay(true);
t3Sock.connect(new InetSocketAddress(host,port), CONTIMOUT);
in = new BufferedInputStream (t3Sock.getInputStream() ,maxBufSiz);
out = new BufferedOutputStream (t3Sock.getOutputStream(),maxBufSiz);
}
}
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
{
if (sslReqd)
t3SSLSock.sendUrgentData(oob);
else
t3Sock.sendUrgentData(oob);
}
public void setTimeout(int msecs) throws UnknownHostException, IOException
{
if (sslReqd)
t3SSLSock.setSoTimeout(msecs);
else
t3Sock.setSoTimeout(msecs);
}
public void close () throws IOException
{
if (t3Sock != null && !t3Sock.isClosed())
{
try {t3Sock.close();}
catch (Exception e)
{e.printStackTrace();}
}
if (t3SSLSock != null && !t3SSLSock.isClosed())
{
try {t3SSLSock.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;
}
}
"Arne Vajh?j" <arne@vajhoej.dk> wrote in message
news:4686eb25$0$90265$14726298@news.sunsite.dk...
Richard Maher wrote:
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'?
Since SSLSocket inherits from Socket then you can make your
t3sock of type Socket (you can assign from a subtype to a
super type).
If you need to use a SSL specific funtion you can use:
((SSLSocket)t3Sock).someSSLSOcketSpecificMethod()
But that is not "nice".
I would find it tempting to create a wrapper class hirachy:
CommonSocketWrapper, SocketWrapper and SSLSocketWrapper where
SocketWrapper has some do nothing methods for the SSL specific
stuff.
If that is not what you are looking for, then pleas explain.
Arne