applied LGPLv3 and source code formatting.
[vamsas.git] / src / uk / ac / vamsas / client / picking / PickEndPoint.java
1 /*\r
2  * This file is part of the Vamsas Client version 0.1. \r
3  * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite, \r
4  *  Andrew Waterhouse and Dominik Lindner.\r
5  * \r
6  * Earlier versions have also been incorporated into Jalview version 2.4 \r
7  * since 2008, and TOPALi version 2 since 2007.\r
8  * \r
9  * The Vamsas Client is free software: you can redistribute it and/or modify\r
10  * it under the terms of the GNU Lesser General Public License as published by\r
11  * the Free Software Foundation, either version 3 of the License, or\r
12  * (at your option) any later version.\r
13  *  \r
14  * The Vamsas Client is distributed in the hope that it will be useful,\r
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
17  * GNU Lesser General Public License for more details.\r
18  * \r
19  * You should have received a copy of the GNU Lesser General Public License\r
20  * along with the Vamsas Client.  If not, see <http://www.gnu.org/licenses/>.\r
21  */\r
22 package uk.ac.vamsas.client.picking;\r
23 \r
24 import java.io.*;\r
25 import java.net.*;\r
26 import java.util.logging.*;\r
27 \r
28 import org.apache.commons.logging.Log;\r
29 \r
30 class PickEndPoint extends Thread {\r
31   private Log logger = org.apache.commons.logging.LogFactory\r
32       .getLog(uk.ac.vamsas.client.picking.PickEndPoint.class);\r
33 \r
34   private Socket socket;\r
35 \r
36   private int rPort;\r
37 \r
38   private BufferedWriter os;\r
39 \r
40   private BufferedReader in;\r
41 \r
42   /**\r
43    * reference to server or null if no comms session active\r
44    */\r
45   private SocketManager manager;\r
46 \r
47   PickEndPoint(SocketManager manager, Socket s) {\r
48     this.manager = manager;\r
49     socket = s;\r
50   }\r
51 \r
52   boolean openConnection() {\r
53     try {\r
54       // Create the socket if it doesn't already exist\r
55       if (socket == null)\r
56         socket = new Socket(InetAddress.getLocalHost(), PickServer.PORT);\r
57 \r
58       rPort = socket.getPort();\r
59       socket.setKeepAlive(true);\r
60 \r
61       // Open the streams for reading/writing\r
62       os = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));\r
63       in = new BufferedReader(new InputStreamReader(socket.getInputStream()));\r
64 \r
65       // Start the thread to listen for incoming messages\r
66       logger.debug("CLIENT: connection successful to port " + socket.getPort()\r
67           + " via port " + socket.getLocalPort());\r
68       start();\r
69 \r
70       return true;\r
71     } catch (Exception e) {\r
72       logger.info("CLIENT: connection failed: " + e);\r
73       return false;\r
74     }\r
75   }\r
76 \r
77   void send(Message message) {\r
78     try {\r
79       String str = message.getRawMessage();\r
80 \r
81       // System.err.println("CLIENT: send " + str + " to " + rPort);\r
82       os.write(str);\r
83 \r
84       // We use a newline to terminate the message\r
85       os.newLine();\r
86       os.flush();\r
87     } catch (Exception e) {\r
88       // logger.info("CLIENT: failed to send");\r
89 \r
90       // TODO: terminate the connection on a failed send or retry? (Has this\r
91       // been done? JBP)\r
92       terminate();\r
93     }\r
94   }\r
95 \r
96   // void receive() (threaded)\r
97   public void run() {\r
98     try {\r
99       while (manager != null) {\r
100         String str = in.readLine();\r
101         // logger.info("CLIENT: recv " + str + " from " + rPort);\r
102 \r
103         // TODO: Spawn this off into the GUI Event-Dispatch thread...\r
104 \r
105         // Convert the string back into something API friendly\r
106         Message message = strToMessage(str);\r
107 \r
108         // Ignore corrupted or unknown message types\r
109         if (message != null)\r
110           manager.processMessage(this, message);\r
111       }\r
112     } catch (Exception e) {\r
113       // Means the other end of the connection has (probably died) so we need\r
114       // terminate this endpoint (if this is server side)\r
115       // logger.info("CLIENT: read failed: " + e);\r
116 \r
117       terminate(); // this may not be necessary - probably caused infinite loop\r
118                    // on terminate() without null checks\r
119     }\r
120   }\r
121 \r
122   void terminate() {\r
123     SocketManager mgr = manager;\r
124     manager = null; // stops receive thread\r
125     if (socket != null) {\r
126       try {\r
127         socket.close();\r
128       } catch (IOException e) {\r
129       }\r
130       socket = null;\r
131     }\r
132     // logger.info("CLIENT: closing connection to port " + socket.getPort());\r
133     // terminate() can be called by the socket manager to shutdown the\r
134     // connection,\r
135     // or the receive thread after an exception has been received\r
136     // (which includes the above case when the socket is closed.\r
137     // so we only want to removeEndPoint once - for the initial call to\r
138     // terminate()\r
139     if (mgr != null)\r
140       mgr.removeEndPoint(this);\r
141   }\r
142 \r
143   private Message strToMessage(String str) {\r
144     try {\r
145       // System.err.println("Received Message\n*\n"+str+"*");\r
146       if (str == null || str.length() == 1)\r
147         return null;\r
148       if (str.startsWith("CUSTOM"))\r
149         return new CustomMessage(str.substring(6));\r
150       if (str.startsWith("MOUSEOVER"))\r
151         return new MouseOverMessage(str);\r
152       if (str.startsWith("SELECTION"))\r
153         return new SelectionMessage(str);\r
154 \r
155     } catch (Exception e) {\r
156       // logger.info("Unable to reconstruct message: " + e);\r
157     }\r
158 \r
159     return null;\r
160   }\r
161 }\r