KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > turbine > services > security > db > DBUserManager


1 package org.apache.turbine.services.security.db;
2
3 /*
4  * Copyright 2001-2004 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License")
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import java.util.ArrayList JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23
24 import org.apache.commons.configuration.Configuration;
25
26 import org.apache.commons.lang.StringUtils;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 import org.apache.torque.om.BaseObject;
32 import org.apache.torque.om.ObjectKey;
33 import org.apache.torque.om.Persistent;
34 import org.apache.torque.util.Criteria;
35
36 import org.apache.turbine.om.security.User;
37 import org.apache.turbine.om.security.peer.TurbineUserPeer;
38 import org.apache.turbine.services.security.TurbineSecurity;
39 import org.apache.turbine.services.security.UserManager;
40 import org.apache.turbine.util.db.map.TurbineMapBuilder;
41 import org.apache.turbine.util.security.DataBackendException;
42 import org.apache.turbine.util.security.EntityExistsException;
43 import org.apache.turbine.util.security.PasswordMismatchException;
44 import org.apache.turbine.util.security.UnknownEntityException;
45
46 /**
47  * An UserManager performs {@link org.apache.turbine.om.security.User}
48  * objects related tasks on behalf of the
49  * {@link org.apache.turbine.services.security.BaseSecurityService}.
50  *
51  * This implementation uses a relational database for storing user data. It
52  * expects that the User interface implementation will be castable to
53  * {@link org.apache.torque.om.BaseObject}.
54  *
55  * @author <a HREF="mailto:jon@collab.net">Jon S. Stevens</a>
56  * @author <a HREF="mailto:john.mcnally@clearink.com">John D. McNally</a>
57  * @author <a HREF="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
58  * @author <a HREF="mailto:cberry@gluecode.com">Craig D. Berry</a>
59  * @author <a HREF="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
60  * @author <a HREF="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
61  * @author <a HREF="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
62  * @version $Id: DBUserManager.java,v 1.16.2.3 2004/10/08 12:09:43 henning Exp $
63  */

