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.persistence;
21  
22  import java.sql.Connection;
23  import java.sql.DriverManager;
24  import java.sql.ResultSet;
25  import java.sql.SQLException;
26  import java.sql.Statement;
27  import java.sql.Timestamp;
28  import java.util.ArrayList;
29  import java.util.List;
30  
31  import triptracker.core.Coordinate;
32  import triptracker.core.Route;
33  import triptracker.core.User;
34  import triptracker.core.Utils;
35  
36  /***
37   * Implementation of the persistence layer in the form of a MySQL database.
38   */
39  public class MySqlDB extends PersistenceAdapter {
40  	public static final String server = Properties.getString("MySqlDB.server");
41  	public static final String database
42  			= Properties.getString("MySqlDB.database");
43  	
44  	/***
45  	 * Connect to the MySQL database.
46  	 * 
47  	 * @return database Connection object
48  	 */
49  	private Connection connect() {
50  		Connection link = null;
51  		
52  		try {
53  			// Logging on to the MySQL database server.
54  			Class.forName(Properties.getString("MySqlDB.driver"));
55  			String url = "jdbc:mysql://" + server + "/" + database;
56  			link = DriverManager.getConnection(url,
57  					Properties.getString("MySqlDB.username"),
58  					Properties.getString("MySqlDB.password"));
59  		} catch (ClassNotFoundException e) {
60  			e.printStackTrace();
61  		} catch (SQLException e) {
62  			e.printStackTrace();
63  		}
64  		return link;
65  	}
66  
67  	/***
68  	 * {@inheritDoc}
69  	 */
70  	@Override
71  	public int getUserId(String username){
72  		Connection link = connect();
73  		int userId = -1;
74  		try {
75  			String query = "SELECT uId FROM trip_user "
76  				+ "WHERE user = '" + username + "'";
77  			
78  			Statement stmt = link.createStatement();
79  			ResultSet rs = stmt.executeQuery(query);
80  	
81  			if (rs.next()) {
82  				userId = rs.getInt(1);
83  			}
84  			
85  			dbLog("UserId for user: " + username + " = " + userId );
86  			stmt.close();
87  			link.close();
88  			return userId;
89  		} catch (SQLException e) {
90  			dbLog("SQL exception at getUserId: " + e);
91  			e.printStackTrace();
92  			return userId;
93  		}
94  	}
95  	
96  	/***
97  	 * {@inheritDoc}
98  	 */
99  	@Override
100 	public int authUser(String user, String pass) {
101 		Connection link = connect();
102 		String dbPass = "";
103 		int userId = -1;
104 		
105 		try {
106 			String query = "SELECT pass, uId FROM trip_user "
107 					+ "WHERE user = '" + user + "'";
108 
109 			Statement stmt = link.createStatement();
110 			ResultSet rs = stmt.executeQuery(query);
111 
112 			if (rs.next()) {
113 				dbPass = rs.getString(1);
114 				if (pass.equals(dbPass)) {
115 					userId = rs.getInt(2);
116 				}
117 			}
118 			dbLog("Checked user: " + user + ", userId: " + userId);
119 			stmt.close();
120 			link.close();
121 		} catch (SQLException e) {
122 			dbLog("SQL exception " + e + "\n");
123 			e.printStackTrace();
124 		}
125 		return userId;
126 	}
127 
128 	/***
129 	 * {@inheritDoc}
130 	 */
131 	@Override
132 	public void storeCoordinate(int routeID, Coordinate coord) {
133 		Connection link = connect();
134 
135 		try {
136 			String query = "INSERT INTO trip_coordinate "
137 				+ " (rId, latitude, longitude, date) "
138 				+ "VALUES('" + routeID  + "', '"
139 				+ coord.getY() + "', '"
140 				+ coord.getX() + "','"
141 				+ coord.getDateString() + "') ";
142 
143 			Statement stmt = link.createStatement();
144 			stmt.executeUpdate(query);
145 			
146 			// TODO Provide some kind of feedback to client if save failed.
147 			
148 			dbLog("Saved: Latitude: " + coord.getY() + 
149 					" Longitude: " + coord.getX() + " Tidspunkt: "
150 					+ coord.getDateString());
151 			stmt.close();
152 			link.close();
153 		} catch (SQLException e) {
154 			dbLog("SQL exception at storeCoordinate: " + e);
155 			e.printStackTrace();
156 		}
157 	}
158 
159 	/***
160 	 * {@inheritDoc}
161 	 */
162 	@Override
163 	public void storeCoordinate(int routeID, List<Coordinate> coords) {
164 		Connection link = connect();	
165 		try {
166 			Statement stmt = link.createStatement();
167 			for(Coordinate coord : coords){			
168 					String query = "INSERT INTO trip_coordinate "
169 						+ " (rId, latitude, longitude, date) "
170 						+ "VALUES('" + routeID  + "', '"
171 						+ coord.getY() + "', '"
172 						+ coord.getX() + "','"
173 						+ coord.getDateString() + "') ";
174 
175 					stmt.executeUpdate(query);
176 					
177 					// TODO Provide some kind of feedback to client if save failed.
178 			}
179 			dbLog("Saved " + coords.size() + " buffered coordnates to route nr: " + routeID);
180 			stmt.close();
181 			link.close();
182 		} catch (SQLException e) {
183 			dbLog("SQL exception at storeCoordinate: " + e);
184 			e.printStackTrace();
185 		}
186 	}
187 	
188 	/***
189 	 * {@inheritDoc}
190 	 */
191 	@Override
192 	public List<User> getUserList() {
193 		Connection link = connect();
194 		int userId;
195 		String username;
196 		List<User> users = new ArrayList<User>();
197 		
198 		try {
199 			String query = "SELECT uId, user, pass FROM trip_user ";
200 			Statement stmt = link.createStatement();
201 			ResultSet rs = stmt.executeQuery(query);
202 			
203 			while (rs.next()) {
204 				userId = rs.getInt(1);
205 				username = rs.getString(2);
206 				users.add(new User(userId, username, null));
207 			}
208 			dbLog("Sent list of users, with userId and username. ");
209 			stmt.close();
210 			link.close();
211 		} catch (SQLException e) {
212 			dbLog("SQL exception " + e + "\n");
213 			e.printStackTrace();
214 		}
215 		return users;
216 	}
217 
218 	/***
219 	 * Returns user data for the specified user.
220 	 * 
221 	 * @param userId ID of user
222 	 * @return User with given ID
223 	 */
224 	@Override
225 	public User getUser(int userId) {
226 		Connection link = connect();
227 
228 		User user = null;
229 		
230 		try {
231 			String query = "SELECT user FROM trip_user WHERE uId = '"
232 				+ userId + "'";
233 			Statement stmt = link.createStatement();
234 			ResultSet rs = stmt.executeQuery(query);
235 			
236 			while (rs.next()){
237 				String username = rs.getString(1);
238 				user = new User(userId, username, null);
239 			}
240 			dbLog("Sent user, with userId and username. ");
241 			stmt.close();
242 			link.close();
243 		} catch (SQLException e) {
244 			dbLog("SQL exception " + e + "\n");
245 			e.printStackTrace();
246 		}
247 		return user;
248 	}
249 	
250 	/***
251 	 * {@inheritDoc}
252 	 */
253 	@Override
254 	public Route makeRoute(int userId, String description,
255 			boolean publicRoute) {
256 		Route route = null;// = new Route(-1,0,null,true,null);
257 
258 		Connection link = connect();
259 
260 		try {			
261 			String insertQuery = "INSERT INTO trip_route "
262 				+ "(uId, description, active) "
263 				+ "VALUES('" + userId  + "', '" + description + "', '1') ";
264 			
265 			Statement stmt = link.createStatement();
266 			stmt.executeUpdate(insertQuery);
267 			
268 			String lastRouteQuery = "SELECT rId FROM trip_route "
269 				+ "WHERE uId = '" + userId + "' ORDER BY rId DESC LIMIT 1";
270 
271 			ResultSet rs = stmt.executeQuery(lastRouteQuery);
272 			
273 			if (rs.next()) {
274 				route = new Route(rs.getInt(1), userId, description);
275 			}
276 			
277 			dbLog("Made route " + route.getRouteId() + " for user " + userId
278 					+ " with description " + description);
279 			
280 			stmt.close();
281 			link.close();
282 		} catch (SQLException e) {
283 			dbLog("SQL exception at makeroute: " + e + "\n");
284 			e.printStackTrace();
285 		}
286 		return route;
287 	}
288 	
289 	/***
290 	 * {@inheritDoc}
291 	 */
292 	@Override
293 	public List<Route> getRoutes(String username) {
294 		List<Route> routes = new ArrayList<Route>();
295 		Connection link = connect();
296 		int userId = getUserId(username);
297 		
298 		try {
299 			String query = "SELECT R.rId, R.uId, R.active, R.description, "
300 				+ "R.public "
301 				+ "FROM trip_route R LEFT OUTER JOIN trip_user U "
302 				+ "ON R.uId = U.uId WHERE U.uId = '" + userId + "' "
303 				+ "AND (U.uId = '" + getUserId() + "' OR R.public)"
304 				+ "ORDER BY R.description";
305 
306 			Statement stmt = link.createStatement();
307 			ResultSet rs = stmt.executeQuery(query);
308 
309 			while (rs.next()) {
310 				int routeId = rs.getInt(1);
311 				int uId = rs.getInt(2);
312 				boolean active = rs.getBoolean(3);
313 				String description = rs.getString(4);
314 				boolean visible = rs.getBoolean(5);
315 				String rQuery = "SELECT date " +
316 					"FROM trip_coordinate " +
317 					"WHERE  '" + routeId + "' = rId " +
318 					"ORDER BY rId DESC " +
319 					"LIMIT 1";
320 
321 				Statement rStmt = link.createStatement();
322 				ResultSet routeSet = rStmt.executeQuery(rQuery);
323 				Timestamp updated = null;
324 				
325 				if (routeSet.next()) {
326 					updated = routeSet.getTimestamp(1);
327 				}
328 				
329 				routes.add(new Route(routeId, uId, description, active, visible,
330 						updated));
331 			}
332 			dbLog("Got routes for " + username);
333 			stmt.close();
334 			link.close();
335 		} catch (SQLException e) {
336 			dbLog("SQL exception at getRoutes: " + e);
337 			e.printStackTrace();
338 		}
339 		return routes;
340 	}
341 
342 	/***
343 	 * {@inheritDoc}
344 	 */
345 	@Override
346 	public List<Coordinate> getCoordinates(int routeID) {
347 		List<Coordinate> coords = new ArrayList<Coordinate>();
348 		Connection link = connect();
349 
350 		try {
351 			// XXX tried adding order by
352 			String query = "SELECT latitude, longitude, date "
353 				+ "FROM trip_coordinate "
354 				+ "WHERE rId = '" + routeID + "' ORDER BY date";
355 			
356 			Statement stmt = link.createStatement();
357 			ResultSet rs = stmt.executeQuery(query);
358 		
359 			while (rs.next()) {
360 				coords.add(new Coordinate(rs.getDouble(1), rs.getDouble(2),
361 						Utils.parseDate(rs.getString(3))));
362 			}
363 			
364 			stmt.close();
365 			link.close();
366 			dbLog("Sent coordinates for route: " + routeID);
367 		} catch (SQLException e) {
368 			dbLog("SQL exception at getCoordinates " + e);
369 			e.printStackTrace();
370 		}
371 		return coords;
372 	}
373 
374 	/***
375 	 * {@inheritDoc}
376 	 */
377 	@Override
378 	public void setVisible(int routeID, boolean visible) {
379 		Connection link = connect();
380 		
381 		try {
382 			String query = "UPDATE trip_route "
383 				+ "SET public = " + (visible ? 1 : 0) + " "
384 				+ "WHERE rId = '" + routeID + "'";
385 		
386 			Statement stmt = link.createStatement();
387 			stmt.executeUpdate(query);
388 			
389 			stmt.close();
390 			link.close();
391 			dbLog("Changed visibility on route " + routeID);
392 		} catch (SQLException e) {
393 			dbLog("SQL exception at setVisible: " + e + "\n");
394 			e.printStackTrace();
395 		}
396 	}
397 
398 	/***
399 	 * {@inheritDoc}
400 	 */
401 	@Override
402 	public void lockRoute(int routeID, boolean lock) {
403 		Connection link = connect();
404 		
405 		try {
406 			String query = "UPDATE trip_route "
407 				+ "SET active = " + (lock ? 0 : 1) + " "
408 				+ "WHERE rId = '" + routeID + "'";
409 		
410 			Statement stmt = link.createStatement();
411 			stmt.executeUpdate(query);
412 			
413 			stmt.close();
414 			link.close();
415 			dbLog("Changed lock state on route " + routeID);
416 		} catch (SQLException e) {
417 			dbLog("SQL exception at lockRoute: " + e + "\n");
418 			e.printStackTrace();
419 		}
420 	}
421 
422 	private void dbLog(String message){
423 	//	System.out.println( message);
424 		log(message);
425 	}
426 
427 	/***
428 	 * Returns spesific route with routeId
429 	 * @param routeId
430 	 * @return Route with given Id
431 	 */
432 	@Override
433 	public Route getRoute(int routeId) {
434 		Route route = null;
435 		Timestamp updated = null;
436 		Connection link = connect();
437 		
438 		try {
439 			String query = "SELECT uId, active, description, public "
440 				+ "FROM trip_route "
441 				+ "WHERE rId = '" + routeId
442 				+ "' AND (uId = '" + getUserId() + "' OR public)";
443 			
444 			Statement stmt = link.createStatement();
445 			ResultSet rs = stmt.executeQuery(query);
446 
447 			while (rs.next()) {
448 				int uId = rs.getInt(1);
449 				Boolean active = rs.getBoolean(2);
450 				String description = rs.getString(3);
451 				Boolean visible = rs.getBoolean(4);
452 				// Get date for last added coordinate.
453 				String rQuery = "SELECT date "
454 					+ "FROM trip_coordinate "
455 					+ "WHERE rId = '" + routeId + "' "
456 					+ "ORDER BY rId DESC "
457 					+ "LIMIT 1"; 
458 				
459 				Statement rStmt = link.createStatement();
460 				ResultSet routeSet = rStmt.executeQuery(rQuery);
461 				
462 				if (routeSet.next()) {
463 					updated = routeSet.getTimestamp(1);
464 				}
465 				
466 				route = new Route(routeId, uId, description, active, visible,
467 						updated);
468 				
469 			}
470 			dbLog("Got route: " + routeId + " updated: " + updated);
471 			
472 			stmt.close();
473 			link.close();
474 		} catch (SQLException e) {
475 			dbLog("SQL exception at getRoutes: " + e);
476 			e.printStackTrace();
477 		}
478 		return route;
479 	}
480 }