1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package triptracker.server;
21
22 import static triptracker.core.Protocol.*;
23
24 import java.io.IOException;
25 import java.net.Socket;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.concurrent.CopyOnWriteArrayList;
29
30 import triptracker.core.Coordinate;
31 import triptracker.core.User;
32 import triptracker.core.Utils;
33
34 /***
35 * Handler for coordinate submitter/sender clients.
36 */
37 public class GPSHandler extends ClientHandler {
38 /*** Listener list for coordinate update events. */
39 private List<CoordListener> coordListeners =
40 new CopyOnWriteArrayList<CoordListener>();
41
42 /***
43 * Sets up socket streams for communication with a GPS client and creates
44 * the message reader thread for message processing.
45 *
46 * @param server main server instance
47 * @param socket client communication socket
48 * @param user client user data
49 * @throws IOException on connection failure
50 */
51 public GPSHandler(Server server, Socket socket, User user)
52 throws IOException {
53 super(server, socket, user);
54 }
55
56 /***
57 * The method making sure everything is being shutdown before the handler
58 * deletes itself.
59 */
60
61 @Override
62 protected void stopHandler() {
63 if (coordListeners != null){
64 for (CoordListener listener : coordListeners) {
65 listener.stopLogging(this);
66 }
67 }
68 server.removeGPSHandler(this);
69 coordListeners = null;
70 }
71
72 /***
73 * {@inheritDoc}
74 */
75 @Override
76 protected boolean messageHandler(String message) {
77 String[] msg = message.split(DELIMITER);
78
79 msg = message.split(DELIMITER);
80 try {
81
82 switch (Integer.parseInt(msg[0])) {
83 case QUIT:
84 log("Exiting thread and closing connection.");
85 stopLogging();
86
87 return false;
88 case COORD_ADD:
89
90 double latitude = Double.parseDouble(msg[1]);
91 double longitude = Double.parseDouble(msg[2]);
92 String time = msg[3];
93 Coordinate coord = new Coordinate(latitude, longitude,
94 Utils.parseDate(time));
95
96
97
98 storeCoordinate(coord);
99 break;
100 case COORD_BUFFER_ADD:
101 coordBufferAdd(Integer.parseInt(msg[1]));
102 break;
103 case MAKE_ROUTE:
104 String description = msg[1];
105 route = db.makeRoute(user.getUserId(), description, false);
106 sendMessage(out,MAKE_ROUTE,route.getRouteId());
107 log("Has set route to: " + route.toString());
108 break;
109 case SET_ROUTE:
110
111 route = db.getRoute(Integer.parseInt(msg[1]));
112 log("Is tracking route: " + route.getRouteId() + ", desc: "
113 + route.toString());
114 server.checkMapHandler(this);
115 break;
116 case VIEW_ROUTES:
117 viewRoutes(user.getUsername());
118 break;
119 case ROUTE_LOCK:
120
121
122 db.lockRoute(route.getRouteId(), true);
123 log("Just locked route " + route.getRouteId());
124 break;
125
126
127
128 default:
129
130 log("Invalid message: " + message);
131 server.invalidMessage(this, message);
132 break;
133 }
134 } catch (NumberFormatException num) {
135 server.invalidMessage(this, message);
136 log("NumberFormatException: " + num);
137 num.printStackTrace();
138 }
139 return true;
140 }
141
142 /***
143 * Publish a coordinate to all coordinate listeners and then lets the
144 * persistency layer store it permanently. The coordinate listeners is
145 * usually map clients listening in on a route in realtime.
146 *
147 * @param coord coordinate to publish and permanently store
148 */
149 public void storeCoordinate(Coordinate coord) {
150
151 coordinateUpdate(coord);
152
153 db.storeCoordinate(route.getRouteId(), coord);
154 }
155
156 /***
157 * For storing coordinates that have been buffered on
158 * the client for some time. Will recieve them packed in
159 * gzip, to save transmitt rate.
160 */
161 public void coordBufferAdd(int size) {
162 System.out.println("Starting buffer add, buffer size: " + size);
163
164 try {
165 String buffIn = in.readLine();
166
167 String[] msg = buffIn.split(DELIMITER);
168
169 List<Coordinate> coords = new ArrayList<Coordinate>();
170 for (int i = 0; i < msg.length; i += 3) {
171 double latitude = Double.parseDouble(msg[i]);
172 double longitude = Double.parseDouble(msg[i + 1]);
173 String time = msg[i + 2];
174
175
176 coords.add(new Coordinate(latitude, longitude,
177 Utils.parseDate(time)));
178 }
179 db.storeCoordinate(route.getRouteId(), coords);
180
181 log("Received buffered coords, size: " + msg.length );
182 coordinateBufferUpdate(msg);
183
184 } catch (IOException e) {
185 log("Exception recieving stored coordinates: ");
186 e.printStackTrace();
187 }
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239 }
240
241 /***
242 * Notifies all listeners and send them the coordinate.
243 *
244 * @param coord
245 */
246 public void coordinateUpdate(Coordinate coord){
247 for (CoordListener listener : coordListeners){
248 listener.coordinateUpdate(coord);
249 }
250 }
251
252 /***
253 * Notifies all listeners and send them the buffered coordinates.
254 *
255 * @param coord
256 */
257 public void coordinateBufferUpdate(String[] coords){
258 for (CoordListener listener : coordListeners){
259 listener.coordinateBufferUpdate(coords);
260 }
261 }
262
263 public void stopLogging(){
264 for (CoordListener listener : coordListeners) {
265 listener.stopLogging(this);
266 }
267 }
268
269 /***
270 * MapHandlers can add themselves to the listener list and recieve updates
271 * when coordinates are added.
272 *
273 * @param listener listener to add for notification events
274 */
275 public void addCoordListener(CoordListener listener) {
276 coordListeners.add(listener);
277 }
278
279 /***
280 * MapHandlers can add themselves to the listener list and recieve updates
281 * when coordinates are added.
282 *
283 * @param listener listener to add for notification events
284 */
285 public void removeCoordListener(CoordListener listener) {
286 coordListeners.remove(listener);
287 }
288
289 }