Coverage report

  %line %branch
org.apache.turbine.services.security.db.DBUserManager
2% 
31% 

 1  
 package org.apache.turbine.services.security.db;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2005 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.Hashtable;
 20  
 import java.util.Iterator;
 21  
 import java.util.List;
 22  
 
 23  
 import org.apache.commons.configuration.Configuration;
 24  
 import org.apache.commons.lang.StringUtils;
 25  
 import org.apache.torque.om.BaseObject;
 26  
 import org.apache.torque.om.ObjectKey;
 27  
 import org.apache.torque.om.Persistent;
 28  
 import org.apache.torque.util.Criteria;
 29  
 import org.apache.turbine.om.security.User;
 30  
 import org.apache.turbine.om.security.peer.TurbineUserPeer;
 31  
 import org.apache.turbine.services.security.TurbineSecurity;
 32  
 import org.apache.turbine.services.security.UserManager;
 33  
 import org.apache.turbine.util.db.map.TurbineMapBuilder;
 34  
 import org.apache.turbine.util.security.DataBackendException;
 35  
 import org.apache.turbine.util.security.EntityExistsException;
 36  
 import org.apache.turbine.util.security.PasswordMismatchException;
 37  
 import org.apache.turbine.util.security.UnknownEntityException;
 38  
 
 39  
 /**
 40  
  * An UserManager performs {@link org.apache.turbine.om.security.User}
 41  
  * objects related tasks on behalf of the
 42  
  * {@link org.apache.turbine.services.security.BaseSecurityService}.
 43  
  *
 44  
  * This implementation uses a relational database for storing user data. It
 45  
  * expects that the User interface implementation will be castable to
 46  
  * {@link org.apache.torque.om.BaseObject}.
 47  
  *
 48  
  * @author <a href="mailto:jon@collab.net">Jon S. Stevens</a>
 49  
  * @author <a href="mailto:john.mcnally@clearink.com">John D. McNally</a>
 50  
  * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
 51  
  * @author <a href="mailto:cberry@gluecode.com">Craig D. Berry</a>
 52  
  * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
 53  
  * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
 54  
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 55  
  * @version $Id: DBUserManager.java 278824 2005-09-05 20:01:15Z henning $
 56  
  */
 57  2
 public class DBUserManager
 58  
         implements UserManager
 59  
 {
 60  
     /**
 61  
      * Initializes the UserManager
 62  
      *
 63  
      * @param conf A Configuration object to init this Manager
 64  
      */
 65  
     public void init(Configuration conf)
 66  
     {
 67  
         // GNDN
 68  2
     }
 69  
 
 70  
     /**
 71  
      * Check whether a specified user's account exists.
 72  
      *
 73  
      * The login name is used for looking up the account.
 74  
      *
 75  
      * @param user The user to be checked.
 76  
      * @return true if the specified account exists
 77  
      * @throws DataBackendException if there was an error accessing
 78  
      *         the data backend.
 79  
      */
 80  
     public boolean accountExists(User user)
 81  
             throws DataBackendException
 82  
     {
 83  0
         return accountExists(user.getName());
 84  
     }
 85  
 
 86  
     /**
 87  
      * Check whether a specified user's account exists.
 88  
      *
 89  
      * The login name is used for looking up the account.
 90  
      *
 91  
      * @param userName The name of the user to be checked.
 92  
      * @return true if the specified account exists
 93  
      * @throws DataBackendException if there was an error accessing
 94  
      *         the data backend.
 95  
      */
 96  
     public boolean accountExists(String userName)
 97  
             throws DataBackendException
 98  
     {
 99  0
         Criteria criteria = new Criteria();
 100  0
         criteria.add(TurbineUserPeer.USERNAME, userName);
 101  
         List users;
 102  
         try
 103  
         {
 104  0
             users = TurbineUserPeer.doSelect(criteria);
 105  
         }
 106  0
         catch (Exception e)
 107  
         {
 108  0
             throw new DataBackendException(
 109  
                     "Failed to check account's presence", e);
 110  0
         }
 111  0
         if (users.size() > 1)
 112  
         {
 113  0
             throw new DataBackendException(
 114  
                     "Multiple Users with same username '" + userName + "'");
 115  
         }
 116  0
         return (users.size() == 1);
 117  
     }
 118  
 
 119  
     /**
 120  
      * Retrieve a user from persistent storage using username as the
 121  
      * key.
 122  
      *
 123  
      * @param userName the name of the user.
 124  
      * @return an User object.
 125  
      * @exception UnknownEntityException if the user's account does not
 126  
      *            exist in the database.
 127  
      * @exception DataBackendException if there is a problem accessing the
 128  
      *            storage.
 129  
      */
 130  
     public User retrieve(String userName)
 131  
             throws UnknownEntityException, DataBackendException
 132  
     {
 133  0
         Criteria criteria = new Criteria();
 134  0
         criteria.add(TurbineUserPeer.USERNAME, userName);
 135  
 
 136  0
         List users = retrieveList(criteria);
 137  
 
 138  0
         if (users.size() > 1)
 139  
         {
 140  0
             throw new DataBackendException(
 141  
                     "Multiple Users with same username '" + userName + "'");
 142  
         }
 143  0
         if (users.size() == 1)
 144  
         {
 145  0
             return (User) users.get(0);
 146  
         }
 147  0
         throw new UnknownEntityException("Unknown user '" + userName + "'");
 148  
     }
 149  
 
 150  
     /**
 151  
      * Retrieve a user from persistent storage using the primary key
 152  
      *
 153  
      * @param key The primary key object
 154  
      * @return an User object.
 155  
      * @throws UnknownEntityException if the user's record does not
 156  
      *         exist in the database.
 157  
      * @throws DataBackendException if there is a problem accessing the
 158  
      *         storage.
 159  
      */
 160  
     public User retrieveById(Object key)
 161  
             throws UnknownEntityException, DataBackendException
 162  
     {
 163  0
         Criteria criteria = new Criteria();
 164  0
         criteria.add(TurbineUserPeer.USER_ID, key);
 165  
 
 166  0
         List users = retrieveList(criteria);
 167  
 
 168  0
         if (users.size() > 1)
 169  
         {
 170  0
             throw new DataBackendException(
 171  
                 "Multiple Users with same unique Key '" + String.valueOf(key) + "'");
 172  
         }
 173  0
         if (users.size() == 1)
 174  
         {
 175  0
             return (User) users.get(0);
 176  
         }
 177  0
         throw new UnknownEntityException("Unknown user with key '" + String.valueOf(key) + "'");
 178  
     }
 179  
 
 180  
     /**
 181  
      * Retrieve a list of users that meet the specified criteria.
 182  
      *
 183  
      * As the keys for the criteria, you should use the constants that
 184  
      * are defined in {@link User} interface, plus the names
 185  
      * of the custom attributes you added to your user representation
 186  
      * in the data storage. Use verbatim names of the attributes -
 187  
      * without table name prefix in case of Torque implementation.
 188  
      *
 189  
      * @param criteria The criteria of selection.
 190  
      * @return a List of users meeting the criteria.
 191  
      * @throws DataBackendException if there is a problem accessing the
 192  
      *         storage.
 193  
      */
 194  
     public List retrieveList(Criteria criteria)
 195  
         throws DataBackendException
 196  
     {
 197  0
         for (Iterator keys = criteria.keySet().iterator(); keys.hasNext(); )
 198  
         {
 199  0
             String key = (String) keys.next();
 200  
 
 201  
             // set the table name for all attached criterion
 202  0
             Criteria.Criterion[] criterion = criteria
 203  
                     .getCriterion(key).getAttachedCriterion();
 204  
 
 205  0
             for (int i = 0; i < criterion.length; i++)
 206  
             {
 207  0
                 if (StringUtils.isEmpty(criterion[i].getTable()))
 208  
                 {
 209  0
                     criterion[i].setTable(TurbineUserPeer.getTableName());
 210  
                 }
 211  
             }
 212  
         }
 213  0
         List users = null;
 214  
         try
 215  
         {
 216  0
             users = TurbineUserPeer.doSelect(criteria);
 217  
         }
 218  0
         catch (Exception e)
 219  
         {
 220  0
             throw new DataBackendException("Failed to retrieve users", e);
 221  0
         }
 222  0
         return users;
 223  
     }
 224  
 
 225  
     /**
 226  
      * Retrieve a set of users that meet the specified criteria.
 227  
      *
 228  
      * As the keys for the criteria, you should use the constants that
 229  
      * are defined in {@link User} interface, plus the names
 230  
      * of the custom attributes you added to your user representation
 231  
      * in the data storage. Use verbatim names of the attributes -
 232  
      * without table name prefix in case of DB implementation.
 233  
      *
 234  
      * @param criteria The criteria of selection.
 235  
      * @return a List of users meeting the criteria.
 236  
      * @throws DataBackendException if there is a problem accessing the
 237  
      *         storage.
 238  
      * @deprecated Use <a href="#retrieveList">retrieveList</a> instead.
 239  
      */
 240  
     public User[] retrieve(Criteria criteria)
 241  
             throws DataBackendException
 242  
     {
 243  0
         return (User []) retrieveList(criteria).toArray(new User[0]);
 244  
     }
 245  
 
 246  
     /**
 247  
      * Retrieve a user from persistent storage using username as the
 248  
      * key, and authenticate the user. The implementation may chose
 249  
      * to authenticate to the server as the user whose data is being
 250  
      * retrieved.
 251  
      *
 252  
      * @param userName the name of the user.
 253  
      * @param password the user supplied password.
 254  
      * @return an User object.
 255  
      * @exception PasswordMismatchException if the supplied password was
 256  
      *            incorrect.
 257  
      * @exception UnknownEntityException if the user's account does not
 258  
      *            exist in the database.
 259  
      * @exception DataBackendException if there is a problem accessing the
 260  
      *            storage.
 261  
      */
 262  
     public User retrieve(String userName, String password)
 263  
             throws PasswordMismatchException, UnknownEntityException,
 264  
             DataBackendException
 265  
     {
 266  0
         User user = retrieve(userName);
 267  0
         authenticate(user, password);
 268  0
         return user;
 269  
     }
 270  
 
 271  
     /**
 272  
      * Save an User object to persistent storage. User's account is
 273  
      * required to exist in the storage.
 274  
      *
 275  
      * @param user an User object to store.
 276  
      * @exception UnknownEntityException if the user's account does not
 277  
      *            exist in the database.
 278  
      * @exception DataBackendException if there is a problem accessing the
 279  
      *            storage.
 280  
      */
 281  
     public void store(User user)
 282  
             throws UnknownEntityException, DataBackendException
 283  
     {
 284  0
         if (!accountExists(user))
 285  
         {
 286  0
             throw new UnknownEntityException("The account '" +
 287  
                     user.getName() + "' does not exist");
 288  
         }
 289  
 
 290  0
         Criteria criteria = TurbineUserPeer.buildCriteria(user);
 291  
         try
 292  
         {
 293  0
             TurbineUserPeer.doUpdate(criteria);
 294  
         }
 295  0
         catch (Exception e)
 296  
         {
 297  0
             throw new DataBackendException("Failed to save user object", e);
 298  0
         }
 299  0
     }
 300  
 
 301  
     /**
 302  
      * Saves User data when the session is unbound. The user account is required
 303  
      * to exist in the storage.
 304  
      *
 305  
      * LastLogin, AccessCounter, persistent pull tools, and any data stored
 306  
      * in the permData hashtable that is not mapped to a column will be saved.
 307  
      *
 308  
      * @exception UnknownEntityException if the user's account does not
 309  
      *            exist in the database.
 310  
      * @exception DataBackendException if there is a problem accessing the
 311  
      *            storage.
 312  
      */
 313  
     public void saveOnSessionUnbind(User user)
 314  
             throws UnknownEntityException, DataBackendException
 315  
     {
 316  0
         if (!user.hasLoggedIn())
 317  
         {
 318  0
             return;
 319  
         }
 320  
 
 321  0
         if (!accountExists(user))
 322  
         {
 323  0
             throw new UnknownEntityException("The account '" +
 324  
                     user.getName() + "' does not exist");
 325  
         }
 326  0
         Criteria crit = new Criteria();
 327  0
         if (!((Persistent) user).isNew())
 328  
         {
 329  0
             crit.add(TurbineUserPeer.USER_ID, ((Persistent) user).getPrimaryKey());
 330  
         }
 331  
 
 332  0
         Hashtable permStorage = (Hashtable) user.getPermStorage().clone();
 333  0
         crit.add(TurbineUserPeer.LAST_LOGIN, permStorage.remove(TurbineUserPeer.LAST_LOGIN));
 334  
 
 335  
         // The OBJECT_DATA column only stores data not mapped to a column.  We must
 336  
         // remove all of the extra data and serialize the rest.  Access Counter
 337  
         // is not mapped to a column so it will be serialized into OBJECT_DATA.
 338  0
         for (int i = 1; i < TurbineUserPeer.columnNames.length; i++)
 339  
         {
 340  0
             if (permStorage.containsKey(TurbineUserPeer.columnNames[i]))
 341  
             {
 342  0
                 permStorage.remove(TurbineUserPeer.columnNames[i]);
 343  
             }
 344  
         }
 345  0
         crit.add(TurbineUserPeer.OBJECT_DATA, permStorage);
 346  
 
 347  
         try
 348  
         {
 349  0
             TurbineUserPeer.doUpdate(crit);
 350  
         }
 351  0
         catch (Exception e)
 352  
         {
 353  0
             throw new DataBackendException("Failed to save user object", e);
 354  0
         }
 355  
 
 356  0
     }
 357  
 
 358  
     /**
 359  
      * Authenticate an User with the specified password. If authentication
 360  
      * is successful the method returns nothing. If there are any problems,
 361  
      * exception was thrown.
 362  
      *
 363  
      * @param user an User object to authenticate.
 364  
      * @param password the user supplied password.
 365  
      * @exception PasswordMismatchException if the supplied password was
 366  
      *            incorrect.
 367  
      * @exception UnknownEntityException if the user's account does not
 368  
      *            exist in the database.
 369  
      * @exception DataBackendException if there is a problem accessing the
 370  
      *            storage.
 371  
      */
 372  
     public void authenticate(User user, String password)
 373  
             throws PasswordMismatchException, UnknownEntityException,
 374  
             DataBackendException
 375  
     {
 376  0
         if (!accountExists(user))
 377  
         {
 378  0
             throw new UnknownEntityException("The account '" +
 379  
                     user.getName() + "' does not exist");
 380  
         }
 381  
 
 382  
         // log.debug("Supplied Pass: " + password);
 383  
         // log.debug("User Pass: " + user.getPassword());
 384  
 
 385  
         /*
 386  
          * Unix crypt needs the existing, encrypted password text as
 387  
          * salt for checking the supplied password. So we supply it
 388  
          * into the checkPassword routine
 389  
          */
 390  
 
 391  0
         if (!TurbineSecurity.checkPassword(password, user.getPassword()))
 392  
         {
 393  0
             throw new PasswordMismatchException("The passwords do not match");
 394  
         }
 395  0
     }
 396  
 
 397  
     /**
 398  
      * Change the password for an User. The user must have supplied the
 399  
      * old password to allow the change.
 400  
      *
 401  
      * @param user an User to change password for.
 402  
      * @param oldPassword The old password to verify
 403  
      * @param newPassword The new password to set
 404  
      * @exception PasswordMismatchException if the supplied password was
 405  
      *            incorrect.
 406  
      * @exception UnknownEntityException if the user's account does not
 407  
      *            exist in the database.
 408  
      * @exception DataBackendException if there is a problem accessing the
 409  
      *            storage.
 410  
      */
 411  
     public void changePassword(User user, String oldPassword,
 412  
                                String newPassword)
 413  
             throws PasswordMismatchException, UnknownEntityException,
 414  
             DataBackendException
 415  
     {
 416  0
         if (!accountExists(user))
 417  
         {
 418  0
             throw new UnknownEntityException("The account '" +
 419  
                     user.getName() + "' does not exist");
 420  
         }
 421  
 
 422  0
         if (!TurbineSecurity.checkPassword(oldPassword, user.getPassword()))
 423  
         {
 424  0
             throw new PasswordMismatchException(
 425  
                     "The supplied old password for '" + user.getName() +
 426  
                     "' was incorrect");
 427  
         }
 428  0
         user.setPassword(TurbineSecurity.encryptPassword(newPassword));
 429  
         // save the changes in the database imediately, to prevent the password
 430  
         // being 'reverted' to the old value if the user data is lost somehow
 431  
         // before it is saved at session's expiry.
 432  0
         store(user);
 433  0
     }
 434  
 
 435  
     /**
 436  
      * Forcibly sets new password for an User.
 437  
      *
 438  
      * This is supposed by the administrator to change the forgotten or
 439  
      * compromised passwords. Certain implementatations of this feature
 440  
      * would require administrative level access to the authenticating
 441  
      * server / program.
 442  
      *
 443  
      * @param user an User to change password for.
 444  
      * @param password the new password.
 445  
      * @exception UnknownEntityException if the user's record does not
 446  
      *            exist in the database.
 447  
      * @exception DataBackendException if there is a problem accessing the
 448  
      *            storage.
 449  
      */
 450  
     public void forcePassword(User user, String password)
 451  
             throws UnknownEntityException, DataBackendException
 452  
     {
 453  0
         if (!accountExists(user))
 454  
         {
 455  0
             throw new UnknownEntityException("The account '" +
 456  
                     user.getName() + "' does not exist");
 457  
         }
 458  0
         user.setPassword(TurbineSecurity.encryptPassword(password));
 459  
         // save the changes in the database immediately, to prevent the
 460  
         // password being 'reverted' to the old value if the user data
 461  
         // is lost somehow before it is saved at session's expiry.
 462  0
         store(user);
 463  0
     }
 464  
 
 465  
     /**
 466  
      * Creates new user account with specified attributes.
 467  
      *
 468  
      * @param user The object describing account to be created.
 469  
      * @param initialPassword the password for the new account
 470  
      * @throws DataBackendException if there was an error accessing
 471  
      the data backend.
 472  
      * @throws EntityExistsException if the user account already exists.
 473  
      */
 474  
     public void createAccount(User user, String initialPassword)
 475  
             throws EntityExistsException, DataBackendException
 476  
     {
 477  0
         if (StringUtils.isEmpty(user.getName()))
 478  
         {
 479  0
             throw new DataBackendException("Could not create "
 480  
                     + "an user with empty name!");
 481  
         }
 482  
 
 483  0
         if (accountExists(user))
 484  
         {
 485  0
             throw new EntityExistsException("The account '" +
 486  
                     user.getName() + "' already exists");
 487  
         }
 488  0
         user.setPassword(TurbineSecurity.encryptPassword(initialPassword));
 489  
 
 490  0
         Criteria criteria = TurbineUserPeer.buildCriteria(user);
 491  
         try
 492  
         {
 493  
             // perform the insert to the database
 494  0
             ObjectKey pk = TurbineUserPeer.doInsert(criteria);
 495  
 
 496  
             // update the user object with the primary key
 497  0
             TurbineMapBuilder mapbuilder = (TurbineMapBuilder)
 498  
                     TurbineUserPeer.getMapBuilder("org.apache.turbine.util.db.map.TurbineMapBuilder");
 499  0
             user.setPerm(mapbuilder.getUserId(), pk);
 500  0
             ((BaseObject) user).setPrimaryKey(pk);
 501  
         }
 502  0
         catch (Exception e)
 503  
         {
 504  0
             throw new DataBackendException("Failed to create account '" +
 505  
                     user.getName() + "'", e);
 506  0
         }
 507  0
     }
 508  
 
 509  
     /**
 510  
      * Removes an user account from the system.
 511  
      *
 512  
      * @param user the object describing the account to be removed.
 513  
      * @throws DataBackendException if there was an error accessing
 514  
      the data backend.
 515  
      * @throws UnknownEntityException if the user account is not present.
 516  
      */
 517  
     public void removeAccount(User user)
 518  
             throws UnknownEntityException, DataBackendException
 519  
     {
 520  0
         if (!accountExists(user))
 521  
         {
 522  0
             throw new UnknownEntityException("The account '" +
 523  
                     user.getName() + "' does not exist");
 524  
         }
 525  0
         Criteria criteria = new Criteria();
 526  0
         criteria.add(TurbineUserPeer.USERNAME, user.getName());
 527  
         try
 528  
         {
 529  0
             TurbineUserPeer.doDelete(criteria);
 530  
         }
 531  0
         catch (Exception e)
 532  
         {
 533  0
             throw new DataBackendException("Failed to remove account '" +
 534  
                     user.getName() + "'", e);
 535  0
         }
 536  0
     }
 537  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.