64 public class DBUserManager
65         implements UserManager
66 {
67     /** Logging */
68     private static Log log = LogFactory.getLog(DBUserManager.class);
69
70     /**
71      * Initializes the UserManager
72      *
73      * @param conf A Configuration object to init this Manager
74      */

75     public void init(Configuration conf)
76     {
77         // GNDN
78
}
79
80     /**
81      * Check whether a specified user's account exists.
82      *
83      * The login name is used for looking up the account.
84      *
85      * @param user The user to be checked.
86      * @return true if the specified account exists
87      * @throws DataBackendException if there was an error accessing
88      * the data backend.
89      */

90     public boolean accountExists(User user)
91             throws DataBackendException
92     {
93         return accountExists(user.getName());
94     }
95
96     /**
97      * Check whether a specified user's account exists.
98      *
99      * The login name is used for looking up the account.
100      *
101      * @param userName The name of the user to be checked.
102      * @return true if the specified account exists
103      * @throws DataBackendException if there was an error accessing
104      * the data backend.
105      */

106     public boolean accountExists(String JavaDoc userName)
107             throws DataBackendException
108     {
109         Criteria criteria = new Criteria();
110         criteria.add(TurbineUserPeer.USERNAME, userName);
111         List JavaDoc users;
112         try
113         {
114             users = TurbineUserPeer.doSelect(criteria);
115         }
116         catch (Exception JavaDoc e)
117         {
118             throw new DataBackendException(
119                     "Failed to check account's presence", e);
120         }
121         if (users.size() > 1)
122         {
123             throw new DataBackendException(
124                     "Multiple Users with same username '" + userName + "'");
125         }
126         return (users.size() == 1);
127     }
128
129     /**
130      * Retrieve a user from persistent storage using username as the
131      * key.
132      *
133      * @param userName the name of the user.
134      * @return an User object.
135      * @exception UnknownEntityException if the user's account does not
136      * exist in the database.
137      * @exception DataBackendException if there is a problem accessing the
138      * storage.
139      */

140     public User retrieve(String JavaDoc userName)
141             throws UnknownEntityException, DataBackendException
142     {
143         Criteria criteria = new Criteria();
144         criteria.add(TurbineUserPeer.USERNAME, userName);
145
146         List JavaDoc users = retrieveList(criteria);
147
148         if (users.size() > 1)
149         {
150             throw new DataBackendException(
151                     "Multiple Users with same username '" + userName + "'");
152         }
153         if (users.size() == 1)
154         {
155             return (User) users.get(0);
156         }
157         throw new UnknownEntityException("Unknown user '" + userName + "'");
158     }
159
160     /**
161      * Retrieve a user from persistent storage using the primary key
162      *
163      * @param key The primary key object
164      * @return an User object.
165      * @throws UnknownEntityException if the user's record does not
166      * exist in the database.
167      * @throws DataBackendException if there is a problem accessing the
168      * storage.
169      */

170     public User retrieveById(Object JavaDoc key)
171             throws UnknownEntityException, DataBackendException
172     {
173         Criteria criteria = new Criteria();
174         criteria.add(TurbineUserPeer.USER_ID, key);
175
176         List JavaDoc users = retrieveList(criteria);
177
178         if (users.size() > 1)
179         {
180             throw new DataBackendException(
181                 "Multiple Users with same unique Key '" + String.valueOf(key) + "'");
182         }
183         if (users.size() == 1)
184         {
185             return (User) users.get(0);
186         }
187         throw new UnknownEntityException("Unknown user with key '" + String.valueOf(key) + "'");
188     }
189
190     /**
191      * Retrieve a list of users that meet the specified criteria.
192      *
193      * As the keys for the criteria, you should use the constants that
194      * are defined in {@link User} interface, plus the names
195      * of the custom attributes you added to your user representation
196      * in the data storage. Use verbatim names of the attributes -
197      * without table name prefix in case of Torque implementation.
198      *
199      * @param criteria The criteria of selection.
200      * @return a List of users meeting the criteria.
201      * @throws DataBackendException if there is a problem accessing the
202      * storage.
203      */

204     public List JavaDoc retrieveList(Criteria criteria)
205         throws DataBackendException
206     {
207         for (Iterator JavaDoc keys = criteria.keySet().iterator(); keys.hasNext(); )
208         {
209             String JavaDoc key = (String JavaDoc) keys.next();
210
211             // set the table name for all attached criterion
212
Criteria.Criterion[] criterion = criteria
213                     .getCriterion(key).getAttachedCriterion();
214
215             for (int i = 0; i < criterion.length; i++)
216             {
217                 if (StringUtils.isEmpty(criterion[i].getTable()))
218                 {
219                     criterion[i].setTable(TurbineUserPeer.getTableName());
220                 }
221             }
222         }
223         List JavaDoc users = null;
224         try
225         {
226             users = TurbineUserPeer.doSelect(criteria);
227         }
228         catch (Exception JavaDoc e)
229         {
230             throw new DataBackendException("Failed to retrieve users", e);
231         }
232         return users;
233     }
234
235     /**
236      * Retrieve a set of users that meet the specified criteria.
237      *
238      * As the keys for the criteria, you should use the constants that
239      * are defined in {@link User} interface, plus the names
240      * of the custom attributes you added to your user representation
241      * in the data storage. Use verbatim names of the attributes -
242      * without table name prefix in case of DB implementation.
243      *
244      * @param criteria The criteria of selection.
245      * @return a List of users meeting the criteria.
246      * @throws DataBackendException if there is a problem accessing the
247      * storage.
248      * @deprecated Use <a HREF="#retrieveList">retrieveList</a> instead.
249      */

250     public User[] retrieve(Criteria criteria)
251             throws DataBackendException
252     {
253         return (User []) retrieveList(criteria).toArray(new User[0]);
254     }
255
256     /**
257      * Retrieve a user from persistent storage using username as the
258      * key, and authenticate the user. The implementation may chose
259      * to authenticate to the server as the user whose data is being
260      * retrieved.
261      *
262      * @param userName the name of the user.
263      * @param password the user supplied password.
264      * @return an User object.
265      * @exception PasswordMismatchException if the supplied password was
266      * incorrect.
267      * @exception UnknownEntityException if the user's account does not
268      * exist in the database.
269      * @exception DataBackendException if there is a problem accessing the
270      * storage.
271      */

272     public User retrieve(String JavaDoc userName, String JavaDoc password)
273             throws PasswordMismatchException, UnknownEntityException,
274             DataBackendException
275     {
276         User user = retrieve(userName);
277         authenticate(user, password);
278         return user;
279     }
280
281     /**
282      * Save an User object to persistent storage. User's account is
283      * required to exist in the storage.
284      *
285      * @param user an User object to store.
286      * @exception UnknownEntityException if the user's account does not
287      * exist in the database.
288      * @exception DataBackendException if there is a problem accessing the
289      * storage.
290      */

291     public void store(User user)
292             throws UnknownEntityException, DataBackendException
293     {
294         if (!accountExists(user))
295         {
296             throw new UnknownEntityException("The account '" +
297                     user.getName() + "' does not exist");
298         }
299
300         Criteria criteria = TurbineUserPeer.buildCriteria(user);
301         try
302         {
303             TurbineUserPeer.doUpdate(criteria);
304         }
305         catch (Exception JavaDoc e)
306         {
307             throw new DataBackendException("Failed to save user object", e);
308         }
309     }
310
311     /**
312      * Saves User data when the session is unbound. The user account is required
313      * to exist in the storage.
314      *
315      * LastLogin, AccessCounter, persistent pull tools, and any data stored
316      * in the permData hashtable that is not mapped to a column will be saved.
317      *
318      * @exception UnknownEntityException if the user's account does not
319      * exist in the database.
320      * @exception DataBackendException if there is a problem accessing the
321      * storage.
322      */

323     public void saveOnSessionUnbind(User user)
324             throws UnknownEntityException, DataBackendException
325     {
326         if (!user.hasLoggedIn())
327         {
328             return;
329         }
330
331         if (!accountExists(user))
332         {
333             throw new UnknownEntityException("The account '" +
334                     user.getName() + "' does not exist");
335         }
336         Criteria crit = new Criteria();
337         if (!((Persistent) user).isNew())
338         {
339             crit.add(TurbineUserPeer.USER_ID, ((Persistent) user).getPrimaryKey());
340         }
341
342         Hashtable JavaDoc permStorage = (Hashtable JavaDoc) user.getPermStorage().clone();
343         crit.add(TurbineUserPeer.LAST_LOGIN, permStorage.remove(TurbineUserPeer.LAST_LOGIN));
344
345         // The OBJECT_DATA column only stores data not mapped to a column. We must
346
// remove all of the extra data and serialize the rest. Access Counter
347
// is not mapped to a column so it will be serialized into OBJECT_DATA.
348
for (int i = 1; i < TurbineUserPeer.columnNames.length; i++)
349         {
350             if (permStorage.containsKey(TurbineUserPeer.columnNames[i]))
351             {
352                 permStorage.remove(TurbineUserPeer.columnNames[i]);
353             }
354         }
355         crit.add(TurbineUserPeer.OBJECT_DATA, permStorage);
356
357         try
358         {
359             TurbineUserPeer.doUpdate(crit);
360         }
361         catch (Exception JavaDoc e)
362         {
363             throw new DataBackendException("Failed to save user object", e);
364         }
365
366     }
367
368     /**
369      * Authenticate an User with the specified password. If authentication
370      * is successful the method returns nothing. If there are any problems,
371      * exception was thrown.
372      *
373      * @param user an User object to authenticate.
374      * @param password the user supplied password.
375      * @exception PasswordMismatchException if the supplied password was
376      * incorrect.
377      * @exception UnknownEntityException if the user's account does not
378      * exist in the database.
379      * @exception DataBackendException if there is a problem accessing the
380      * storage.
381      */

382     public void authenticate(User user, String JavaDoc password)
383             throws PasswordMismatchException, UnknownEntityException,
384             DataBackendException
385     {
386         if (!accountExists(user))
387         {
388             throw new UnknownEntityException("The account '" +
389                     user.getName() + "' does not exist");
390         }
391
392         // log.debug("Supplied Pass: " + password);
393
// log.debug("User Pass: " + user.getPassword());
394

395         /*
396          * Unix crypt needs the existing, encrypted password text as
397          * salt for checking the supplied password. So we supply it
398          * into the checkPassword routine
399          */

400
401         if (!TurbineSecurity.checkPassword(password, user.getPassword()))
402         {
403             throw new PasswordMismatchException("The passwords do not match");
404         }
405     }
406
407     /**
408      * Change the password for an User. The user must have supplied the
409      * old password to allow the change.
410      *
411      * @param user an User to change password for.
412      * @param oldPassword The old password to verify
413      * @param newPassword The new password to set
414      * @exception PasswordMismatchException if the supplied password was
415      * incorrect.
416      * @exception UnknownEntityException if the user's account does not
417      * exist in the database.
418      * @exception DataBackendException if there is a problem accessing the
419      * storage.
420      */

421     public void changePassword(User user, String JavaDoc oldPassword,
422                                String JavaDoc newPassword)
423             throws PasswordMismatchException, UnknownEntityException,
424             DataBackendException
425     {
426         if (!accountExists(user))
427         {
428             throw new UnknownEntityException("The account '" +
429                     user.getName() + "' does not exist");
430         }
431
432         if (!TurbineSecurity.checkPassword(oldPassword, user.getPassword()))
433         {
434             throw new PasswordMismatchException(
435                     "The supplied old password for '" + user.getName() +
436                     "' was incorrect");
437         }
438         user.setPassword(TurbineSecurity.encryptPassword(newPassword));
439         // save the changes in the database imediately, to prevent the password
440
// being 'reverted' to the old value if the user data is lost somehow
441
// before it is saved at session's expiry.
442
store(user);
443     }
444
445     /**
446      * Forcibly sets new password for an User.
447      *
448      * This is supposed by the administrator to change the forgotten or
449      * compromised passwords. Certain implementatations of this feature
450      * would require administrative level access to the authenticating
451      * server / program.
452      *
453      * @param user an User to change password for.
454      * @param password the new password.
455      * @exception UnknownEntityException if the user's record does not
456      * exist in the database.
457      * @exception DataBackendException if there is a problem accessing the
458      * storage.
459      */

460     public void forcePassword(User user, String JavaDoc password)
461             throws UnknownEntityException, DataBackendException
462     {
463         if (!accountExists(user))
464         {
465             throw new UnknownEntityException("The account '" +
466                     user.getName() + "' does not exist");
467         }
468         user.setPassword(TurbineSecurity.encryptPassword(password));
469         // save the changes in the database immediately, to prevent the
470
// password being 'reverted' to the old value if the user data
471
// is lost somehow before it is saved at session's expiry.
472
store(user);
473     }
474
475     /**
476      * Creates new user account with specified attributes.
477      *
478      * @param user The object describing account to be created.
479      * @param initialPassword the password for the new account
480      * @throws DataBackendException if there was an error accessing
481      the data backend.
482      * @throws EntityExistsException if the user account already exists.
483      */

484     public void createAccount(User user, String JavaDoc initialPassword)
485             throws EntityExistsException, DataBackendException
486     {
487         if (StringUtils.isEmpty(user.getName()))
488         {
489             throw new DataBackendException("Could not create "
490                     + "an user with empty name!");
491         }
492
493         if (accountExists(user))
494         {
495             throw new EntityExistsException("The account '" +
496                     user.getName() + "' already exists");
497         }
498         user.setPassword(TurbineSecurity.encryptPassword(initialPassword));
499
500         Criteria criteria = TurbineUserPeer.buildCriteria(user);
501         try
502         {
503             // perform the insert to the database
504
ObjectKey pk = TurbineUserPeer.doInsert(criteria);
505
506             // update the user object with the primary key
507
TurbineMapBuilder mapbuilder = (TurbineMapBuilder)
508                     TurbineUserPeer.getMapBuilder("org.apache.turbine.util.db.map.TurbineMapBuilder");
509             user.setPerm(mapbuilder.getUserId(), pk);
510             ((BaseObject) user).setPrimaryKey(pk);
511         }
512         catch (Exception JavaDoc e)
513         {
514             throw new DataBackendException("Failed to create account '" +
515                     user.getName() + "'", e);
516         }
517     }
518
519     /**
520      * Removes an user account from the system.
521      *
522      * @param user the object describing the account to be removed.
523      * @throws DataBackendException if there was an error accessing
524      the data backend.
525      * @throws UnknownEntityException if the user account is not present.
526      */

527     public void removeAccount(User user)
528             throws UnknownEntityException, DataBackendException
529     {
530         if (!accountExists(user))
531         {
532             throw new UnknownEntityException("The account '" +
533                     user.getName() + "' does not exist");
534         }
535         Criteria criteria = new Criteria();
536         criteria.add(TurbineUserPeer.USERNAME, user.getName());
537         try
538         {
539             TurbineUserPeer.doDelete(criteria);
540         }
541         catch (Exception JavaDoc e)
542         {
543             throw new DataBackendException("Failed to remove account '" +
544                     user.getName() + "'", e);
545         }
546     }
547 }
548
Popular Tags