\r
import java.net.*;\r
import java.util.*;\r
+import java.util.logging.*;\r
\r
+/**\r
+ * Manager class that maintains a list of connected clients in addition to\r
+ * attempting to run a server to listen for client connections. If the server\r
+ * initialization fails, then an attempt to connect (as a client) to another JVM\r
+ * that is already a server happens instead.\r
+ */\r
public class PickManager\r
{\r
+ private static Logger logger = Logger.getLogger("org.vamsas.client.picking");\r
+ \r
// Maintains a list of client communication objects - each object represents\r
// a way of talking to either:\r
// the server - if this is client side (and in which case, the list will only contain one element\r
\r
private PickServer server;\r
\r
+ /**\r
+ * Constructs a new PickManager. This method will return immediately, while\r
+ * a looping thread runs that attempts to run the server or connect to an\r
+ * existing server.\r
+ */\r
public PickManager()\r
{\r
server = new PickServer(this);\r
new InitializeThread().start();\r
}\r
\r
- // Called whenver we try to make a new endpoint<->endpoint connection\r
- boolean addClientConnection(Socket socket)\r
+ /**\r
+ * Attempts to establish a connection between two client endpoints. This\r
+ * method is called in two ways: 1) by the server when it receives a remote\r
+ * request (in which case the socket will already be established) and 2) by\r
+ * a client that is attempting to connect *to* the server.\r
+ * @param socket a socket endpoint for the connection\r
+ * @return true if the connection is successfully, false otherwise\r
+ */\r
+ boolean addEndPoint(Socket socket)\r
{\r
PickEndPoint client = new PickEndPoint(this, socket);\r
\r
if (client.openConnection())\r
{\r
clients.add(client);\r
- System.out.println("List now contains " + clients.size() + " client(s)");\r
+ logger.fine("List now contains " + clients.size() + " client(s)");\r
return true;\r
}\r
\r
return false;\r
}\r
\r
+ /**\r
+ * Sends a message to other clients.\r
+ * @param str the message to send\r
+ */\r
public void sendMessage(String str)\r
{\r
forwardMessage(null, str);\r
}\r
\r
- // Forwards (or sends) a message\r
- // When the server receives a message, it will be resent to all clients,\r
- // but *not* to the client that sent it out in the first place!\r
+ /**\r
+ * Forwards (or sends) a message. When the server (client A) receives a\r
+ * message from client B, it must also forward it to clients C and D (etc),\r
+ * but mustn't forward it *back* to client B.\r
+ * @param origin the client endpoint that received the message (will be null\r
+ * if the message originates from this instance\r
+ * @param str the message to send\r
+ */\r
private void forwardMessage(PickEndPoint origin, String str)\r
{\r
ListIterator itor = clients.listIterator();\r
}\r
}\r
\r
- // Called by the endpoint code when a message is received\r
- // The manager has to:\r
- // a) hand message to VAMSAS app\r
- // b) forward it to other clients if we're the server\r
+ /**\r
+ * Handles a received message. If the manager is running in server mode,\r
+ * then it must ensure the message is also forwarded to the other clients.\r
+ * @param origin the client endpoint that received the message\r
+ * @str the message that was received\r
+ */\r
void handleMessage(PickEndPoint origin, String str)\r
{\r
if (server.isServer())\r
// TODO: pass message to VAMSAS API\r
}\r
\r
+ /**\r
+ * Removes a client connection from the list when its connection is no\r
+ * longer valid.\r
+ * @param client the client endpoint to remove\r
+ */\r
void removeEndPoint(PickEndPoint client)\r
{\r
clients.remove(client);\r
- System.out.println("List now contains " + clients.size() + " client(s)");\r
+ logger.fine("List now contains " + clients.size() + " client(s)");\r
\r
// If there's no endpoints left, then we've lost all connections and\r
// need to reinitialize\r
new InitializeThread().start();\r
}\r
\r
+ /**\r
+ * Thread extension class to handle the actual initialization\r
+ */\r
private class InitializeThread extends Thread\r
{\r
public void run()\r
{\r
- System.out.println("Initializing connection...");\r
+ logger.fine("Initializing connection...");\r
boolean connected = false;\r
\r
// Loop until we can get a connection (one way or the other)\r
connected = true;\r
\r
// If it fails, then attempt to make a client connection...\r
- else if (addClientConnection(null))\r
+ else if (addEndPoint(null))\r
connected = true;\r
}\r
}\r
\r
import java.io.*;\r
import java.net.*;\r
+import java.util.logging.*;\r
\r
+/**\r
+ * Server class that listens for incoming connections on a predefined port.\r
+ */\r
class PickServer extends Thread\r
{\r
+ private static Logger logger = Logger.getLogger("org.vamsas.client.picking");\r
+ \r
+ // The port number we'll listen on\r
static final int PORT = 53782;\r
\r
private ServerSocket serverSocket;\r
+ // Set to true once the server is established\r
private boolean isServer = false;\r
\r
private PickManager manager;\r
\r
+ /**\r
+ * Constructs a new instance of the server (but doesn't start it).\r
+ * @param manager a reference to the pick manager that owns this server\r
+ */\r
PickServer(PickManager manager)\r
{\r
this.manager = manager;\r
}\r
\r
+ /**\r
+ * Returns true if this server instance is running.\r
+ * Return true if this server instance is running\r
+ */\r
boolean isServer()\r
{ return isServer; }\r
\r
+ /**\r
+ * Attempts to create the server by opening a server socket on the port.\r
+ * @return true if the server was created; false otherwise\r
+ */\r
boolean createServer()\r
{\r
try\r
}\r
catch (IOException e)\r
{\r
- // If we fail, just assume another app already has the port\r
- System.out.println("SERVER: " + e);\r
+ logger.info("SERVER: " + e);\r
return false;\r
}\r
}\r
\r
+ /**\r
+ * Thread listening method - loops indefinitely listening for connections.\r
+ * When one is received, the socket object is passed to the manager so it\r
+ * can make a full client connection for further comms.\r
+ */\r
public void run()\r
{\r
- System.out.println("SERVER: listening on " + PORT + " - SERVER");\r
+ logger.fine("SERVER: listening on " + PORT + " - SERVER");\r
\r
// Loop forever, accepting connectons from other clients\r
+ // TODO: add in the ability to terminate the server if a VAMSAS session\r
+ // is ended\r
while (true)\r
{\r
try\r
{\r
Socket socket = serverSocket.accept(); \r
- System.out.println("SERVER: connection detected");\r
+ logger.fine("SERVER: connection detected");\r
\r
- manager.addClientConnection(socket);\r
+ manager.addEndPoint(socket);\r
}\r
catch (IOException e) {}\r
}\r