You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@turbine.apache.org by ep...@apache.org on 2003/08/24 00:02:04 UTC

cvs commit: jakarta-turbine-fulcrum/security/src/java/org/apache/fulcrum/security/spi/memory/simple MemoryUserManagerImpl.java MemoryPermissionManagerImpl.java MemoryRoleManagerImpl.java MemoryGroupManagerImpl.java

epugh       2003/08/23 15:02:04

  Added:       security/src/java/org/apache/fulcrum/security/spi/memory/simple
                        MemoryUserManagerImpl.java
                        MemoryPermissionManagerImpl.java
                        MemoryRoleManagerImpl.java
                        MemoryGroupManagerImpl.java
  Log:
  
  
  Revision  Changes    Path
  1.1                  jakarta-turbine-fulcrum/security/src/java/org/apache/fulcrum/security/spi/memory/simple/MemoryUserManagerImpl.java
  
  Index: MemoryUserManagerImpl.java
  ===================================================================
  package org.apache.fulcrum.security.spi.memory.simple;
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Turbine" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.Composable;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.commons.lang.StringUtils;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.fulcrum.factory.FactoryService;
  import org.apache.fulcrum.security.GroupManager;
  import org.apache.fulcrum.security.RoleManager;
  import org.apache.fulcrum.security.acl.AccessControlList;
  import org.apache.fulcrum.security.acl.DefaultAccessControlList;
  import org.apache.fulcrum.security.entity.Group;
  import org.apache.fulcrum.security.entity.Role;
  import org.apache.fulcrum.security.entity.User;
  import org.apache.fulcrum.security.model.simple.entity.SimpleGroup;
  import org.apache.fulcrum.security.model.simple.entity.SimpleRole;
  import org.apache.fulcrum.security.model.simple.entity.SimpleUser;
  import org.apache.fulcrum.security.model.simple.manager.*;
  import org.apache.fulcrum.security.util.DataBackendException;
  import org.apache.fulcrum.security.util.EntityExistsException;
  import org.apache.fulcrum.security.util.GroupSet;
  import org.apache.fulcrum.security.util.PasswordMismatchException;
  import org.apache.fulcrum.security.util.RoleSet;
  import org.apache.fulcrum.security.util.UnknownEntityException;
  /**
   * This implementation keeps all objects in memory.  This is mostly meant to help
   * with testing and prototyping of ideas.
   *
   * @todo Need to load up Crypto component and actually encrypt passwords!
   * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
   * @version $Id: MemoryUserManagerImpl.java,v 1.1 2003/08/23 22:02:04 epugh Exp $
   */
  public class MemoryUserManagerImpl extends AbstractLogEnabled implements SimpleUserManager, Composable
  {
      /** Logging */
      private static Log log = LogFactory.getLog(MemoryUserManagerImpl.class);
      private static List users = new ArrayList();
      
      /** A factory to construct ACL Objects */
      private FactoryService aclFactoryService = null;
      private ComponentManager manager = null;
      /** Our groupManager **/
      private GroupManager groupManager;
      /** Our roleManager **/
      private RoleManager roleManager;
      /** Our Unique ID counter */
      private static int uniqueId = 0;
      /**
       * @return
       */
      private GroupManager getGroupManager() throws ComponentException
      {
          if (groupManager == null)
          {
              groupManager = (GroupManager) manager.lookup(GroupManager.ROLE);
          }
          return groupManager;
      }
      /**
      	* @return
      	*/
  	private RoleManager getRoleManager() throws ComponentException
      {
          if (roleManager == null)
          {
              roleManager = (RoleManager) manager.lookup(RoleManager.ROLE);
          }
          return roleManager;
      }
      /**
       * Check whether a specified user's account exists.
       *
       * The login name is used for looking up the account.
       *
       * @param user The user to be checked.
       * @return true if the specified account exists
       * @throws DataBackendException if there was an error accessing
       *         the data backend.
       */
      public boolean checkExists(User user) throws DataBackendException
      {
          boolean exists = false;
          for (Iterator i = users.iterator(); i.hasNext();)
          {
              User u = (User) i.next();
              if (u.getName().equalsIgnoreCase(user.getName()) | u.getId() == user.getId())
              {
                  exists = true;
              }
          }
          return exists;
      }
      /**
       * Check whether a specified user's account exists.
       *
       * The login name is used for looking up the account.
       *
       * @param userName The name of the user to be checked.
       * @return true if the specified account exists
       * @throws DataBackendException if there was an error accessing
       *         the data backend.
       */
      public boolean checkExists(String userName) throws DataBackendException
      {
          List tempUsers = new ArrayList();
          for (Iterator i = users.iterator(); i.hasNext();)
          {
              User user = (User) i.next();
              if (user.getName().equalsIgnoreCase(userName))
              {
                  tempUsers.add(user);
              }
          }
          if (tempUsers.size() > 1)
          {
              throw new DataBackendException("Multiple Users with same username '" + userName + "'");
          }
          return (tempUsers.size() == 1);
      }
      /**
       * Retrieve a user from persistent storage using username as the
       * key.
       *
       * @param userName the name of the user.
       * @return an User object.
       * @exception UnknownEntityException if the user's account does not
       *            exist in the database.
       * @exception DataBackendException if there is a problem accessing the
       *            storage.
       */
      public User getUser(String userName) throws UnknownEntityException, DataBackendException
      {
          List tempUsers = new ArrayList();
          for (Iterator i = users.iterator(); i.hasNext();)
          {
              User user = (User) i.next();
              if (user.getName().equalsIgnoreCase(userName))
              {
                  tempUsers.add(user);
              }
          }
          if (tempUsers.size() > 1)
          {
              throw new DataBackendException("Multiple Users with same username '" + userName + "'");
          }
          if (tempUsers.size() == 1)
          {
              return (User) tempUsers.get(0);
          }
          throw new UnknownEntityException("Unknown user '" + userName + "'");
      }
      /**
       * Retrieve a user from persistent storage using username as the
       * key, and authenticate the user. The implementation may chose
       * to authenticate to the server as the user whose data is being
       * retrieved.
       *
       * @param userName the name of the user.
       * @param password the user supplied password.
       * @return an User object.
       * @exception PasswordMismatchException if the supplied password was
       *            incorrect.
       * @exception UnknownEntityException if the user's account does not
       *            exist in the database.
       * @exception DataBackendException if there is a problem accessing the
       *            storage.
       */
      public User getUser(String userName, String password)
          throws PasswordMismatchException, UnknownEntityException, DataBackendException
      {
          User user = getUser(userName);
          authenticate(user, password);
          return user;
      }
      /**
       * Authenticate an User with the specified password. If authentication
       * is successful the method returns nothing. If there are any problems,
       * exception was thrown.
       *
       * @param user an User object to authenticate.
       * @param password the user supplied password.
       * @exception PasswordMismatchException if the supplied password was
       *            incorrect.
       * @exception UnknownEntityException if the user's account does not
       *            exist in the database.
       * @exception DataBackendException if there is a problem accessing the
       *            storage.
       */
      public void authenticate(User user, String password)
          throws PasswordMismatchException, UnknownEntityException, DataBackendException
      {
          if (!checkExists(user))
          {
              throw new UnknownEntityException("The account '" + user.getName() + "' does not exist");
          }
          // log.debug("Supplied Pass: " + password);
          // log.debug("User Pass: " + user.getPassword());
          /*
           * Unix crypt needs the existing, encrypted password text as
           * salt for checking the supplied password. So we supply it
           * into the checkPassword routine
           */
          if (!password.equals(user.getPassword()))
          {
              throw new PasswordMismatchException("The passwords do not match");
          }
      }
      /**
       * Change the password for an User. The user must have supplied the
       * old password to allow the change.
       *
       * @param user an User to change password for.
       * @param oldPassword The old password to verify
       * @param newPassword The new password to set
       * @exception PasswordMismatchException if the supplied password was
       *            incorrect.
       * @exception UnknownEntityException if the user's account does not
       *            exist in the database.
       * @exception DataBackendException if there is a problem accessing the
       *            storage.
       */
      public void changePassword(User user, String oldPassword, String newPassword)
          throws PasswordMismatchException, UnknownEntityException, DataBackendException
      {
          if (!checkExists(user))
          {
              throw new UnknownEntityException("The account '" + user.getName() + "' does not exist");
          }
          if (!oldPassword.equals(user.getPassword()))
          {
              throw new PasswordMismatchException("The supplied old password for '" + user.getName() + "' was incorrect");
          }
          user.setPassword(newPassword);
          // save the changes in the database imediately, to prevent the password
          // being 'reverted' to the old value if the user data is lost somehow
          // before it is saved at session's expiry.
          saveUser(user);
      }
      /**
       * Forcibly sets new password for an User.
       *
       * This is supposed by the administrator to change the forgotten or
       * compromised passwords. Certain implementatations of this feature
       * would require administrative level access to the authenticating
       * server / program.
       *
       * @param user an User to change password for.
       * @param password the new password.
       * @exception UnknownEntityException if the user's record does not
       *            exist in the database.
       * @exception DataBackendException if there is a problem accessing the
       *            storage.
       */
      public void forcePassword(User user, String password) throws UnknownEntityException, DataBackendException
      {
          if (!checkExists(user))
          {
              throw new UnknownEntityException("The account '" + user.getName() + "' does not exist");
          }
          user.setPassword(password);
          // save the changes in the database immediately, to prevent the
          // password being 'reverted' to the old value if the user data
          // is lost somehow before it is saved at session's expiry.
          saveUser(user);
      }
      /**
       * Creates new user account with specified attributes.
       *
       * @param user The object describing account to be created.
       * @param initialPassword the password for the new account
       * @throws DataBackendException if there was an error accessing
       the data backend.
       * @throws EntityExistsException if the user account already exists.
       */
      public void createAccount(User user, String initialPassword) throws EntityExistsException, DataBackendException
      {
          if (StringUtils.isEmpty(user.getName()))
          {
              throw new DataBackendException("Could not create " + "an user with empty name!");
          }
          if (checkExists(user))
          {
              throw new EntityExistsException("The account '" + user.getName() + "' already exists");
          }
          user.setPassword(initialPassword);
          try
          {
              users.remove(user);
              user.setId(getUniqueId());
              users.add(user);
          }
          catch (Exception e)
          {
              throw new DataBackendException("Failed to create account '" + user.getName() + "'", e);
          }
      }
      /**
       * Construct a blank User object.
       *
       * This method calls getUserClass, and then creates a new object using
       * the default constructor.
       *
       * @return an object implementing User interface.
       * @throws UnknownEntityException if the object could not be instantiated.
       */
      public User getUserInstance() throws UnknownEntityException
      {
          User user;
          try
          {
              user = (User) new SimpleUser();
          }
          catch (Exception e)
          {
              throw new UnknownEntityException("Failed instantiate an User implementation object", e);
          }
          return user;
      }
      /**
       * Construct a blank User object.
       *
       * This method calls getUserClass, and then creates a new object using
       * the default constructor.
       *
       * @param userName The name of the user.
       *
       * @return an object implementing User interface.
       *
       * @throws UnknownEntityException if the object could not be instantiated.
       */
      public User getUserInstance(String userName) throws UnknownEntityException
      {
          User user = getUserInstance();
          user.setName(userName);
          return user;
      }
      /**
      	 * Revokes all groups from a user
      	 *
      	 * This method is used when deleting an account.
      	 *
      	 * @param user the User.
      	 * @throws DataBackendException if there was an error accessing the data
      	 *         backend.
      	 * @throws UnknownEntityException if the account is not present.
      	 */
      public synchronized void revokeAll(User user) throws DataBackendException, UnknownEntityException
      {
          boolean userExists = false;
          try
          {
              userExists = checkExists(user);
              if (userExists)
              {
                  ((SimpleUser) user).setGroups(new GroupSet());
                  return;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("revokeAll(User) failed", e);
          }
          finally
          {
          }
          throw new UnknownEntityException("Unknown user '" + user.getName() + "'");
      }
      /*-----------------------------------------------------------------------
      	 Security management
      	 -----------------------------------------------------------------------*/
      /**
      	* Grant an User a Role in a Group.
      	*
      	* @param user the user.
      	* @param group the group.
      	* @param role the role.
      	* @throws DataBackendException if there was an error accessing the data
      	*         backend.
      	* @throws UnknownEntityException if user account, group or role is not
      	*         present.
      	*/
      /* public synchronized void grant(User user, Group group, Role role)
           throws DataBackendException, UnknownEntityException
       {
           boolean userExists = false;
           boolean groupExists = false;
           boolean roleExists = false;
           try
           {
               userExists = checkExists(user);
               groupExists = checkExists(group);
               roleExists = checkExists(role);
               if (userExists && groupExists && roleExists)
               {
                   ((SimpleUser) user).addGroup(group);
                   ((SimpleUser) user).addRole(role);
                   return;
               }
           }
           catch (Exception e)
           {
               throw new DataBackendException("grant(User,Group,Role) failed", e);
           }
           finally
           {
           }
           if (!userExists)
           {
               throw new UnknownEntityException("Unknown user '" + user.getName() + "'");
           }
           if (!groupExists)
           {
               throw new UnknownEntityException("Unknown group '" + group.getName() + "'");
           }
           if (!roleExists)
           {
               throw new UnknownEntityException("Unknown role '" + role.getName() + "'");
           }
       }
       */
      /**
      	* Revoke a Role in a Group from an User.
      	*
      	* @param user the user.
      	* @param group the group.
      	* @param role the role.
      	* @throws DataBackendException if there was an error accessing the data
      	*         backend.
      	* @throws UnknownEntityException if user account, group or role is not
      	*         present.
      	*/
      /*
       * 
       public synchronized void revoke(User user, Group group, Role role)
          throws DataBackendException, UnknownEntityException
      {
          boolean userExists = false;
          boolean groupExists = false;
          boolean roleExists = false;
          try
          {
              userExists = checkExists(user);
              groupExists = checkExists(group);
              roleExists = checkExists(role);
              if (userExists && groupExists && roleExists)
              {
                  ((SimpleUser) user).getGroups().remove(group);
                  ((SimpleUser) user).getRoles().remove(role);
                  return;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("revoke(User,Role,Group) failed", e);
          }
          finally
          {
          }
          if (!userExists)
          {
              throw new UnknownEntityException("Unknown user '" + user.getName() + "'");
          }
          if (!groupExists)
          {
              throw new UnknownEntityException("Unknown group '" + group.getName() + "'");
          }
          if (!roleExists)
          {
              throw new UnknownEntityException("Unknown role '" + role.getName() + "'");
          }
      }
      */
      /**
      	* Determines if the <code>Group</code> exists in the security system.
      	*
      	* @param group a <code>Group</code> value
      	* @return true if the group exists in the system, false otherwise
      	* @throws DataBackendException when more than one Group with
      	*         the same name exists.
      	* @throws Exception A generic exception.
      	*/
      private boolean checkExists(Group group) throws DataBackendException, Exception
      {
          return getGroupManager().checkExists(group);
      }
      /**
      	* Determines if the <code>Role</code> exists in the security system.
      	*
      	* @param role a <code>Role</code> value
      	* @return true if the role exists in the system, false otherwise
      	* @throws DataBackendException when more than one Role with
      	*         the same name exists.
      	* @throws Exception A generic exception.
      	*/
      private boolean checkExists(Role role) throws DataBackendException, Exception
      {
          return getRoleManager().checkExists(role);
      }
      /**
      	* This method provides client-side encryption of passwords.
      	*
      	* If <code>secure.passwords</code> are enabled in TurbineResources,
      	* the password will be encrypted, if not, it will be returned unchanged.
      	* The <code>secure.passwords.algorithm</code> property can be used
      	* to chose which digest algorithm should be used for performing the
      	* encryption. <code>SHA</code> is used by default.
      	*
      	* @param password the password to process
      	* @return processed password
      	*/
      public String encryptPassword(String password)
      {
          return encryptPassword(password, null);
      }
      /**
      	* This method provides client-side encryption of passwords.
      	*
      	* If <code>secure.passwords</code> are enabled in TurbineResources,
      	* the password will be encrypted, if not, it will be returned unchanged.
      	* The <code>secure.passwords.algorithm</code> property can be used
      	* to chose which digest algorithm should be used for performing the
      	* encryption. <code>SHA</code> is used by default.
      	*
      	* The used algorithms must be prepared to accept null as a
      	* valid parameter for salt. All algorithms in the Fulcrum Cryptoservice
      	* accept this.
      	*
      	* @param password the password to process
      	* @param salt     algorithms that needs a salt can provide one here
      	* @return processed password
      	*/
      public String encryptPassword(String password, String salt)
      {
          //@todo need to tie into password utils.
          return password + salt;
      }
      /**
      	* Checks if a supplied password matches the encrypted password
      	*
      	* @param checkpw      The clear text password supplied by the user
      	* @param encpw        The current, encrypted password
      	*
      	* @return true if the password matches, else false
      	*
      	*/
      public boolean checkPassword(String checkpw, String encpw)
      {
          String result = encryptPassword(checkpw, encpw);
          return (result == null) ? false : result.equals(encpw);
      }
     
      /**
       * Construct a new ACL object.
       *
       * This constructs a new ACL object from the configured class and
       * initializes it with the supplied roles and permissions.
       *
       * @param roles The roles that this ACL should contain
       * @param permissions The permissions for this ACL
       *
       * @return an object implementing ACL interface.
       * @throws UnknownEntityException if the object could not be instantiated.
       */
      public AccessControlList getAclInstance(Map roles, Map permissions) throws UnknownEntityException
      {
          Object[] objects = { roles, permissions };
          String[] signatures = { Map.class.getName(), Map.class.getName()};
          AccessControlList accessControlList;
          try
          {
          	/*
          	 * 
          	 @todo I think this is overkill for now..
              accessControlList =
                  (AccessControlList) aclFactoryService.getInstance(aclClass.getName(), objects, signatures);
                  */
                  accessControlList = new DefaultAccessControlList(roles,permissions);
          }
          catch (Exception e)
          {
              throw new UnknownEntityException("Failed to instantiate an ACL implementation object", e);
          }
          return accessControlList;
      }
      public AccessControlList getACL(User user)
      {
          Map roleSets = new HashMap();
          Map permissionSets = new HashMap();
          for (Iterator i = ((SimpleUser) user).getGroups().iterator(); i.hasNext();)
          {
              Group group = (Group) i.next();
              RoleSet roleSet = (RoleSet) ((SimpleGroup) group).getRoles();
              roleSets.put(group, roleSet);
              for (Iterator j = roleSet.iterator(); j.hasNext();)
              {
                  SimpleRole role = (SimpleRole) j.next();
                  permissionSets.put(role, role.getPermissions());
              }
          }
          try
          {
              return getAclInstance(roleSets, permissionSets);
          }
          catch (UnknownEntityException uue)
          {
              throw new RuntimeException(uue.getMessage(), uue);
          }
      }
      /**
      	* Removes an user account from the system.
      	*
      	* @param user the object describing the account to be removed.
      	* @throws DataBackendException if there was an error accessing the data
      	*         backend.
      	* @throws UnknownEntityException if the user account is not present.
      	*/
      public void removeUser(User user) throws DataBackendException, UnknownEntityException
      {
          // revoke all roles form the user
          revokeAll(user);
          users.remove(user);
      }
      /**
         * Creates new user account with specified attributes.
         *
         * @param user the object describing account to be created.
         * @param password The password to use for the account.
         *
         * @throws DataBackendException if there was an error accessing the
         *         data backend.
         * @throws EntityExistsException if the user account already exists.
         */
      public void addUser(User user, String password) throws DataBackendException, EntityExistsException
      {
          createAccount(user, password);
      }
      /**
         * Stores User attributes. The User is required to exist in the system.
         *
         * @param role The User to be stored.
         * @throws DataBackendException if there was an error accessing the data
         *         backend.
         * @throws UnknownEntityException if the role does not exist.
         */
      public void saveUser(User user) throws DataBackendException, UnknownEntityException
      {
          boolean userExists = false;
          userExists = checkExists(user);
          if (userExists)
          {
              users.remove(user);
              users.add(user);
          }
          else
          {
              throw new UnknownEntityException("Unknown user '" + user + "'");
          }
      }
      /**
       * Puts a user in a group.
       *
       * This method is used when adding a user to a group
       *
       * @param user the User.
       * @throws DataBackendException if there was an error accessing the data
       *         backend.
       * @throws UnknownEntityException if the account is not present.
       */
      public void grant(User user, Group group) throws DataBackendException, UnknownEntityException
      {
          boolean groupExists = false;
          boolean userExists = false;
          try
          {
              groupExists = checkExists(group);
              userExists = checkExists(user);
              if (groupExists && userExists)
              {
                  ((SimpleUser) user).addGroup(group);
                  return;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("grant(Role,Permission) failed", e);
          }
          finally
          {
          }
          if (!groupExists)
          {
              throw new UnknownEntityException("Unknown group '" + group.getName() + "'");
          }
          if (!userExists)
          {
              throw new UnknownEntityException("Unknown user '" + user.getName() + "'");
          }
      }
      /**
      * Removes a user in a group.
      *
      * This method is used when removing a user to a group
      *
      * @param user the User.
      * @throws DataBackendException if there was an error accessing the data
      *         backend.
      * @throws UnknownEntityException if the user or group is not present.
      */
      public void revoke(User user, Group group) throws DataBackendException, UnknownEntityException
      {
          boolean groupExists = false;
          boolean userExists = false;
          try
          {
              groupExists = checkExists(group);
              userExists = checkExists(user);
              if (groupExists && userExists)
              {
                  ((SimpleUser) user).removeGroup(group);
                  return;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("grant(Role,Permission) failed", e);
          }
          finally
          {
          }
          if (!groupExists)
          {
              throw new UnknownEntityException("Unknown group '" + group.getName() + "'");
          }
          if (!userExists)
          {
              throw new UnknownEntityException("Unknown user '" + user.getName() + "'");
          }
      }
      /**
      	  * Avalon component lifecycle method
      	  */
      public void compose(ComponentManager manager) throws ComponentException
      {
          this.manager = manager;
      }
      private int getUniqueId()
      {
          return ++uniqueId;
      }
  }
  
  
  
  1.1                  jakarta-turbine-fulcrum/security/src/java/org/apache/fulcrum/security/spi/memory/simple/MemoryPermissionManagerImpl.java
  
  Index: MemoryPermissionManagerImpl.java
  ===================================================================
  package org.apache.fulcrum.security.spi.memory.simple;
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Turbine" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
  
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.Composable;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.commons.lang.StringUtils;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.fulcrum.security.PermissionManager;
  import org.apache.fulcrum.security.RoleManager;
  import org.apache.fulcrum.security.entity.Permission;
  import org.apache.fulcrum.security.entity.Role;
  import org.apache.fulcrum.security.model.simple.entity.SimplePermission;
  import org.apache.fulcrum.security.util.DataBackendException;
  import org.apache.fulcrum.security.util.EntityExistsException;
  import org.apache.fulcrum.security.util.PermissionSet;
  import org.apache.fulcrum.security.util.UnknownEntityException;
  /**
   * This implementation keeps all objects in memory.  This is mostly meant to help
   * with testing and prototyping of ideas.
   *
   * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
   * @version $Id: MemoryPermissionManagerImpl.java,v 1.1 2003/08/23 22:02:04 epugh Exp $
   */
  public class MemoryPermissionManagerImpl extends AbstractLogEnabled implements PermissionManager, Composable
  {
      /** Logging */
      private static Log log = LogFactory.getLog(MemoryPermissionManagerImpl.class);
      private static List permissions = new ArrayList();
      private ComponentManager manager = null;
      private RoleManager roleManager = null;
      /** Our Unique ID counter */
      private static int uniqueId = 0;
      /**
      	 * @return
      	 */
      RoleManager getRoleManager() throws ComponentException
      {
          if (roleManager == null)
          {
              roleManager = (RoleManager) manager.lookup(RoleManager.ROLE);
          }
          return roleManager;
      }
      /**
       * Construct a blank Permission object.
       *
       * This method calls getPermissionClass, and then creates a new object using
       * the default constructor.
       *
       * @return an object implementing Permission interface.
       * @throws UnknownEntityException if the object could not be instantiated.
       */
      public Permission getPermissionInstance() throws UnknownEntityException
      {
          Permission permission;
          try
          {
              permission = (Permission) new SimplePermission();
          }
          catch (Exception e)
          {
              throw new UnknownEntityException("Failed to instantiate a Permission implementation object", e);
          }
          return permission;
      }
      /**
       * Construct a blank Permission object.
       *
       * This method calls getPermissionClass, and then creates a new object using
       * the default constructor.
       *
       * @param permName The name of the permission.
       *
       * @return an object implementing Permission interface.
       * @throws UnknownEntityException if the object could not be instantiated.
       */
      public Permission getPermissionInstance(String permName) throws UnknownEntityException
      {
          Permission perm = getPermissionInstance();
          perm.setName(permName);
          return perm;
      }
      /**
         * Retrieve a Permission object with specified name.
         *
         * @param name the name of the Permission.
         * @return an object representing the Permission with specified name.
         * @throws DataBackendException if there was an error accessing the
         *         data backend.
         * @throws UnknownEntityException if the permission does not exist.
         */
      public Permission getPermissionByName(String name) throws DataBackendException, UnknownEntityException
      {
          Permission permission = getAllPermissions().getPermissionByName(name);
          if (permission == null)
          {
              throw new UnknownEntityException("The specified permission does not exist");
          }
          return permission;
      }
      /**
       * Retrieve a Permission object with specified Id.
       *
       * @param name the name of the Permission.
       *
       * @return an object representing the Permission with specified name.
       *
       * @throws UnknownEntityException if the permission does not
       *            exist in the database.
       * @throws DataBackendException if there is a problem accessing the
       *            storage.
       */
      public Permission getPermissionById(int id) throws DataBackendException, UnknownEntityException
      {
          Permission permission = getAllPermissions().getPermissionById(id);
          if (permission == null)
          {
              throw new UnknownEntityException("The specified permission does not exist");
          }
          return permission;
      }
      /**
      	* Retrieves all permissions defined in the system.
      	*
      	* @return the names of all roles defined in the system.
      	* @throws DataBackendException if there was an error accessing the
      	*         data backend.
      	*/
      public PermissionSet getAllPermissions() throws DataBackendException
      {
          return new PermissionSet(permissions);
      }
      /**
  	* Renames an existing Permission.
  	*
  	* @param permission The object describing the permission to be renamed.
  	* @param name the new name for the permission.
  	* @throws DataBackendException if there was an error accessing the data
  	*         backend.
  	* @throws UnknownEntityException if the permission does not exist.
  	*/
      public synchronized void renamePermission(Permission permission, String name)
          throws DataBackendException, UnknownEntityException
      {
          boolean permissionExists = false;
          try
          {
              permissionExists = checkExists(permission);
              if (permissionExists)
              {
                  permissions.remove(permission);
                  permission.setName(name);
                  permissions.add(permission);
                  return;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("renamePermission(Permission,name)", e);
          }
          finally
          {
          }
          throw new UnknownEntityException("Unknown permission '" + permission + "'");
      }
      /**
     * Determines if the <code>Permission</code> exists in the security system.
     *
     * @param permission a <code>Permission</code> value
     * @return true if the permission exists in the system, false otherwise
     * @throws DataBackendException when more than one Permission with
     *         the same name exists.
     * @throws Exception A generic exception.
     */
      public boolean checkExists(Permission permission) throws DataBackendException
      {
          boolean exists = false;
          for (Iterator i = permissions.iterator(); i.hasNext();)
          {
              Permission p = (Permission) i.next();
              if (p.getName().equalsIgnoreCase(permission.getName()) | p.getId() == permission.getId())
              {
                  exists = true;
              }
          }
          return exists;
      }
      /**
  	* Stores Permission's attributes. The Permissions is required to exist in
  	* the system.
  	*
  	* @param permission The Permission to be stored.
  	* @throws DataBackendException if there was an error accessing the data
  	*         backend.
  	* @throws UnknownEntityException if the permission does not exist.
  	*/
      public void savePermission(Permission permission) throws DataBackendException, UnknownEntityException
      {
          boolean permissionExists = false;
          try
          {
              permissionExists = checkExists(permission);
              if (permissionExists)
              {
                  permissions.remove(permission);
                  permissions.add(permission);
              }
              else
              {
                  throw new UnknownEntityException("Unknown permission '" + permission + "'");
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("savePermission(Permission) failed", e);
          }
      }
      /**
       * Removes a Permission from the system.
       *
       * @param permission The object describing the permission to be removed.
       * @throws DataBackendException if there was an error accessing the data
       *         backend.
       * @throws UnknownEntityException if the permission does not exist.
       */
      public synchronized void removePermission(Permission permission)
          throws DataBackendException, UnknownEntityException
      {
          boolean permissionExists = false;
          try
          {
              permissionExists = checkExists(permission);
              if (permissionExists)
              {
                  permissions.remove(permission);
              }
              else
              {
                  throw new UnknownEntityException("Unknown permission '" + permission + "'");
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("removePermission(Permission)", e);
          }
          finally
          {
          }
      }
      /**
  	* Creates a new permission with specified attributes.
  	*
  	* @param permission the object describing the permission to be created.
  	* @return a new Permission object that has id set up properly.
  	* @throws DataBackendException if there was an error accessing the data
  	*         backend.
  	* @throws EntityExistsException if the permission already exists.
  	*/
      public synchronized Permission addPermission(Permission permission)
          throws DataBackendException, EntityExistsException
      {
          boolean permissionExists = false;
          if (StringUtils.isEmpty(permission.getName()))
          {
              throw new DataBackendException("Could not create a permission with empty name!");
          }
          if (permission.getId() > 0)
          {
              throw new DataBackendException("Could not create a permission with an id!");
          }
          try
          {
              permissionExists = checkExists(permission);
              if (!permissionExists)
              {
                  permission.setId(getUniqueId());
                  permissions.add(permission);
                  return permission;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("addPermission(Permission) failed", e);
          }
          finally
          {
          }
          // the only way we could get here without return/throw tirggered
          // is that the permissionExists was true.
          throw new EntityExistsException("Permission '" + permission + "' already exists");
      }
      /**
      	 * Retrieves all permissions associated with a role.
      	 *
      	 * @param role the role name, for which the permissions are to be retrieved.
      	 * @return A Permission set for the Role.
      	 * @throws DataBackendException if there was an error accessing the data
      	 *         backend.
      	 * @throws UnknownEntityException if the role is not present.
      	 */
      public PermissionSet getPermissions(Role role) throws DataBackendException, UnknownEntityException
      {
          boolean roleExists = false;
          try
          {
              roleExists = checkExists(role);
              if (roleExists)
              {
                  return role.getPermissions();
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("getPermissions(Role) failed", e);
          }
          finally
          {
          }
          throw new UnknownEntityException("Unknown role '" + role.getName() + "'");
      }
      /**
      	* Determines if the <code>Role</code> exists in the security system.
      	*
      	* @param role a <code>Role</code> value
      	* @return true if the role exists in the system, false otherwise
      	* @throws DataBackendException when more than one Role with
      	*         the same name exists.
      	* @throws Exception A generic exception.
      	*/
      public boolean checkExists(Role role) throws DataBackendException
      {
          try
          {
              return getRoleManager().checkExists(role);
          }
          catch (ComponentException ce)
          {
              throw new DataBackendException("Problem accessing role manager", ce);
          }
      }
      /**
      	  * Avalon component lifecycle method
      	  */
      public void compose(ComponentManager manager) throws ComponentException
      {
          this.manager = manager;
      }
      private int getUniqueId()
      {
          return ++uniqueId;
      }
  }
  
  
  
  1.1                  jakarta-turbine-fulcrum/security/src/java/org/apache/fulcrum/security/spi/memory/simple/MemoryRoleManagerImpl.java
  
  Index: MemoryRoleManagerImpl.java
  ===================================================================
  package org.apache.fulcrum.security.spi.memory.simple;
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Turbine" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
  
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.Composable;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.commons.lang.StringUtils;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.fulcrum.security.PermissionManager;
  import org.apache.fulcrum.security.entity.Permission;
  import org.apache.fulcrum.security.entity.Role;
  import org.apache.fulcrum.security.model.simple.entity.SimpleRole;
  import org.apache.fulcrum.security.model.simple.manager.*;
  import org.apache.fulcrum.security.util.DataBackendException;
  import org.apache.fulcrum.security.util.EntityExistsException;
  import org.apache.fulcrum.security.util.PermissionSet;
  import org.apache.fulcrum.security.util.RoleSet;
  import org.apache.fulcrum.security.util.UnknownEntityException;
  /**
   *
   * This implementation keeps all objects in memory.  This is mostly meant to help
   * with testing and prototyping of ideas.
   *
   * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
   * @version $Id: MemoryRoleManagerImpl.java,v 1.1 2003/08/23 22:02:04 epugh Exp $
   */
  public class MemoryRoleManagerImpl extends AbstractLogEnabled implements SimpleRoleManager, Composable
  {
      boolean composed = false;
      /** Logging */
      private static Log log = LogFactory.getLog(MemoryRoleManagerImpl.class);
      /** List to store all our roles in */
      private static List roles = new ArrayList();
      private ComponentManager manager = null;
      /** Our permissionManager **/
      private PermissionManager permissionManager;
      /** Our Unique ID counter */
      private static int uniqueId = 0;
      /**
       * @return
       */
      PermissionManager getPermissionManager() throws ComponentException
      {
          if (permissionManager == null)
          {
              permissionManager = (PermissionManager) manager.lookup(PermissionManager.ROLE);
          }
          return permissionManager;
      }
      /**
      	* Construct a blank Role object.
      	*
      	* This method calls getRoleClass, and then creates a new object using
      	* the default constructor.
      	*
      	* @return an object implementing Role interface.
      	* @throws UnknownEntityException if the object could not be instantiated.
      	*/
      public Role getRoleInstance() throws UnknownEntityException
      {
          Role role;
          try
          {
              role = (Role) new SimpleRole();
          }
          catch (Exception e)
          {
              throw new UnknownEntityException("Failed to instantiate a Role implementation object", e);
          }
          return role;
      }
      /**
      	* Construct a blank Role object.
      	*
      	* This method calls getRoleClass, and then creates a new object using
      	* the default constructor.
      	*
      	* @param roleName The name of the role.
      	*
      	* @return an object implementing Role interface.
      	*
      	* @throws UnknownEntityException if the object could not be instantiated.
      	*/
      public Role getRoleInstance(String roleName) throws UnknownEntityException
      {
          Role role = getRoleInstance();
          role.setName(roleName);
          return role;
      }
      /**
      	* Retrieve a Role object with specified name.
      	*
      	* @param name the name of the Role.
      	* @return an object representing the Role with specified name.
      	* @throws DataBackendException if there was an error accessing the
      	*         data backend.
      	* @throws UnknownEntityException if the role does not exist.
      	*/
      public Role getRoleByName(String name) throws DataBackendException, UnknownEntityException
      {
          Role role = getAllRoles().getRoleByName(name);
          if (role == null)
          {
              throw new UnknownEntityException("The specified role does not exist");
          }
          role.setPermissions(getPermissions(role));
          return role;
      }
      /**
      	* Retrieve a Role object with specified Id.
      	*
      	* @param name the name of the Role.
      	*
      	* @return an object representing the Role with specified name.
      	*
      	* @throws UnknownEntityException if the permission does not
      	*            exist in the database.
      	* @throws DataBackendException if there is a problem accessing the
      	*            storage.
      	*/
      public Role getRoleById(int id) throws DataBackendException, UnknownEntityException
      {
          Role role = getAllRoles().getRoleById(id);
          if (role == null)
          {
              throw new UnknownEntityException("The specified role does not exist");
          }
          role.setPermissions(getPermissions(role));
          return role;
      }
      /**
      	* Grants a Role a Permission
      	*
      	* @param role the Role.
      	* @param permission the Permission.
      	* @throws DataBackendException if there was an error accessing the data
      	*         backend.
      	* @throws UnknownEntityException if role or permission is not present.
      	*/
      public synchronized void grant(Role role, Permission permission)
          throws DataBackendException, UnknownEntityException
      {
          boolean roleExists = false;
          boolean permissionExists = false;
          try
          {
              roleExists = checkExists(role);
              permissionExists = checkExists(permission);
              if (roleExists && permissionExists)
              {
                  ((SimpleRole) role).addPermission(permission);
                  return;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("grant(Role,Permission) failed", e);
          }
         
          if (!roleExists)
          {
              throw new UnknownEntityException("Unknown role '" + role.getName() + "'");
          }
          if (!permissionExists)
          {
              throw new UnknownEntityException("Unknown permission '" + permission.getName() + "'");
          }
      }
      /**
      	* Revokes a Permission from a Role.
      	*
      	* @param role the Role.
      	* @param permission the Permission.
      	* @throws DataBackendException if there was an error accessing the data
      	*         backend.
      	* @throws UnknownEntityException if role or permission is not present.
      	*/
      public synchronized void revoke(Role role, Permission permission)
          throws DataBackendException, UnknownEntityException
      {
          boolean roleExists = false;
          boolean permissionExists = false;
          try
          {
              roleExists = checkExists(role);
              permissionExists = checkExists(permission);
              if (roleExists && permissionExists)
              {
                  ((SimpleRole) role).removePermission(permission);
                  return;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("revoke(Role,Permission) failed", e);
          }
          finally
          {
          }
          if (!roleExists)
          {
              throw new UnknownEntityException("Unknown role '" + role.getName() + "'");
          }
          if (!permissionExists)
          {
              throw new UnknownEntityException("Unknown permission '" + permission.getName() + "'");
          }
      }
      /**
      	* Revokes all permissions from a Role.
      	*
      	* This method is user when deleting a Role.
      	*
      	* @param role the Role
      	* @throws DataBackendException if there was an error accessing the data
      	*         backend.
      	* @throws UnknownEntityException if the Role is not present.
      	*/
      public synchronized void revokeAll(Role role) throws DataBackendException, UnknownEntityException
      {
          boolean roleExists = false;
          try
          {
              roleExists = checkExists(role);
              if (roleExists)
              {
                  role.setPermissions(new PermissionSet());
                  return;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("revokeAll(Role) failed", e);
          }
          finally
          {
          }
          throw new UnknownEntityException("Unknown role '" + role.getName() + "'");
      }
      /**
      	* Renames an existing Role.
      	*
      	* @param role The object describing the role to be renamed.
      	* @param name the new name for the role.
      	* @throws DataBackendException if there was an error accessing the data
      	*         backend.
      	* @throws UnknownEntityException if the role does not exist.
      	*/
      public synchronized void renameRole(Role role, String name) throws DataBackendException, UnknownEntityException
      {
          boolean roleExists = false;
          try
          {
              roleExists = checkExists(role);
              if (roleExists)
              {
                  roles.remove(role);
                  role.setName(name);
                  roles.add(role);
                  return;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("renameRole(Role,String)", e);
          }
          finally
          {
          }
          throw new UnknownEntityException("Unknown role '" + role + "'");
      }
      /**
        * Determines if the <code>Role</code> exists in the security system.
        *
        * @param role a <code>Role</code> value
        * @return true if the role exists in the system, false otherwise
        * @throws DataBackendException when more than one Role with
        *         the same name exists.
        * @throws Exception A generic exception.
        */
      public boolean checkExists(Role role) throws DataBackendException
      {
          boolean exists = false;
          for (Iterator i = roles.iterator(); i.hasNext();)
          {
              Role r = (Role) i.next();
              if (r.getName().equalsIgnoreCase(role.getName()) | r.getId() == role.getId())
              {
                  exists = true;
              }
          }
          return exists;
      }
      /**
      		 * Retrieves all roles defined in the system.
      		 *
      		 * @return the names of all roles defined in the system.
      		 * @throws DataBackendException if there was an error accessing the
      		 *         data backend.
      		 */
      public RoleSet getAllRoles() throws DataBackendException
      {
          return new RoleSet(roles);
      }
      /**
      	 * Retrieves all permissions associated with a role.
      	 *
      	 * @param role the role name, for which the permissions are to be retrieved.
      	 * @return A Permission set for the Role.
      	 * @throws DataBackendException if there was an error accessing the data
      	 *         backend.
      	 * @throws UnknownEntityException if the role is not present.
      	 */
      public PermissionSet getPermissions(Role role) throws DataBackendException, UnknownEntityException
      {
          boolean roleExists = false;
          try
          {
              roleExists = checkExists(role);
              if (roleExists)
              {
                  return getPermissionManager().getPermissions(role);
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("getPermissions(Role) failed", e);
          }
          finally
          {
          }
          throw new UnknownEntityException("Unknown role '" + role.getName() + "'");
      }
      /**
  	 * 	 if the <code>Permission</code> exists in the security system.
  	 *
  	 * @param permission a <code>Permission</code> value
  	 * @return true if the permission exists in the system, false otherwise
  	 * @throws DataBackendException when more than one Permission with
  	 *         the same name exists.
  	 * @throws Exception A generic exception.
  	 */
      public boolean checkExists(Permission permission) throws DataBackendException
      {
          try
          {
              return getPermissionManager().checkExists(permission);
          }
          catch (ComponentException ce)
          {
              throw new DataBackendException("Problem getting permission manager", ce);
          }
      }
      /**
      	* Creates a new role with specified attributes.
      	*
      	* @param role the object describing the role to be created.
      	* @return a new Role object that has id set up properly.
      	* @throws DataBackendException if there was an error accessing the data
      	*         backend.
      	* @throws EntityExistsException if the role already exists.
      	*/
      public synchronized Role addRole(Role role) throws DataBackendException, EntityExistsException
      {
          boolean roleExists = false;
          if (StringUtils.isEmpty(role.getName()))
          {
              throw new DataBackendException("Could not create a role with empty name!");
          }
          if (role.getId() > 0)
          {
              throw new DataBackendException("Could not create a role with an id!");
          }
          try
          {
              roleExists = checkExists(role);
              if (!roleExists)
              {
                  role.setId(getUniqueId());
                  roles.add(role);
                  // add the role to system-wide cache
                  getAllRoles().add(role);
                  // return the object with correct id
                  return role;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("addRole(Role) failed", e);
          }
          finally
          {
          }
          // the only way we could get here without return/throw tirggered
          // is that the roleExists was true.
          throw new EntityExistsException("Role '" + role + "' already exists");
      }
      /**
         * Stores Role's attributes. The Roles is required to exist in the system.
         *
         * @param role The Role to be stored.
         * @throws DataBackendException if there was an error accessing the data
         *         backend.
         * @throws UnknownEntityException if the role does not exist.
         */
      public void saveRole(Role role) throws DataBackendException, UnknownEntityException
      {
          boolean roleExists = false;
          roleExists = checkExists(role);
          if (roleExists)
          {
              roles.add(role);
          }
          else
          {
              throw new UnknownEntityException("Unknown role '" + role + "'");
          }
      }
      /**
      	* Removes a Role from the system.
      	*
      	* @param role The object describing the role to be removed.
      	* @throws DataBackendException if there was an error accessing the data
      	*         backend.
      	* @throws UnknownEntityException if the role does not exist.
      	*/
      public synchronized void removeRole(Role role) throws DataBackendException, UnknownEntityException
      {
          boolean roleExists = false;
          try
          {
              roleExists = checkExists(role);
              if (roleExists)
              {
                  // revoke all permissions from the role to be deleted
                  revokeAll(role);
                  roles.remove(role);
                  getAllRoles().remove(role);
                  return;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("removeRole(Role)", e);
          }
          finally
          {
          }
          throw new UnknownEntityException("Unknown role '" + role + "'");
      }
      /**
     * Avalon component lifecycle method
     */
      public void compose(ComponentManager manager) throws ComponentException
      {
          this.manager = manager;
      }
      private int getUniqueId()
      {
          return ++uniqueId;
      }
  }
  
  
  
  1.1                  jakarta-turbine-fulcrum/security/src/java/org/apache/fulcrum/security/spi/memory/simple/MemoryGroupManagerImpl.java
  
  Index: MemoryGroupManagerImpl.java
  ===================================================================
  package org.apache.fulcrum.security.spi.memory.simple;
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Turbine" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
  
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.Composable;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.commons.lang.StringUtils;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.fulcrum.security.RoleManager;
  import org.apache.fulcrum.security.entity.Group;
  import org.apache.fulcrum.security.entity.Role;
  import org.apache.fulcrum.security.model.simple.entity.SimpleGroup;
  import org.apache.fulcrum.security.model.simple.manager.*;
  import org.apache.fulcrum.security.util.DataBackendException;
  import org.apache.fulcrum.security.util.EntityExistsException;
  import org.apache.fulcrum.security.util.GroupSet;
  import org.apache.fulcrum.security.util.UnknownEntityException;
  /**
   * This implementation keeps all objects in memory.  This is mostly meant to help
   * with testing and prototyping of ideas.
   *
   * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
   * @version $Id: MemoryGroupManagerImpl.java,v 1.1 2003/08/23 22:02:04 epugh Exp $
   */
  public class MemoryGroupManagerImpl extends AbstractLogEnabled implements SimpleGroupManager, Composable
  {
      /** Logging */
      private static Log log = LogFactory.getLog(MemoryGroupManagerImpl.class);
      private static List groups = new ArrayList();
      /** Our Unique ID counter */
      private static int uniqueId = 0;
      private ComponentManager manager = null;
      /** Our role Manager **/
      private RoleManager roleManager;
      /**
      	* @return
      	*/
      RoleManager getRoleManager() throws ComponentException
      {
          if (roleManager == null)
          {
              roleManager = (RoleManager) manager.lookup(RoleManager.ROLE);
          }
          return roleManager;
      }
      /**
      	* Construct a blank Group object.
      	*
      	* This method calls getGroupClass, and then creates a new object using
      	* the default constructor.
      	*
      	* @return an object implementing Group interface.
      	* @throws UnknownEntityException if the object could not be instantiated.
      	*/
      public Group getGroupInstance() throws UnknownEntityException
      {
          Group group;
          try
          {
              group = (Group) new SimpleGroup();
          }
          catch (Exception e)
          {
              throw new UnknownEntityException("Failed to instantiate a Group implementation object", e);
          }
          return group;
      }
      /**
      	* Construct a blank Group object.
      	*
      	* This method calls getGroupClass, and then creates a new object using
      	* the default constructor.
      	*
      	* @param groupName The name of the Group
      	*
      	* @return an object implementing Group interface.
      	*
      	* @throws UnknownEntityException if the object could not be instantiated.
      	*/
      public Group getGroupInstance(String groupName) throws UnknownEntityException
      {
          Group group = getGroupInstance();
          group.setName(groupName);
          return group;
      }
      /**
      	 * Retrieve a Group object with specified name.
      	 *
      	 * @param name the name of the Group.
      	 * @return an object representing the Group with specified name.
      	 * @throws DataBackendException if there was an error accessing the
      	 *         data backend.
      	 * @throws UnknownEntityException if the group does not exist.
      	 * @deprecated Use <a href="#getGroupByName">getGroupByName</a> instead.
      	 */
      public Group getGroup(String name) throws DataBackendException, UnknownEntityException
      {
          return getGroupByName(name);
      }
      /**
       * Retrieve a Group object with specified name.
       *
       * @param name the name of the Group.
       * @return an object representing the Group with specified name.
       * @throws DataBackendException if there was an error accessing the
       *         data backend.
       * @throws UnknownEntityException if the group does not exist.
       */
      public Group getGroupByName(String name) throws DataBackendException, UnknownEntityException
      {
          Group group = getAllGroups().getGroupByName(name);
          if (group == null)
          {
              throw new UnknownEntityException("The specified group does not exist");
          }
          return group;
      }
      /**
       * Retrieve a Group object with specified Id.
       *
       * @param name the name of the Group.
       *
       * @return an object representing the Group with specified name.
       *
       * @throws UnknownEntityException if the permission does not
       *            exist in the database.
       * @throws DataBackendException if there is a problem accessing the
       *            storage.
       */
      public Group getGroupById(int id) throws DataBackendException, UnknownEntityException
      {
          Group group = getAllGroups().getGroupById(id);
          if (group == null)
          {
              throw new UnknownEntityException("The specified group does not exist");
          }
          return group;
      }
      /**
      	 * Retrieves all groups defined in the system.
      	 *
      	 * @return the names of all groups defined in the system.
      	 * @throws DataBackendException if there was an error accessing the
      	 *         data backend.
      	 */
      public GroupSet getAllGroups() throws DataBackendException
      {
          return new GroupSet(groups);
      }
      /**
      	* Removes a Group from the system.
      	*
      	* @param group The object describing the group to be removed.
      	* @throws DataBackendException if there was an error accessing the data
      	*         backend.
      	* @throws UnknownEntityException if the group does not exist.
      	*/
      public synchronized void removeGroup(Group group) throws DataBackendException, UnknownEntityException
      {
          boolean groupExists = false;
          try
          {
              groupExists = checkExists(group);
              if (groupExists)
              {
                  groups.remove(group);
                  return;
              }
              else
              {
                  throw new UnknownEntityException("Unknown group '" + group + "'");
              }
          }
          catch (Exception e)
          {
              log.error("Failed to delete a Group");
              log.error(e);
              throw new DataBackendException("removeGroup(Group) failed", e);
          }
          finally
          {
          }
      }
      /**
      	* Renames an existing Group.
      	*
      	* @param group The object describing the group to be renamed.
      	* @param name the new name for the group.
      	* @throws DataBackendException if there was an error accessing the data
      	*         backend.
      	* @throws UnknownEntityException if the group does not exist.
      	*/
      public synchronized void renameGroup(Group group, String name) throws DataBackendException, UnknownEntityException
      {
          boolean groupExists = false;
          try
          {
              groupExists = checkExists(group);
              if (groupExists)
              {
                  groups.remove(group);
                  group.setName(name);
                  groups.add(group);
              }
              else
              {
                  throw new UnknownEntityException("Unknown group '" + group + "'");
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("renameGroup(Group,String)", e);
          }
          finally
          {
          }
      }
      /**
      	* Stores Group's attributes. The Groups is required to exist in the system.
      	*
      	* @param group The Group to be stored.
      	* @throws DataBackendException if there was an error accessing the data
      	*         backend.
      	* @throws UnknownEntityException if the group does not exist.
      	*/
      public void saveGroup(Group group) throws DataBackendException, UnknownEntityException
      {
          boolean groupExists = false;
          try
          {
              groupExists = checkExists(group);
              if (groupExists)
              {
                  groups.remove(group);
                  groups.add(group);
              }
              else
              {
                  throw new UnknownEntityException("Unknown group '" + group + "'");
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("saveGroup(Group) failed", e);
          }
      }
      /**
       * Determines if the <code>Group</code> exists in the security system.
       *
       * @param group a <code>Group</code> value
       * @return true if the group exists in the system, false otherwise
       * @throws DataBackendException when more than one Group with
       *         the same name exists.
       * @throws Exception A generic exception.
       */
      public boolean checkExists(Group group) throws DataBackendException
      {
          try
          {
              boolean exists = false;
              for (Iterator i = groups.iterator(); i.hasNext();)
              {
                  Group g = (Group) i.next();
                  if (g.getName().equalsIgnoreCase(group.getName()) | g.getId() == group.getId())
                  {
                      exists = true;
                  }
              }
              return exists;
              //return groups.contains(group);
          }
          catch (Exception e)
          {
              throw new DataBackendException("Problem checking if groups exists", e);
          }
      }
      /**
      	* Creates a new group with specified attributes.
      	*
      	* @param group the object describing the group to be created.
      	* @return a new Group object that has id set up properly.
      	* @throws DataBackendException if there was an error accessing the data
      	*         backend.
      	* @throws EntityExistsException if the group already exists.
      	*/
      public synchronized Group addGroup(Group group) throws DataBackendException, EntityExistsException
      {
          boolean groupExists = false;
          if (StringUtils.isEmpty(group.getName()))
          {
              throw new DataBackendException("Could not create a group with empty name!");
          }
          if (group.getId() > 0)
          {
              throw new DataBackendException("Could not create a group with an id!");
          }
          groupExists = checkExists(group);
          if (!groupExists)
          {
              group.setId(getUniqueId());
              groups.add(group);
              // return the object with correct id
              return group;
          }
          else
          {
              throw new EntityExistsException("Group '" + group + "' already exists");
          }
      }
      /**
      	  * Grants a Group a Role
      	  *
      	  * @param group the Group.
      	  * @param role the Role.
      	  * @throws DataBackendException if there was an error accessing the data
      	  *         backend.
      	  * @throws UnknownEntityException if group or role is not present.
      	  */
      public synchronized void grant(Group group, Role role) throws DataBackendException, UnknownEntityException
      {
          boolean groupExists = false;
          boolean roleExists = false;
          try
          {
              groupExists = checkExists(group);
              roleExists = checkExists(role);
              if (groupExists && roleExists)
              {
                  ((SimpleGroup) group).addRole(role);
                  return;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("grant(Group,Role) failed", e);
          }
          if (!groupExists)
          {
              throw new UnknownEntityException("Unknown group '" + group.getName() + "'");
          }
          if (!roleExists)
          {
              throw new UnknownEntityException("Unknown role '" + role.getName() + "'");
          }
      }
      /**
      	  * Revokes a Role from a Group.
      	  *
      	  * @param group the Group.
      	  * @param role the Role.
      	  * @throws DataBackendException if there was an error accessing the data
      	  *         backend.
      	  * @throws UnknownEntityException if group or role is not present.
      	  */
      public synchronized void revoke(Group group, Role role) throws DataBackendException, UnknownEntityException
      {
          boolean groupExists = false;
          boolean roleExists = false;
          try
          {
              groupExists = checkExists(group);
              roleExists = checkExists(role);
              if (groupExists && roleExists)
              {
                  ((SimpleGroup) group).removeRole(role);
                  return;
              }
          }
          catch (Exception e)
          {
              throw new DataBackendException("revoke(Group,Role) failed", e);
          }
          finally
          {
          }
          if (!groupExists)
          {
              throw new UnknownEntityException("Unknown group '" + group.getName() + "'");
          }
          if (!roleExists)
          {
              throw new UnknownEntityException("Unknown role '" + role.getName() + "'");
          }
      }
      /**
       * Determines if the <code>Permission</code> exists in the security system.
       *
       * @param permission a <code>Permission</code> value
       * @return true if the permission exists in the system, false otherwise
       * @throws DataBackendException when more than one Permission with
       *         the same name exists.
       * @throws Exception A generic exception.
       */
      public boolean checkExists(Role role) throws DataBackendException
      {
          try
          {
              return getRoleManager().checkExists(role);
          }
          catch (ComponentException ce)
          {
              throw new DataBackendException("Problem getting role manager", ce);
          }
      }
      /**
        * Avalon component lifecycle method
        */
      public void compose(ComponentManager manager) throws ComponentException
      {
          this.manager = manager;
      }
      private int getUniqueId()
      {
          return ++uniqueId;
      }
  }