1 /**
2 * Copyright 2005-2008 the original author or authors.
3 *
4 * Licensed under the Gnu General Pubic License, Version 2.0 (the
5 * "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.opensource.org/licenses/gpl-license.php
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the Gnu General Public License for more details.
14 */
15 package org.figure8.join.businessobjects.security.persistence;
16
17 import org.figure8.join.core.EntityObject;
18 import org.figure8.join.core.InfrastructureException;
19 import org.figure8.join.businessobjects.security.User;
20 import org.figure8.join.util.LogUtil;
21
22 import org.apache.commons.logging.Log;
23 import org.springframework.jdbc.core.RowMapper;
24 import org.springframework.jdbc.core.JdbcTemplate;
25
26 import javax.sql.DataSource;
27
28 import java.util.List;
29 import java.sql.ResultSet;
30 import java.sql.SQLException;
31 /**
32 * This is an implementation of {@link UserDao} using row Jdbc.
33 * @author <a href="mailto:jerome.evrard@gmail.com">Jerome Evrard</a>
34 * @author <a href="mailto:laurent.broudoux@free.fr">Laurent Broudoux</a>
35 * @version $Revision: 1.2 $
36 */
37 public class JdbcUserDao implements UserDao{
38
39
40
41 /** Get a commons logger */
42 private static final Log log = LogUtil.getLog(JdbcUserDao.class);
43
44
45
46
47 /** Cache the select clause with provided columns */
48 private String selectClause = null;
49
50 /** Spring Jdbc template helper */
51 private JdbcTemplate jt;
52 /** Jdbc datasource allowing access to userTable */
53 private DataSource dataSource;
54
55 /** Column representing unique identifier */
56 private String idColumn = "n_id";
57 /** Column representing user login */
58 private String loginColumn = "s_login";
59 /** Column representing user password */
60 private String passwordColumn = "s_password";
61 /** Column representing user lastname */
62 private String lastnameColumn = "s_lastname";
63 /** Column representing user firstname */
64 private String firstnameColumn = "s_firstname";
65 /** Column representing user mail address */
66 private String mailColumn = "s_mail";
67 /** Column representing user phone number */
68 private String phoneColumn = "s_phone";
69 /** Column representing user team description */
70 private String teamColumn = "s_team";
71
72 /** Table containing user definitions */
73 private String userTable = "join_users";
74
75
76
77
78 /** Creates a new instance of JdbcUserDao */
79 public JdbcUserDao(){
80 }
81
82
83
84
85 /** @return Column representing unique identifier */
86 public String getIdColumn(){
87 return idColumn;
88 }
89 /** @param idColumn Column representing unique identifier */
90 public void setIdColumn(String idColumn){
91 this.idColumn = idColumn;
92 }
93 /** @return Column representing user login */
94 public String getLoginColumn(){
95 return loginColumn;
96 }
97 /** @param loginColumn Column representing user login */
98 public void setLoginColumn(String loginColumn){
99 this.loginColumn = loginColumn;
100 }
101 /** @return Column representing user password */
102 public String getPasswordColumn(){
103 return passwordColumn;
104 }
105 /** @param passwordColumn Column representing user password */
106 public void setPasswordColumn(String passwordColumn){
107 this.passwordColumn = passwordColumn;
108 }
109 /** @return Column representing user lastname */
110 public String getLastnameColumn(){
111 return lastnameColumn;
112 }
113 /** @param lastnameColumn Column representing user lastname */
114 public void setLastnameColumn(String lastnameColumn){
115 this.lastnameColumn = lastnameColumn;
116 }
117 /** @return Column representing user firstname */
118 public String getFirstnameColumn(){
119 return firstnameColumn;
120 }
121 /** @param firstnameColumn Column representing user firstname */
122 public void setFirstnameColumn(String firstnameColumn){
123 this.firstnameColumn = firstnameColumn;
124 }
125 /** @return Column representing user mail address */
126 public String getMailColumn(){
127 return mailColumn;
128 }
129 /** @param mailColumn Column representing user mail address */
130 public void setMailColumn(String mailColumn){
131 this.mailColumn = mailColumn;
132 }
133 /** @return Column representing user phone number */
134 public String getPhoneColumn(){
135 return phoneColumn;
136 }
137 /** @param phoneColumn Column representing user phone number */
138 public void setPhoneColumn(String phoneColumn){
139 this.phoneColumn = phoneColumn;
140 }
141 /** @return Column representing user team description */
142 public String getTeamColumn(){
143 return teamColumn;
144 }
145 /** @param teamColumn Column representing user team description */
146 public void setTeamColumn(String teamColumn){
147 this.teamColumn = teamColumn;
148 }
149
150 /** @return Table containing user definitions */
151 public String getUserTable(){
152 return userTable;
153 }
154 /** @param userTable Table containing user definitions */
155 public void setUserTable(String userTable){
156 this.userTable = userTable;
157 }
158
159 /** @param dataSource The Datasource allowing access to userTable */
160 public void setDataSource(DataSource dataSource){
161 this.dataSource = dataSource;
162 }
163
164
165
166
167 /**
168 * @param login User login (should be a unique identifier)
169 * @return The user object corresponding to <b>login</b>
170 */
171 public User getUser(String login){
172 User user = findUser(login);
173 if (user == null)
174 log.warn("User with login '" + login + "' is not defined or defined multiple times !");
175 return user;
176 }
177
178 /**
179 * Retrieve all users having lastname 'like' the specified one
180 * @param lastname The string that users lastname should contain
181 * @return A List of {@code org.figure8.join.businessobjects.security.User}
182 */
183 public List getUsersWithLastnameLike(String lastname){
184 List users = findUsers(lastnameColumn, lastname, lastnameColumn);
185 if (log.isDebugEnabled())
186 log.debug("Users having lastname like '" + lastname + "' are: " + users.size());
187 return users;
188 }
189
190
191
192
193 /**
194 * Save the given entity into underlying datastore.
195 * @param entityobject EntityObject to save
196 */
197 public void save(EntityObject entityobject){
198
199 if (!(entityobject instanceof User))
200 throw new IllegalArgumentException("JdbcUserDao only support User not " + entityobject.getClass());
201 User user = (User)entityobject;
202
203 jt = new JdbcTemplate(dataSource);
204 if (user.isTransient()){
205
206 long maxId = jt.queryForLong("select max(" + idColumn + " from " + userTable);
207
208 StringBuffer query = new StringBuffer("insert into ").append(userTable).append(" (");
209 query.append(idColumn).append(", ").append(loginColumn).append(", ").append(passwordColumn).append(", ");
210 query.append(lastnameColumn).append(", ").append(firstnameColumn);
211
212 if (mailColumn != null || !"null".equals(mailColumn))
213 query.append(", ").append(mailColumn);
214 if (phoneColumn != null || !"null".equals(phoneColumn))
215 query.append(", ").append(phoneColumn);
216 if (teamColumn != null || !"null".equals(teamColumn))
217 query.append(", ").append(teamColumn);
218
219 query.append(") values (").append(maxId + 1).append(", ");
220 query.append("'").append(user.getLogin()).append("', '").append(user.getPassword()).append("', ");
221 query.append("'").append(user.getLastname()).append("', '").append(user.getFirstname()).append("'");
222 if (mailColumn != null || !"null".equals(mailColumn))
223 query.append(", '").append(user.getMail()).append("'");
224 if (phoneColumn != null || !"null".equals(phoneColumn))
225 query.append(", '").append(user.getPhone()).append("'");
226 if (teamColumn != null || !"null".equals(teamColumn))
227 query.append(", ").append(user.getTeam()).append("'");
228 query.append(")");
229
230 if (log.isDebugEnabled())
231 log.debug("Inserting a new User with: " + query.toString());
232 jt.execute(query.toString());
233 }
234 else{
235
236 StringBuffer query = new StringBuffer("update ").append(userTable);
237 query.append(" set ").append(loginColumn).append("='").append(user.getLogin()).append("', ");
238 query.append(passwordColumn).append("='").append(user.getPassword()).append("', ");
239 query.append(lastnameColumn).append("='").append(user.getLastname()).append("', ");
240 query.append(firstnameColumn).append("='").append(user.getFirstname()).append("'");
241
242 if (mailColumn != null || !"null".equals(mailColumn))
243 query.append(", ").append(mailColumn).append("='").append(user.getMail()).append("'");
244 if (phoneColumn != null || !"null".equals(phoneColumn))
245 query.append(", ").append(phoneColumn).append("='").append(user.getPhone()).append("'");
246 if (teamColumn != null || !"null".equals(teamColumn))
247 query.append(", ").append(teamColumn).append("='").append(user.getTeam()).append("'");
248
249 query.append(" where ").append(idColumn).append("=").append(user.getId());
250
251 if (log.isDebugEnabled())
252 log.debug("Updating existing User with: " + query.toString());
253 int rows = jt.update(query.toString());
254 }
255 }
256
257 /**
258 * Remove the given entity object from underlying datastore.
259 * @param entityobject EntityObject to remove
260 */
261 public void remove(EntityObject entityobject){
262 throw new InfrastructureException("JdbcUserDao does not implement remove() method");
263 }
264
265 /**
266 * Re-read the content of the given entity from underlying datastore.
267 * @param entityobject EntityObject to refresh content
268 */
269 public void refresh(EntityObject entityobject){
270
271 if (!(entityobject instanceof User))
272 throw new IllegalArgumentException("JdbcUserDao only support User not " + entityobject.getClass());
273 User user = (User)entityobject;
274
275 user = findUser(user.getId());
276 }
277
278 /**
279 * Force initialization of the given entity from underlying datastore
280 * (this may involves initialization of lazily loaded relations fields)
281 * @param entityobject EntityObject to initialize
282 */
283 public void initialize(EntityObject entityobject){
284
285 refresh(entityobject);
286 }
287
288 /**
289 * Force initialization of the given entity association from underlying datastore
290 * @param entityobject EntityObject whose association shoud be initialized
291 * @param proxy A proxy object representing entoty association (this may be a collection)
292 */
293 public void initializeAssociation(EntityObject entityobject, Object proxy){
294
295 refresh(entityobject);
296 }
297
298 /**
299 * Check if an object (EntityObject or association proxy) is initialized from datastore
300 * @param object The object to check initialization for
301 * @return true if object has been loaded from datastore, false otherwise
302 */
303 public boolean isInitialized(Object object){
304 return (object instanceof User);
305 }
306
307 /**
308 * Persist the object state throughout the cluster.
309 * @param obj The object to replicate
310 */
311 public void replicate(Object obj){
312
313 if (!(obj instanceof User))
314 throw new IllegalArgumentException("JdbcUserDao only support User not " + obj.getClass());
315
316 save((User)obj);
317 }
318
319 /**
320 * Find all entity objects associated with this Dao.
321 * @return A List of EntityObjects
322 */
323 public List findAll(){
324 return findUsers(null, null, null);
325 }
326
327 /**
328 * Find all entity objects asscoiated with this Dao.
329 * The result list is sorted by <b>sortField</b> criteria.
330 * @param sortField Field for sorting criteria
331 * @return A List of EntityObjects
332 */
333 public List findAllSorted(String sortField){
334 if ("login".equals(sortField))
335 return findUsers(null, null, loginColumn);
336 if ("lastname".equals(sortField))
337 return findUsers(null, null, lastnameColumn);
338 if ("firstname".equals(sortField))
339 return findUsers(null, null, firstnameColumn);
340
341 return findAll();
342 }
343
344 /**
345 * Get the persistent class associated to this Dao.
346 * @return The class of the persistent object
347 */
348 public Class getPersistentClass(){
349 return org.figure8.join.businessobjects.security.User.class;
350 }
351
352
353
354
355 /**
356 * Find a unique User using its identifier
357 * @param id The identifier of User to retrieve
358 * @return The corresponding User or null.
359 */
360 protected User findUser(long id){
361 StringBuffer query = new StringBuffer(getSelectClause());
362
363 query.append(" where ").append(idColumn).append("=").append(id);
364
365 jt = new JdbcTemplate(dataSource);
366 List users = jt.query(query.toString(), getUserRowMapper());
367
368 if (users.size() > 1){
369 log.error("Expected only one User but found many when looking for id: " + id);
370 throw new InfrastructureException("Expected only one User but found many when looking for id: " + id);
371 }
372 if (!users.isEmpty())
373 return (User)users.get(0);
374 return null;
375 }
376
377 /**
378 * Find a unique User using its login
379 * @param login The login of User to retrieve
380 * @return The corresponding User object or null.
381 */
382 protected User findUser(String login){
383 StringBuffer query = new StringBuffer(getSelectClause());
384
385 query.append(" where ").append(loginColumn).append("='").append(login).append("'");
386
387 jt = new JdbcTemplate(dataSource);
388 List users = jt.query(query.toString(), getUserRowMapper());
389
390 if (users.size() > 1){
391 log.error("Expected only one User but found many when looking for login: " + login);
392 throw new InfrastructureException("Expected only one User but found many when looking for login: " + login);
393 }
394 if (!users.isEmpty())
395 return (User)users.get(0);
396 return null;
397 }
398
399 /**
400 * Find many users using a criterion column and its value.
401 * @param criterionColumn The column that appears in where clause
402 * @param value The value of select criterion
403 * @param sortColumn The column to use for sorting results
404 * @return A list of User objects
405 */
406 protected List findUsers(String criterionColumn, String value, String sortColumn){
407 StringBuffer query = new StringBuffer(getSelectClause());
408
409 if (criterionColumn != null)
410 query.append(" where ").append(criterionColumn).append(" like '%").append(value).append("%'");
411
412 if (sortColumn != null)
413 query.append(" order by ").append(sortColumn).append(" asc");
414
415 jt = new JdbcTemplate(dataSource);
416 return jt.query(query.toString(), getUserRowMapper());
417 }
418
419 /**
420 * Retrieve the where clause depending on specified columns and table name
421 * @return The where clause of SQL query from 'select' to 'from table '
422 */
423 protected String getSelectClause(){
424 if (selectClause == null){
425 StringBuffer buffer = new StringBuffer("select ").append(idColumn).append(", ");
426 buffer.append(loginColumn).append(", ").append(passwordColumn).append(", ");
427 buffer.append(lastnameColumn).append(", ").append(firstnameColumn);
428
429 if (mailColumn != null || !"null".equals(mailColumn))
430 buffer.append(", ").append(mailColumn);
431 if (phoneColumn != null || !"null".equals(phoneColumn))
432 buffer.append(", ").append(phoneColumn);
433 if (teamColumn != null || !"null".equals(teamColumn))
434 buffer.append(", ").append(teamColumn);
435
436 buffer.append(" from ").append(userTable);
437 selectClause = buffer.toString();
438 }
439 return selectClause;
440 }
441
442 /**
443 * Retrieve a Spring row mappper for User object
444 * @return A RowMapper implementation for User object
445 */
446 protected RowMapper getUserRowMapper(){
447 return new RowMapper(){
448 /**
449 * Map each row of data in the ResultSet. This method should not call
450 * next() on the ResultSet, but extract the current values.
451 * @param rs the ResultSet to map
452 * @param rowNum The number of the current row
453 * @throws SQLException if a SQLException is encountered getting
454 * column values (that is, there's no need to catch SQLException)
455 */
456 public Object mapRow(ResultSet rs, int rowNum) throws SQLException{
457 User user = new User();
458 user.setId(rs.getLong(idColumn));
459 user.setLogin(rs.getString(loginColumn));
460 user.setPassword(rs.getString(passwordColumn));
461 user.setLastname(rs.getString(lastnameColumn));
462 user.setFirstname(rs.getString(firstnameColumn));
463
464 if (mailColumn != null || !"null".equals(mailColumn))
465 user.setMail(rs.getString(mailColumn));
466 if (phoneColumn != null || !"null".equals(phoneColumn))
467 user.setPhone(rs.getString(phoneColumn));
468 if (teamColumn != null || !"null".equals(teamColumn))
469 user.setTeam(rs.getString(teamColumn));
470 return user;
471 }
472 };
473 }
474 }