View Javadoc

1   /*
2    * Trip Tracker, a real-time position tracking system for the Internet.
3    * Copyright (C) 2006  Team Trip Tracker
4    *
5    * This program is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License as published by the
7    * Free Software Foundation; either version 2 of the License, or (at your
8    * option) any later version.
9    *
10   * This program is distributed in the hope that it will be useful, but
11   * WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13   * General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License along
16   * with this program; if not, write to the Free Software Foundation, Inc.,
17   * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
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  	// TODO (harald) Not finished yet!!!
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  			// Handle message based on first field (msg[0]).
82  			switch (Integer.parseInt(msg[0])) {
83  			case QUIT:
84  				log("Exiting thread and closing connection.");
85  				stopLogging();
86  				//stopHandler();
87  				return false;
88  			case COORD_ADD:
89  //				 For storing one specific coordinate.
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  //				log("latitude: " + latitude + ", longitude "
97  //						+ longitude + ", tidspunkt: " + time);
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 				 // Set active route.
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 				// This will lock the route for further logging.
121 				// TODO Check for unlocking too.
122 				db.lockRoute(route.getRouteId(), true); 
123 				log("Just locked route " + route.getRouteId());
124 				break;
125 //			case ROUTE_VISIBILITY:
126 //				db.setVisible(route.getRouteId(), Utils.strToBool(msg[1]));
127 //				break;
128 			default:
129 				// Invalid/unsupported message.
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 		// Lagre koordinat i database
151 		coordinateUpdate(coord);
152 		//System.out.println("Route: " + route + ", coord: " + coord);
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 //			System.out.println("buffIn: " + buffIn);
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 //				log("latitude: " + latitude + ", longitude " + longitude
175 //						+ ", tidspunkt: " + time);
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 //		StringBuilder buffInput = new StringBuilder();
190 		
191 /*		try {
192 //			ZipInputStream gzipBuffer = new ZipInputStream(input);//, size);
193 			InflaterInputStream gzipBuffer = new InflaterInputStream(input);
194 			
195 			byte[] buffer = new byte[2];//size];
196 			System.out.println("Started buffer");
197 			
198 			gzipBuffer.read(buffer);//,0,size);
199 			System.out.println("Array: " + buffer[0] + " " + buffer[1]);
200 //			String coordBuffer = new String(buffer);
201 //			System.out.println("Stringbuffer = " + coordBuffer);
202 			
203 		} catch (IOException e) {
204 			System.out.println("Exception adding buffred coordinates: ");
205 			e.printStackTrace();
206 		}
207 */
208 //		int bytesRead = 0;
209 //		System.out.println("Entering while loop");
210 //		while (bytesRead < 0){
211 //			bytesRead = gzipBuffer.read(buffer);
212 //			bytesRead = gzipBuffer.read(buffer,0,size);
213 //			System.out.println("Read: " + bytesRead);
214 //		}
215 
216 //		byte[] buffer = new byte[256];
217 //		while (true) {
218 //			int bytesRead = in.read(buffer);
219 //			if (bytesRead == -1) break;
220 //			out.write(buffer, 0, bytesRead);
221 //		}
222 
223 
224 //		while (gzipBuffer.ready()) {
225 //			System.out.println("Start of loop.");
226 //			String coordBuff = (gzipBuffer.readLine());
227 //			System.out.println("Line read!");
228 //			String[] coordTable = new String[3];
229 //			System.out.println("Coordtable generated");
230 //			coordTable = coordBuff.split("" + DELIMITER);
231 //										 	
232 //			System.out.println("Buffered: " + coordTable[0] +","
233 //					+ coordTable[1] +","+ coordTable[2]);
234 //			db.storeCoordinate(route,
235 //			Double.parseDouble(coordTable[0]),
236 //			Double.parseDouble(coordTable[1]), coordTable[2]);
237 //		}
238 //		gzipBuffer = null;
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 }