/*
* $Id$
*
* Copyright (c) 2000-2007 by Rodney Kinney
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License (LGPL) as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, copies are available
* at http://www.opensource.org.
*/
package VASSAL.chat.node;
import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Copyright (c) 2003 by Rodney Kinney. All rights reserved.
* Date: Aug 27, 2003
*/
public abstract class SocketHandler {
protected Socket sock;
protected SocketWatcher handler;
private BlockingQueue<String> writeQueue = new LinkedBlockingQueue<String>();
private boolean isOpen = true;
private Thread readThread;
private Thread writeThread;
private static final String SIGN_OFF = "!BYE"; //$NON-NLS-1$
public SocketHandler(Socket sock, SocketWatcher handler) throws IOException {
this.sock = sock;
this.handler = handler;
}
public void start() {
if (readThread == null) {
readThread = startReadThread();
}
if (writeThread == null) {
writeThread = startWriteThread();
}
}
private Thread startReadThread() {
Runnable runnable = new Runnable() {
public void run() {
String line;
try {
while ((line = readNext()) != null) {
if (SIGN_OFF.equals(line)) {
break;
}
else if (line.length() > 0) {
try {
handler.handleMessage(line);
}
// FIXME: review error message
catch (Exception e) {
// Handler threw an exception. Keep reading.
System.err.println("Caught " + e.getClass().getName() + " handling " + line); //$NON-NLS-1$ //$NON-NLS-2$
e.printStackTrace();
}
}
}
}
// FIXME: review error message
catch (IOException ignore) {
String msg = ignore.getClass().getName();
msg = msg.substring(msg.lastIndexOf('.') + 1);
// System.err.println("Caught " + msg + "(" + ignore.getMessage() + ") reading socket.");
}
closeSocket();
}
};
Thread t = new Thread(runnable, "read " + sock.getInetAddress());
t.start();
return t;
}
private Thread startWriteThread() {
Runnable runnable = new Runnable() {
public void run() {
String line;
try {
while (true) {
if ((line = getLine()) != null) {
writeNext(line);
if (SIGN_OFF.equals(line)) break;
}
}
}
// FIXME: review error message
catch (IOException ignore) {
String msg = ignore.getClass().getName();
msg = msg.substring(msg.lastIndexOf('.') + 1);
// System.err.println("Caught " + msg + "(" + ignore.getMessage() + ") writing to socket.");
}
closeSocket();
}
};
Thread t = new Thread(runnable, "write " + sock.getInetAddress());
t.start();
return t;
}
protected abstract void closeStreams() throws IOException;
protected abstract String readNext() throws IOException;
protected abstract void writeNext(String line) throws IOException;
public void writeLine(String pMessage) {
try {
writeQueue.put(pMessage);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
public void close() {
writeLine(SIGN_OFF);
}
private synchronized void closeSocket() {
if (isOpen) {
try {
closeStreams();
}
// FIXME: review error message
catch (IOException ignore) {
}
try {
sock.close();
}
// FIXME: review error message
catch (IOException ignore) {
}
close();
isOpen = false;
handler.socketClosed(this);
}
}
private String getLine() {
try {
return writeQueue.take();
}
catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}