+/*\r
+ * This file is part of the Vamsas Client version 0.1. \r
+ * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite, \r
+ * Andrew Waterhouse and Dominik Lindner.\r
+ * \r
+ * Earlier versions have also been incorporated into Jalview version 2.4 \r
+ * since 2008, and TOPALi version 2 since 2007.\r
+ * \r
+ * The Vamsas Client is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU Lesser General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * The Vamsas Client is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU Lesser General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU Lesser General Public License\r
+ * along with the Vamsas Client. If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
package uk.ac.vamsas.client.picking;\r
\r
import java.net.*;\r
* server for other clients; failing that, it attempts to connect to an existing\r
* server instead.\r
*/\r
-public class SocketManager implements IPickManager\r
-{\r
- private Log logger = org.apache.commons.logging.LogFactory.getLog(uk.ac.vamsas.client.picking.SocketManager.class);\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
- // the other clients - if this is server side\r
- private LinkedList clients;\r
- \r
- private PickServer server;\r
- \r
- private IMessageHandler msgHandler;\r
- \r
- private boolean isRunning = true;\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 SocketManager()\r
- {\r
- //logger.setLevel(Level.OFF);\r
- \r
- server = new PickServer(this);\r
- clients = new LinkedList();\r
- \r
- new InitializeThread().start();\r
- }\r
- \r
- /**\r
- * Registers a message handler with the manager that allows the manager to\r
- * perform a method callback on that object whenever a message is received.\r
- * @param handler the message handler to register\r
- */\r
- public void registerMessageHandler(IMessageHandler handler)\r
- {\r
- msgHandler = handler;\r
- }\r
- \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
- synchronized boolean addEndPoint(Socket socket)\r
- {\r
- PickEndPoint client = new PickEndPoint(this, socket);\r
- \r
- if (client.openConnection())\r
- {\r
- clients.add(client);\r
- //logger.info("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 message the message to send\r
- */\r
- public void sendMessage(Message message)\r
- {\r
- forwardMessage(null, message);\r
- }\r
- \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 message the message to send\r
- */\r
- private void forwardMessage(PickEndPoint origin, Message message)\r
- {\r
- for (int i = clients.size()-1; i >= 0; i--)\r
- {\r
- try\r
- {\r
- PickEndPoint client = (PickEndPoint) clients.get(i);\r
- if (client != origin)\r
- client.send(message);\r
- }\r
- catch (Exception e)\r
- {\r
- System.out.println("FORWARD: " + e);\r
- }\r
- }\r
- }\r
- \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
- * @message the message that was received\r
- */\r
- void processMessage(PickEndPoint origin, Message message)\r
- { \r
- if (server.isServer())\r
- forwardMessage(origin, message);\r
- \r
- if (msgHandler != null)\r
- msgHandler.handleMessage(message);\r
-// else\r
-// logger.info("No handler available to deal with incoming message");\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
- synchronized void removeEndPoint(PickEndPoint client)\r
- {\r
- clients.remove(client);\r
- //logger.info("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 - but only if we've not been told to stop\r
- if (clients.size() == 0 && isRunning)\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
- logger.debug("Initializing connection...");\r
- boolean connected = false;\r
- \r
- // Loop until we can get a connection (one way or the other)\r
- while (!connected && isRunning)\r
- {\r
- // Sleep for a rnd time so we don't end up with all the VAMSAS\r
- // apps trying to initialize servers at the same time\r
- try { Thread.sleep((int)(10*Math.random())); }\r
- catch (InterruptedException e) {}\r
- \r
- // Attempt to open the server port...\r
- if (server.isServer() || server.createServer())\r
- connected = true;\r
-\r
- // If it fails, then attempt to make a client connection...\r
- else if (addEndPoint(null))\r
- connected = true;\r
- }\r
+public class SocketManager implements IPickManager {\r
+ private Log logger = org.apache.commons.logging.LogFactory\r
+ .getLog(uk.ac.vamsas.client.picking.SocketManager.class);\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\r
+ // contain one element\r
+ // the other clients - if this is server side\r
+ private LinkedList clients;\r
+\r
+ private PickServer server;\r
+\r
+ private IMessageHandler msgHandler;\r
+\r
+ private boolean isRunning = true;\r
+\r
+ /**\r
+ * Constructs a new PickManager. This method will return immediately, while a\r
+ * looping thread runs that attempts to run the server or connect to an\r
+ * existing server.\r
+ */\r
+ public SocketManager() {\r
+ // logger.setLevel(Level.OFF);\r
+\r
+ server = new PickServer(this);\r
+ clients = new LinkedList();\r
+\r
+ new InitializeThread().start();\r
+ }\r
+\r
+ /**\r
+ * Registers a message handler with the manager that allows the manager to\r
+ * perform a method callback on that object whenever a message is received.\r
+ * \r
+ * @param handler\r
+ * the message handler to register\r
+ */\r
+ public void registerMessageHandler(IMessageHandler handler) {\r
+ msgHandler = handler;\r
+ }\r
+\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 a\r
+ * client that is attempting to connect *to* the server.\r
+ * \r
+ * @param socket\r
+ * a socket endpoint for the connection\r
+ * @return true if the connection is successfully, false otherwise\r
+ */\r
+ synchronized boolean addEndPoint(Socket socket) {\r
+ PickEndPoint client = new PickEndPoint(this, socket);\r
+\r
+ if (client.openConnection()) {\r
+ clients.add(client);\r
+ // logger.info("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
+ * \r
+ * @param message\r
+ * the message to send\r
+ */\r
+ public void sendMessage(Message message) {\r
+ forwardMessage(null, message);\r
+ }\r
+\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
+ * \r
+ * @param origin\r
+ * the client endpoint that received the message (will be null if the\r
+ * message originates from this instance\r
+ * @param message\r
+ * the message to send\r
+ */\r
+ private void forwardMessage(PickEndPoint origin, Message message) {\r
+ for (int i = clients.size() - 1; i >= 0; i--) {\r
+ try {\r
+ PickEndPoint client = (PickEndPoint) clients.get(i);\r
+ if (client != origin)\r
+ client.send(message);\r
+ } catch (Exception e) {\r
+ System.out.println("FORWARD: " + e);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Handles a received message. If the manager is running in server mode, then\r
+ * it must ensure the message is also forwarded to the other clients.\r
+ * \r
+ * @param origin\r
+ * the client endpoint that received the message\r
+ * @message the message that was received\r
+ */\r
+ void processMessage(PickEndPoint origin, Message message) {\r
+ if (server.isServer())\r
+ forwardMessage(origin, message);\r
+\r
+ if (msgHandler != null)\r
+ msgHandler.handleMessage(message);\r
+ // else\r
+ // logger.info("No handler available to deal with incoming message");\r
+ }\r
+\r
+ /**\r
+ * Removes a client connection from the list when its connection is no longer\r
+ * valid.\r
+ * \r
+ * @param client\r
+ * the client endpoint to remove\r
+ */\r
+ synchronized void removeEndPoint(PickEndPoint client) {\r
+ clients.remove(client);\r
+ // logger.info("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 - but only if we've not been told to stop\r
+ if (clients.size() == 0 && isRunning)\r
+ new InitializeThread().start();\r
+ }\r
+\r
+ /**\r
+ * Thread extension class to handle the actual initialization\r
+ */\r
+ private class InitializeThread extends Thread {\r
+ public void run() {\r
+ logger.debug("Initializing connection...");\r
+ boolean connected = false;\r
+\r
+ // Loop until we can get a connection (one way or the other)\r
+ while (!connected && isRunning) {\r
+ // Sleep for a rnd time so we don't end up with all the VAMSAS\r
+ // apps trying to initialize servers at the same time\r
+ try {\r
+ Thread.sleep((int) (10 * Math.random()));\r
+ } catch (InterruptedException e) {\r
+ }\r
+\r
+ // Attempt to open the server port...\r
+ if (server.isServer() || server.createServer())\r
+ connected = true;\r
+\r
+ // If it fails, then attempt to make a client connection...\r
+ else if (addEndPoint(null))\r
+ connected = true;\r
+ }\r
logger.debug("Completed initializing connection.");\r
- }\r
- }\r
- \r
- public void shutdown()\r
- {\r
- logger.debug("Shutting down socket manager.");\r
+ }\r
+ }\r
+\r
+ public void shutdown() {\r
+ logger.debug("Shutting down socket manager.");\r
if (server == null)\r
- throw new Error("Client Implementation Error: shutdown() called on uninitialized SocketManager.");\r
- \r
- isRunning = false;\r
- \r
- if (server.isServer())\r
- server.terminate();\r
- \r
- while (clients.size() > 0) {\r
- logger.debug("Closing endpoint.");\r
- ((PickEndPoint)clients.getFirst()).terminate();\r
- }\r
+ throw new Error(\r
+ "Client Implementation Error: shutdown() called on uninitialized SocketManager.");\r
+\r
+ isRunning = false;\r
+\r
+ if (server.isServer())\r
+ server.terminate();\r
+\r
+ while (clients.size() > 0) {\r
+ logger.debug("Closing endpoint.");\r
+ ((PickEndPoint) clients.getFirst()).terminate();\r
+ }\r
logger.debug("Shutdown of socketmanager completed.");\r
}\r
-}
\ No newline at end of file
+}\r