View Javadoc

    1   package org.apache.turbine.services.security;
    2
    3
    4   /*
    5    * Licensed to the Apache Software Foundation (ASF) under one
    6    * or more contributor license agreements.  See the NOTICE file
    7    * distributed with this work for additional information
    8    * regarding copyright ownership.  The ASF licenses this file
    9    * to you under the Apache License, Version 2.0 (the
    10   * "License"); you may not use this file except in compliance
    11   * with the License.  You may obtain a copy of the License at
    12   *
    13   *   http://www.apache.org/licenses/LICENSE-2.0
    14   *
    15   * Unless required by applicable law or agreed to in writing,
    16   * software distributed under the License is distributed on an
    17   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    18   * KIND, either express or implied.  See the License for the
    19   * specific language governing permissions and limitations
    20   * under the License.
    21   */
    22
    23
    24  import java.util.ArrayList;
    25  import java.util.List;
    26
    27  import org.apache.commons.configuration.Configuration;
    28  import org.apache.commons.logging.Log;
    29  import org.apache.commons.logging.LogFactory;
    30  import org.apache.fulcrum.factory.FactoryService;
    31  import org.apache.fulcrum.security.acl.AccessControlList;
    32  import org.apache.fulcrum.security.model.turbine.TurbineUserManager;
    33  import org.apache.fulcrum.security.model.turbine.entity.TurbineUser;
    34  import org.apache.fulcrum.security.util.DataBackendException;
    35  import org.apache.fulcrum.security.util.EntityExistsException;
    36  import org.apache.fulcrum.security.util.PasswordMismatchException;
    37  import org.apache.fulcrum.security.util.UnknownEntityException;
    38  import org.apache.fulcrum.security.util.UserSet;
    39  import org.apache.turbine.om.security.TurbineUserDelegate;
    40  import org.apache.turbine.om.security.User;
    41  import org.apache.turbine.services.InitializationException;
    42  import org.apache.turbine.services.ServiceManager;
    43  import org.apache.turbine.services.TurbineServices;
    44  import org.apache.turbine.util.ObjectUtils;
    45
    46  /**
    47   * Default user manager.
    48   *
    49   * The user manager wraps Fulcrum security user objects into
    50   * Turbine-specific ones.
    51   *
    52   *
    53   * <ol><li>either in a method with the same name (and very similar signature)
    54   * <li>or mapped to method names as listed below:
    55   *
    56   * <ul>
    57   * <li>method(s) in this manager -> Fulcrum manager method(s)
    58   * <li>{@link #createAccount(User, String)}createAccount -> addUser(User, String)
    59   * <li>{@link #removeAccount(User)} -> removeUser(User)
    60   * <li>{@link #store(User)} -> saveUser(User)
    61   * <li>{@link #retrieve(String)} and {@link #retrieve(String, String)} -> getUser(String), getUser(String, String)
    62   * <li>{@link #retrieveList(Object)} ->getAllUsers()
    63   * <li>{@link #accountExists(String)}, {@link #accountExists(User)} -> checkExists(String), checkExists(User)
    64   *
    65   * In this way all public methods of Fulcrum {@link TurbineUserManager} interface are used by reference of the Fulcrum delegate {@link #umDelegate}
    66   * and wrapped by this manager.
    67   *
    68   * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
    69   * @version $Id: PassiveUserManager.java 1096130 2011-04-23 10:37:19Z ludwig $
    70   */
    71  public class DefaultUserManager implements UserManager
    72  {
    73      /** Fulcrum user manager instance to delegate to */
    74      private TurbineUserManager umDelegate = null;
    75
    76      private FactoryService factoryService = null;
    77
    78      /** The user class, which the UserManager uses as wrapper for Fulcrum {@link TurbineUser} */
    79      private String userWrapperClass;
    80
    81
    82      /** Logging */
    83      private static Log log = LogFactory.getLog(DefaultUserManager.class);
    84
    85      /**
    86       * Wrap a Fulcrum user object into a Turbine user object
    87       *
    88       * @param user the user object to delegate to
    89       *
    90       * @return the wrapped object
    91       */
    92      protected <U extends User> U wrap(TurbineUser user)
    93      {
    94      	// U u = (U)new DefaultUserImpl(user);
    95          @SuppressWarnings("unchecked")
    96          U u = (U) getUserWrapper(user);
    97          return u;
    98      }
    99
    100     /**
    101      * Exception could be ignored, as it is tested before in {@link #init(Configuration)}.
    102      *
    103      * @param user the user object to wrap
    104      * @return instance extending {@link User}
    105      */
    106     @SuppressWarnings("unchecked")
    107 	public <U extends User> U getUserWrapper(TurbineUser user)
    108     {
    109 		try
    110 		{
    111             Object params[] = new Object[] { user };
    112             String signature[] = new String[] { TurbineUser.class.getName() };
    113             return (U) factoryService.getInstance(getUserWrapperClass(), params, signature);
    114 		}
    115 		catch (Exception e)
    116 		{
    117 			log.error("after init/late instantiation exception", e);
    118 			return null; // (U)new DefaultUserImpl(user);
    119 		}
    120 	}
    121
    122     /**
    123      * Get the wrapper class for user objects
    124      *
    125      * @return the wrapper class name
    126      */
    127     public String getUserWrapperClass()
    128     {
    129 		return userWrapperClass;
    130 	}
    131
    132     /**
    133      * Set the wrapper class for user objects
    134      *
    135      * @param userWrapperClass2 the wrapper class name
    136      */
    137     public void setUserWrapperClass(String userWrapperClass2)
    138     {
    139 		userWrapperClass = userWrapperClass2;
    140 	}
    141
    142 	/**
    143      * Initializes the UserManager
    144      *
    145      * @param conf A Configuration object to init this Manager
    146      */
    147     @Override
    148     public void init(Configuration conf) throws InitializationException
    149     {
    150         ServiceManager manager = TurbineServices.getInstance();
    151         this.umDelegate = (TurbineUserManager)manager.getService(TurbineUserManager.ROLE);
    152
    153         String userWrapperClass = conf.getString(
    154                 SecurityService.USER_WRAPPER_KEY,
    155                 SecurityService.USER_WRAPPER_DEFAULT);
    156
    157 //        String userClass = conf.getString(
    158 //                SecurityService.USER_KEY,
    159 //                SecurityService.USER_DEFAULT);
    160
    161         try
    162         {
    163         	factoryService = (FactoryService)manager.getService(FactoryService.ROLE);
    164
    165             //  check instantiation
    166
    167         	// should provide default constructor
    168         	TurbineUser turbineUser = umDelegate.getUserInstance();
    169         			//(TurbineUser) factoryService.getInstance(userClass);
    170             Object params[] = new Object[] { turbineUser };
    171             String signature[] = new String[] { TurbineUser.class.getName() };
    172
    173             // Just check if exceptions would occur
    174             factoryService.getInstance(userWrapperClass, params, signature);
    175
    176             this.setUserWrapperClass(userWrapperClass);
    177         }
    178         catch (Exception e)
    179 	    {
    180 	       throw new InitializationException("Failed to instantiate user wrapper class", e);
    181 	    }
    182
    183     }
    184
    185
    186 	/**
    187      * Check whether a specified user's account exists.
    188      *
    189      * The login name is used for looking up the account.
    190      *
    191      * @param user The user to be checked.
    192      * @return true if the specified account exists
    193      * @throws DataBackendException if there was an error accessing the data backend.
    194      */
    195     @Override
    196     public boolean accountExists(User user)
    197             throws DataBackendException
    198     {
    199         if (user == null) {
    200             return false;
    201         }
    202         return umDelegate.checkExists(user.getUserDelegate());
    203     }
    204
    205     /**
    206      * Check whether a specified user's account exists.
    207      *
    208      * The login name is used for looking up the account.
    209      *
    210      * @param userName The name of the user to be checked.
    211      * @return true if the specified account exists
    212      * @throws DataBackendException if there was an error accessing the data backend.
    213      */
    214     @Override
    215     public boolean accountExists(String userName)
    216             throws DataBackendException
    217     {
    218         return umDelegate.checkExists(userName);
    219     }
    220
    221     /**
    222      * Retrieve a user from persistent storage using username as the
    223      * key.
    224      *
    225      * @param username the name of the user.
    226      * @return an User object.
    227      * @throws UnknownEntityException if the user's record does not
    228      *            exist in the database.
    229      * @throws DataBackendException if there is a problem accessing the
    230      *            storage.
    231      */
    232     @Override
    233     public <U extends User> U retrieve(String username)
    234             throws UnknownEntityException, DataBackendException
    235     {
    236         TurbineUser u = umDelegate.getUser(username);
    237         return wrap(u);
    238     }
    239
    240     /**
    241      * Retrieve a set of users that meet the specified criteria.
    242      *
    243      * As the keys for the criteria, you should use the constants that
    244      * are defined in {@link User} interface, plus the names
    245      * of the custom attributes you added to your user representation
    246      * in the data storage. Use verbatim names of the attributes -
    247      * without table name prefix in case of DB implementation.
    248      *
    249      * @param criteria The criteria of selection.
    250      * @return a List of users meeting the criteria.
    251      * @throws DataBackendException if there is a problem accessing the
    252      *         storage.
    253      */
    254     @Override
    255     public List<? extends User> retrieveList(Object criteria)
    256             throws DataBackendException
    257     {
    258         UserSet<org.apache.fulcrum.security.entity.User> uset = umDelegate.getAllUsers();
    259         List<User> userList = new ArrayList<User>();
    260
    261         for (org.apache.fulcrum.security.entity.User u : uset)
    262         {
    263             TurbineUser tu = (TurbineUser)u;
    264             userList.add(wrap(tu));
    265         }
    266
    267         return userList;
    268     }
    269
    270     /**
    271      * Retrieve a user from persistent storage using username as the
    272      * key, and authenticate the user. The implementation may chose
    273      * to authenticate to the server as the user whose data is being
    274      * retrieved.
    275      *
    276      * @param username the name of the user.
    277      * @param password the user supplied password.
    278      * @return an User object.
    279      * @throws PasswordMismatchException if the supplied password was
    280      *            incorrect.
    281      * @throws UnknownEntityException if the user's record does not
    282      *            exist in the database.
    283      * @throws DataBackendException if there is a problem accessing the
    284      *            storage.
    285      */
    286     @Override
    287     public <U extends User> U retrieve(String username, String password)
    288             throws PasswordMismatchException, UnknownEntityException,
    289             DataBackendException
    290     {
    291         TurbineUser u = umDelegate.getUser(username, password);
    292         return wrap(u);
    293     }
    294
    295     /**
    296      * Save an User object to persistent storage. User's record is
    297      * required to exist in the storage.
    298      *
    299      * @param user an User object to store.
    300      * @throws UnknownEntityException if the user's record does not
    301      *            exist in the database.
    302      * @throws DataBackendException if there is a problem accessing the
    303      *            storage.
    304      */
    305     @Override
    306     public void store(User user)
    307             throws UnknownEntityException, DataBackendException
    308     {
    309         if (user == null) {
    310             throw new UnknownEntityException("user is null");
    311         }
    312         try
    313         {
    314             user.setObjectdata(ObjectUtils.serializeMap(user.getPermStorage()));
    315         }
    316         catch (Exception e)
    317         {
    318             throw new DataBackendException("Could not serialize permanent storage", e);
    319         }
    320
    321         umDelegate.saveUser(((TurbineUserDelegate)user).getUserDelegate());
    322     }
    323
    324     /**
    325      * Saves User data when the session is unbound. The user account is required
    326      * to exist in the storage.
    327      *
    328      * LastLogin, AccessCounter, persistent pull tools, and any data stored
    329      * in the permData hashtable that is not mapped to a column will be saved.
    330      *
    331      * @throws UnknownEntityException if the user's account does not
    332      *            exist in the database.
    333      * @throws DataBackendException if there is a problem accessing the
    334      *            storage.
    335      */
    336     @Override
    337     public void saveOnSessionUnbind(User user)
    338             throws UnknownEntityException, DataBackendException
    339     {
    340         store(user);
    341     }
    342
    343     /**
    344      * Authenticate an User with the specified password. If authentication
    345      * is successful the method returns nothing. If there are any problems,
    346      * exception was thrown.
    347      *
    348      * @param user an User object to authenticate.
    349      * @param password the user supplied password.
    350      * @throws PasswordMismatchException if the supplied password was
    351      *            incorrect.
    352      * @throws UnknownEntityException if the user's record does not
    353      *            exist in the database.
    354      * @throws DataBackendException if there is a problem accessing the
    355      *            storage.
    356      */
    357     @Override
    358     public void authenticate(User user, String password)
    359             throws PasswordMismatchException, UnknownEntityException,
    360             DataBackendException
    361     {
    362         umDelegate.authenticate(user, password);
    363     }
    364
    365     /**
    366      * Creates new user account with specified attributes.
    367      *
    368      * @param user the object describing account to be created.
    369      * @param initialPassword The password to use for the object creation
    370      *
    371      * @throws DataBackendException if there was an error accessing the data backend.
    372      * @throws EntityExistsException if the user account already exists.
    373      */
    374     @Override
    375     public void createAccount(User user, String initialPassword)
    376             throws UnknownEntityException, EntityExistsException, DataBackendException
    377     {
    378         if (user == null) {
    379             throw new UnknownEntityException("user is null");
    380         }
    381         umDelegate.addUser(user.getUserDelegate(), initialPassword);
    382     }
    383
    384     /**
    385      * Removes an user account from the system.
    386      *
    387      * @param user the object describing the account to be removed.
    388      * @throws DataBackendException if there was an error accessing the data backend.
    389      * @throws UnknownEntityException if the user account is not present.
    390      */
    391     @Override
    392     public void removeAccount(User user)
    393             throws UnknownEntityException, DataBackendException
    394     {
    395         if (user == null) {
    396             throw new UnknownEntityException("user is null");
    397         }
    398         umDelegate.removeUser(user.getUserDelegate());
    399     }
    400
    401     /**
    402      * Change the password for an User.
    403      *
    404      * @param user an User to change password for.
    405      * @param oldPassword the current password supplied by the user.
    406      * @param newPassword the current password requested by the user.
    407      * @throws PasswordMismatchException if the supplied password was
    408      *            incorrect.
    409      * @throws UnknownEntityException if the user's record does not
    410      *            exist in the database.
    411      * @throws DataBackendException if there is a problem accessing the
    412      *            storage.
    413      */
    414     @Override
    415     public void changePassword(User user, String oldPassword,
    416                                String newPassword)
    417             throws PasswordMismatchException, UnknownEntityException,
    418             DataBackendException
    419     {
    420         if (user == null) {
    421             throw new UnknownEntityException("user is null");
    422         }
    423         umDelegate.changePassword(
    424                 ((TurbineUserDelegate)user).getUserDelegate(),
    425                 oldPassword, newPassword);
    426     }
    427
    428     /**
    429      * Forcibly sets new password for an User.
    430      *
    431      * This is supposed by the administrator to change the forgotten or
    432      * compromised passwords. Certain implementations of this feature
    433      * would require administrative level access to the authenticating
    434      * server / program.
    435      *
    436      * @param user an User to change password for.
    437      * @param password the new password.
    438      * @throws UnknownEntityException if the user's record does not
    439      *            exist in the database.
    440      * @throws DataBackendException if there is a problem accessing the
    441      *            storage.
    442      */
    443     @Override
    444     public void forcePassword(User user, String password)
    445             throws UnknownEntityException, DataBackendException
    446     {
    447         if (user == null) {
    448             throw new UnknownEntityException("user is null");
    449         }
    450         umDelegate.forcePassword(user.getUserDelegate(), password);
    451     }
    452
    453     /**
    454      * Constructs an User object to represent an anonymous user of the
    455      * application.
    456      *
    457      * @return An anonymous Turbine User.
    458      * @throws UnknownEntityException
    459      *             if the anonymous User object couldn't be constructed.
    460      */
    461     @Override
    462     public <U extends User> U getAnonymousUser() throws UnknownEntityException
    463     {
    464         TurbineUser u = umDelegate.getAnonymousUser();
    465         return wrap(u);
    466     }
    467
    468     /**
    469      * Checks whether a passed user object matches the anonymous user pattern
    470      * according to the configured user manager
    471      *
    472      * @param u a user object
    473      *
    474      * @return True if this is an anonymous user
    475      *
    476      */
    477     @Override
    478     public boolean isAnonymousUser(User u)
    479     {
    480         return umDelegate.isAnonymousUser(u);
    481     }
    482
    483     /**
    484      * Construct a blank User object.
    485      *
    486      * This method calls getUserClass, and then creates a new object using the
    487      * default constructor.
    488      *
    489      * @return an object implementing User interface.
    490      * @throws DataBackendException
    491      *             if the object could not be instantiated.
    492      */
    493     @Override
    494     public <U extends User> U getUserInstance() throws DataBackendException
    495     {
    496         TurbineUser u = umDelegate.getUserInstance();
    497         return wrap(u);
    498     }
    499
    500     /**
    501      * Construct a blank User object.
    502      *
    503      * This method calls getUserClass, and then creates a new object using the
    504      * default constructor.
    505      *
    506      * @param userName
    507      *            The name of the user.
    508      *
    509      * @return an object implementing User interface.
    510      * @throws DataBackendException
    511      *             if the object could not be instantiated.
    512      */
    513     @Override
    514     public <U extends User> U getUserInstance(String userName) throws DataBackendException
    515     {
    516         TurbineUser u = umDelegate.getUserInstance(userName);
    517         return wrap(u);
    518     }
    519
    520     /**
    521      * Return a Class object representing the system's chosen implementation of
    522      * of ACL interface.
    523      *
    524      * @return systems's chosen implementation of ACL interface.
    525      * @throws UnknownEntityException
    526      *             if the implementation of ACL interface could not be
    527      *             determined, or does not exist.
    528      */
    529     @Override
    530     public <A extends AccessControlList> A getACL(User user) throws UnknownEntityException
    531     {
    532         if (user == null) {
    533             throw new UnknownEntityException("user is null");
    534         }
    535         return umDelegate.getACL(user.getUserDelegate());
    536     }
    537 }