Coverage report

  %line %branch
org.apache.turbine.services.security.db.DBUserManager
3% 
39% 

 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;
 20  
 import java.util.Hashtable;
 21  
 import java.util.Iterator;
 22  
 import java.util.List;
 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  1
 public class DBUserManager
 65  
         implements UserManager
 66  
 {
 67  
     /** Logging */
 68  18
     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  1
     }
 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  0
         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 userName)
 107  
             throws DataBackendException
 108  
     {
 109  0
         Criteria criteria = new Criteria();
 110  0
         criteria.add(TurbineUserPeer.USERNAME, userName);
 111  
         List users;
 112  
         try
 113  
         {
 114  0
             users = TurbineUserPeer.doSelect(criteria);
 115  
         }
 116  0
         catch (Exception e)
 117  
         {
 118  0
             throw new DataBackendException(
 119  
                     "Failed to check account's presence", e);
 120  0
         }
 121  0
         if (users.size() > 1)
 122  
         {
 123  0
             throw new DataBackendException(
 124  
                     "Multiple Users with same username '" + userName + "'");
 125  
         }
 126  0
         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 userName)
 141  
             throws UnknownEntityException, DataBackendException
 142  
     {
 143  0
         Criteria criteria = new Criteria();
 144  0
         criteria.add(TurbineUserPeer.USERNAME, userName);
 145  
 
 146  0
         List users = retrieveList(criteria);
 147  
 
 148  0
         if (users.size() > 1)
 149  
         {
 150  0
             throw new DataBackendException(
 151  
                     "Multiple Users with same username '" + userName + "'");
 152  
         }
 153  0
         if (users.size() == 1)
 154  
         {
 155  0
             return (User) users.get(0);
 156  
         }
 157  0
         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 key)
 171  
             throws UnknownEntityException, DataBackendException
 172  
     {
 173  0
         Criteria criteria = new Criteria();
 174  0
         criteria.add(TurbineUserPeer.USER_ID, key);
 175  
 
 176  0
         List users = retrieveList(criteria);
 177  
 
 178  0
         if (users.size() > 1)
 179  
         {
 180  0
             throw new DataBackendException(
 181  
                 "Multiple Users with same unique Key '" + String.valueOf(key) + "'");
 182  
         }
 183  0
         if (users.size() == 1)
 184  
         {
 185  0
             return (User) users.get(0);
 186  
         }
 187  0
         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 retrieveList(Criteria criteria)
 205  
         throws DataBackendException
 206  
     {
 207  0
         for (Iterator keys = criteria.keySet().iterator(); keys.hasNext(); )
 208  
         {
 209  0
             String key = (String) keys.next();
 210  
 
 211  
             // set the table name for all attached criterion
 212  0
             Criteria.Criterion[] criterion = criteria
 213  
                     .getCriterion(key).getAttachedCriterion();
 214  
 
 215  0
             for (int i = 0; i < criterion.length; i++)
 216  
             {
 217  0
                 if (StringUtils.isEmpty(criterion[i].getTable()))
 218  
                 {
 219  0
                     criterion[i].setTable(TurbineUserPeer.getTableName());
 220  
                 }
 221  
             }
 222  
         }
 223  0
         List users = null;
 224  
         try
 225  
         {
 226  0
             users = TurbineUserPeer.doSelect(criteria);
 227  
         }
 228  0
         catch (Exception e)
 229  
         {
 230  0
             throw new DataBackendException("Failed to retrieve users", e);
 231  0
         }
 232  0
         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  0
         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 userName, String password)
 273  
             throws PasswordMismatchException, UnknownEntityException,
 274  
             DataBackendException
 275  
     {
 276  0
         User user = retrieve(userName);
 277  0
         authenticate(user, password);
 278  0
         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  0
         if (!accountExists(user))
 295  
         {
 296  0
             throw new UnknownEntityException("The account '" +
 297  
                     user.getName() + "' does not exist");
 298  
         }
 299  
 
 300  0
         Criteria criteria = TurbineUserPeer.buildCriteria(user);
 301  
         try
 302  
         {
 303  0
             TurbineUserPeer.doUpdate(criteria);
 304  
         }
 305  0
         catch (Exception e)
 306  
         {
 307  0
             throw new DataBackendException("Failed to save user object", e);
 308  0
         }
 309  0
     }
 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  0
         if (!user.hasLoggedIn())
 327  
         {
 328  0
             return;
 329  
         }
 330  
 
 331  0
         if (!accountExists(user))
 332  
         {
 333  0
             throw new UnknownEntityException("The account '" +
 334  
                     user.getName() + "' does not exist");
 335  
         }
 336  0
         Criteria crit = new Criteria();
 337  0
         if (!((Persistent) user).isNew())
 338  
         {
 339  0
             crit.add(TurbineUserPeer.USER_ID, ((Persistent) user).getPrimaryKey());
 340  
         }
 341  
 
 342  0
         Hashtable permStorage = (Hashtable) user.getPermStorage().clone();
 343  0
         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  0
         for (int i = 1; i < TurbineUserPeer.columnNames.length; i++)
 349  
         {
 350  0
             if (permStorage.containsKey(TurbineUserPeer.columnNames[i]))
 351  
             {
 352  0
                 permStorage.remove(TurbineUserPeer.columnNames[i]);
 353  
             }
 354  
         }
 355  0
         crit.add(TurbineUserPeer.OBJECT_DATA, permStorage);
 356  
 
 357  
         try
 358  
         {
 359  0
             TurbineUserPeer.doUpdate(crit);
 360  
         }
 361  0
         catch (Exception e)
 362  
         {
 363  0
             throw new DataBackendException("Failed to save user object", e);
 364  0
         }
 365  
 
 366  0
     }
 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 password)
 383  
             throws PasswordMismatchException, UnknownEntityException,
 384  
             DataBackendException
 385  
     {
 386  0
         if (!accountExists(user))
 387  
         {
 388  0
             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  0
         if (!TurbineSecurity.checkPassword(password, user.getPassword()))
 402  
         {
 403  0
             throw new PasswordMismatchException("The passwords do not match");
 404  
         }
 405  0
     }
 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 oldPassword,
 422  
                                String newPassword)
 423  
             throws PasswordMismatchException, UnknownEntityException,
 424  
             DataBackendException
 425  
     {
 426  0
         if (!accountExists(user))
 427  
         {
 428  0
             throw new UnknownEntityException("The account '" +
 429  
                     user.getName() + "' does not exist");
 430  
         }
 431  
 
 432  0
         if (!TurbineSecurity.checkPassword(oldPassword, user.getPassword()))
 433  
         {
 434  0
             throw new PasswordMismatchException(
 435  
                     "The supplied old password for '" + user.getName() +
 436  
                     "' was incorrect");
 437  
         }
 438  0
         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  0
         store(user);
 443  0
     }
 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 password)
 461  
             throws UnknownEntityException, DataBackendException
 462  
     {
 463  0
         if (!accountExists(user))
 464  
         {
 465  0
             throw new UnknownEntityException("The account '" +
 466  
                     user.getName() + "' does not exist");
 467  
         }
 468  0
         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  0
         store(user);
 473  0
     }
 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 initialPassword)
 485  
             throws EntityExistsException, DataBackendException
 486  
     {
 487  0
         if (StringUtils.isEmpty(user.getName()))
 488  
         {
 489  0
             throw new DataBackendException("Could not create "
 490  
                     + "an user with empty name!");
 491  
         }
 492  
 
 493  0
         if (accountExists(user))
 494  
         {
 495  0
             throw new EntityExistsException("The account '" +
 496  
                     user.getName() + "' already exists");
 497  
         }
 498  0
         user.setPassword(TurbineSecurity.encryptPassword(initialPassword));
 499  
 
 500  0
         Criteria criteria = TurbineUserPeer.buildCriteria(user);
 501  
         try
 502  
         {
 503  
             // perform the insert to the database
 504  0
             ObjectKey pk = TurbineUserPeer.doInsert(criteria);
 505  
 
 506  
             // update the user object with the primary key
 507  0
             TurbineMapBuilder mapbuilder = (TurbineMapBuilder)
 508  
                     TurbineUserPeer.getMapBuilder("org.apache.turbine.util.db.map.TurbineMapBuilder");
 509  0
             user.setPerm(mapbuilder.getUserId(), pk);
 510  0
             ((BaseObject) user).setPrimaryKey(pk);
 511  
         }
 512  0
         catch (Exception e)
 513  
         {
 514  0
             throw new DataBackendException("Failed to create account '" +
 515  
                     user.getName() + "'", e);
 516  0
         }
 517  0
     }
 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  0
         if (!accountExists(user))
 531  
         {
 532  0
             throw new UnknownEntityException("The account '" +
 533  
                     user.getName() + "' does not exist");
 534  
         }
 535  0
         Criteria criteria = new Criteria();
 536  0
         criteria.add(TurbineUserPeer.USERNAME, user.getName());
 537  
         try
 538  
         {
 539  0
             TurbineUserPeer.doDelete(criteria);
 540  
         }
 541  0
         catch (Exception e)
 542  
         {
 543  0
             throw new DataBackendException("Failed to remove account '" +
 544  
                     user.getName() + "'", e);
 545  0
         }
 546  0
     }
 547  
 }

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