KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > turbine > services > security > torque > TorqueUserManager


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

59 public class TorqueUserManager
60     implements UserManager
61 {
62     /** Logging */
63     private static Log log = LogFactory.getLog(TorqueUserManager.class);
64
65     /**
66      * Initializes the UserManager
67      *
68      * @param conf A Configuration object to init this Manager
69      *
70      * @throws InitializationException When something went wrong.
71      */

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

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

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

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

168     public User retrieveById(Object JavaDoc key)
169             throws UnknownEntityException, DataBackendException
170     {
171         Criteria criteria = new Criteria();
172         criteria.add(UserPeerManager.getIdColumn(), key);
173
174         List JavaDoc users = retrieveList(criteria);
175
176         if (users.size() > 1)
177         {
178             throw new DataBackendException(
179                 "Multiple Users with same unique Key '" + String.valueOf(key) + "'");
180         }
181         if (users.size() == 1)
182         {
183             return (User) users.get(0);
184         }
185         throw new UnknownEntityException("Unknown user with key '" + String.valueOf(key) + "'");
186     }
187
188     /**
189      * @deprecated Use <a HREF="#retrieveList">retrieveList</a> instead.
190      *
191      * @param criteria The criteria of selection.
192      * @return a List of users meeting the criteria.
193      * @throws DataBackendException if there is a problem accessing the
194      * storage.
195      */

196     public User[] retrieve(Criteria criteria)
197         throws DataBackendException
198     {
199         return (User [])retrieveList(criteria).toArray(new User[0]);
200     }
201
202     /**
203      * Retrieve a list of users that meet the specified criteria.
204      *
205      * As the keys for the criteria, you should use the constants that
206      * are defined in {@link User} interface, plus the names
207      * of the custom attributes you added to your user representation
208      * in the data storage. Use verbatim names of the attributes -
209      * without table name prefix in case of Torque implementation.
210      *
211      * @param criteria The criteria of selection.
212      * @return a List of users meeting the criteria.
213      * @throws DataBackendException if there is a problem accessing the
214      * storage.
215      */

216     public List JavaDoc retrieveList(Criteria criteria)
217         throws DataBackendException
218     {
219         for (Iterator JavaDoc keys = criteria.keySet().iterator(); keys.hasNext(); )
220         {
221             String JavaDoc key = (String JavaDoc) keys.next();
222
223             // set the table name for all attached criterion
224
Criteria.Criterion[] criterion = criteria
225                 .getCriterion(key).getAttachedCriterion();
226
227             for (int i = 0; i < criterion.length; i++)
228             {
229                 if (StringUtils.isEmpty(criterion[i].getTable()))
230                 {
231                     criterion[i].setTable(UserPeerManager.getTableName());
232                 }
233             }
234         }
235         List JavaDoc users = null;
236         try
237         {
238             users = UserPeerManager.doSelect(criteria);
239         }
240         catch (Exception JavaDoc e)
241         {
242             throw new DataBackendException("Failed to retrieve users", e);
243         }
244         return users;
245     }
246
247     /**
248      * Retrieve a user from persistent storage using username as the
249      * key, and authenticate the user. The implementation may chose
250      * to authenticate to the server as the user whose data is being
251      * retrieved.
252      *
253      * @param userName the name of the user.
254      * @param password the user supplied password.
255      * @return an User object.
256      * @exception PasswordMismatchException if the supplied password was
257      * incorrect.
258      * @exception UnknownEntityException if the user's account does not
259      * exist in the database.
260      * @exception DataBackendException if there is a problem accessing the
261      * storage.
262      */

263     public User retrieve(String JavaDoc userName, String JavaDoc password)
264         throws PasswordMismatchException, UnknownEntityException,
265                DataBackendException
266     {
267         User user = retrieve(userName);
268         authenticate(user, password);
269         return user;
270     }
271
272     /**
273      * Save an User object to persistent storage. User's account is
274      * required to exist in the storage.
275      *
276      * @param user an User object to store.
277      * @exception UnknownEntityException if the user's account does not
278      * exist in the database.
279      * @exception DataBackendException if there is a problem accessing the
280      * storage.
281      */

282     public void store(User user)
283         throws UnknownEntityException, DataBackendException
284     {
285         if (!accountExists(user))
286         {
287             throw new UnknownEntityException("The account '" +
288                                              user.getName() + "' does not exist");
289         }
290
291         try
292         {
293             // this is to mimic the old behavior of the method, the user
294
// should be new that is passed to this method. It would be
295
// better if this was checked, but the original code did not
296
// care about the user's state, so we set it to be appropriate
297
((Persistent) user).setNew(false);
298             ((Persistent) user).setModified(true);
299             ((Persistent) user).save();
300         }
301         catch (Exception JavaDoc e)
302         {
303             throw new DataBackendException("Failed to save user object", e);
304         }
305     }
306
307     /**
308      * Saves User data when the session is unbound. The user account is required
309      * to exist in the storage.
310      *
311      * LastLogin, AccessCounter, persistent pull tools, and any data stored
312      * in the permData hashtable that is not mapped to a column will be saved.
313      *
314      * @exception UnknownEntityException if the user's account does not
315      * exist in the database.
316      * @exception DataBackendException if there is a problem accessing the
317      * storage.
318      */

319     public void saveOnSessionUnbind(User user)
320         throws UnknownEntityException, DataBackendException
321     {
322         if (!user.hasLoggedIn())
323         {
324             return;
325         }
326         store(user);
327     }
328
329
330     /**
331      * Authenticate an User with the specified password. If authentication
332      * is successful the method returns nothing. If there are any problems,
333      * exception was thrown.
334      *
335      * @param user an User object to authenticate.
336      * @param password the user supplied password.
337      * @exception PasswordMismatchException if the supplied password was
338      * incorrect.
339      * @exception UnknownEntityException if the user's account does not
340      * exist in the database.
341      * @exception DataBackendException if there is a problem accessing the
342      * storage.
343      */

344     public void authenticate(User user, String JavaDoc password)
345         throws PasswordMismatchException, UnknownEntityException,
346                DataBackendException
347     {
348         if (!accountExists(user))
349         {
350             throw new UnknownEntityException("The account '" +
351                                              user.getName() + "' does not exist");
352         }
353
354         // log.debug("Supplied Pass: " + password);
355
// log.debug("User Pass: " + user.getPassword());
356

357         /*
358          * Unix crypt needs the existing, encrypted password text as
359          * salt for checking the supplied password. So we supply it
360          * into the checkPassword routine
361          */

362
363         if (!TurbineSecurity.checkPassword(password, user.getPassword()))
364         {
365             throw new PasswordMismatchException("The passwords do not match");
366         }
367     }
368
369     /**
370      * Change the password for an User. The user must have supplied the
371      * old password to allow the change.
372      *
373      * @param user an User to change password for.
374      * @param oldPassword The old password to verify
375      * @param newPassword The new password to set
376      * @exception PasswordMismatchException if the supplied password was
377      * incorrect.
378      * @exception UnknownEntityException if the user's account does not
379      * exist in the database.
380      * @exception DataBackendException if there is a problem accessing the
381      * storage.
382      */

383     public void changePassword(User user, String JavaDoc oldPassword,
384                                String JavaDoc newPassword)
385         throws PasswordMismatchException, UnknownEntityException,
386                DataBackendException
387     {
388         if (!accountExists(user))
389         {
390             throw new UnknownEntityException("The account '" +
391                                              user.getName() + "' does not exist");
392         }
393
394         if (!TurbineSecurity.checkPassword(oldPassword, user.getPassword()))
395         {
396             throw new PasswordMismatchException(
397                 "The supplied old password for '" + user.getName() +
398                 "' was incorrect");
399         }
400         user.setPassword(TurbineSecurity.encryptPassword(newPassword));
401         // save the changes in the database imediately, to prevent the password
402
// being 'reverted' to the old value if the user data is lost somehow
403
// before it is saved at session's expiry.
404
store(user);
405     }
406
407     /**
408      * Forcibly sets new password for an User.
409      *
410      * This is supposed by the administrator to change the forgotten or
411      * compromised passwords. Certain implementatations of this feature
412      * would require administrative level access to the authenticating
413      * server / program.
414      *
415      * @param user an User to change password for.
416      * @param password the new password.
417      * @exception UnknownEntityException if the user's record does not
418      * exist in the database.
419      * @exception DataBackendException if there is a problem accessing the
420      * storage.
421      */

422     public void forcePassword(User user, String JavaDoc password)
423         throws UnknownEntityException, DataBackendException
424     {
425         if (!accountExists(user))
426         {
427             throw new UnknownEntityException("The account '" +
428                                              user.getName() + "' does not exist");
429         }
430         user.setPassword(TurbineSecurity.encryptPassword(password));
431         // save the changes in the database immediately, to prevent the
432
// password being 'reverted' to the old value if the user data
433
// is lost somehow before it is saved at session's expiry.
434
store(user);
435     }
436
437     /**
438      * Creates new user account with specified attributes.
439      *
440      * @param user The object describing account to be created.
441      * @param initialPassword the password for the new account
442      * @throws DataBackendException if there was an error accessing
443      the data backend.
444      * @throws EntityExistsException if the user account already exists.
445      */

446     public void createAccount(User user, String JavaDoc initialPassword)
447         throws EntityExistsException, DataBackendException
448     {
449         if(StringUtils.isEmpty(user.getName()))
450         {
451             throw new DataBackendException("Could not create "
452                                            + "an user with empty name!");
453         }
454
455         if (accountExists(user))
456         {
457             throw new EntityExistsException("The account '" +
458                                             user.getName() + "' already exists");
459         }
460         user.setPassword(TurbineSecurity.encryptPassword(initialPassword));
461
462         try
463         {
464             // this is to mimic the old behavior of the method, the user
465
// should be new that is passed to this method. It would be
466
// better if this was checked, but the original code did not
467
// care about the user's state, so we set it to be appropriate
468
((Persistent) user).setNew(true);
469             ((Persistent) user).setModified(true);
470             ((Persistent) user).save();
471         }
472         catch (Exception JavaDoc e)
473         {
474             throw new DataBackendException("Failed to create account '" +
475                                            user.getName() + "'", e);
476         }
477     }
478
479     /**
480      * Removes an user account from the system.
481      *
482      * @param user the object describing the account to be removed.
483      * @throws DataBackendException if there was an error accessing
484      the data backend.
485      * @throws UnknownEntityException if the user account is not present.
486      */

487     public void removeAccount(User user)
488         throws UnknownEntityException, DataBackendException
489     {
490         if (!accountExists(user))
491         {
492             throw new UnknownEntityException("The account '" +
493                                              user.getName() + "' does not exist");
494         }
495         Criteria criteria = new Criteria();
496         criteria.add(UserPeerManager.getNameColumn(), user.getName());
497         try
498         {
499             UserPeerManager.doDelete(criteria);
500         }
501         catch (Exception JavaDoc e)
502         {
503             throw new DataBackendException("Failed to remove account '" +
504                                            user.getName() + "'", e);
505         }
506     }
507 }
508
Popular Tags