You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by se...@apache.org on 2001/09/11 06:34:49 UTC

cvs commit: jakarta-james/src/java/org/apache/james/userrepository AbstractJdbcUsersRepository.java DefaultUsersJdbcRepository.java JamesUsersJdbcRepository.java ListUsersJdbcRepository.java AbstractUsersRepository.java UsersJDBCRepository.java

serge       01/09/10 21:34:49

  Modified:    src/java/org/apache/james/userrepository
                        AbstractUsersRepository.java
  Added:       src/java/org/apache/james/userrepository
                        AbstractJdbcUsersRepository.java
                        DefaultUsersJdbcRepository.java
                        JamesUsersJdbcRepository.java
                        ListUsersJdbcRepository.java
  Removed:     src/java/org/apache/james/userrepository
                        UsersJDBCRepository.java
  Log:
  Adding code from userstore branch.
  
  Revision  Changes    Path
  1.2       +25 -50    jakarta-james/src/java/org/apache/james/userrepository/AbstractUsersRepository.java
  
  Index: AbstractUsersRepository.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/src/java/org/apache/james/userrepository/AbstractUsersRepository.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AbstractUsersRepository.java	2001/06/11 09:29:35	1.1
  +++ AbstractUsersRepository.java	2001/09/11 04:34:49	1.2
  @@ -12,7 +12,7 @@
   import org.apache.avalon.framework.logger.AbstractLoggable;
   
   /**
  - * A partial implementation of a Repository to store users on the File System.
  + * A partial implementation of a Repository to store users.
    * <p>This implements common functionality found in different UsersRespository 
    * implementations, and makes it easier to create new User repositories.</p>
    *
  @@ -28,7 +28,7 @@
       //
       /**
        * Returns a list populated with all of the Users in the repository.
  -     * @return an <code>Iterator</code> of <code>JamesUser</code>s.
  +     * @return an <code>Iterator</code> of <code>User</code>s.
        */
       protected abstract Iterator listAllUsers();
   
  @@ -36,31 +36,25 @@
        * Adds a user to the underlying Repository.
        * The user name must not clash with an existing user.
        */
  -    protected abstract void doAddUser(DefaultJamesUser user);
  +    protected abstract void doAddUser(User user);
   
       /**
        * Removes a user from the underlying repository.
        * If the user doesn't exist, returns ok.
        */
  -    protected abstract void doRemoveUser(DefaultJamesUser user);
  +    protected abstract void doRemoveUser(User user);
   
  +    /**
  +     * Updates a user record to match the supplied User.
  +     */
  +    protected abstract void doUpdateUser(User user);
  +
       //
       // Extended protected methods.
       // These provide very basic default implementations, which will work,
       // but may need to be overridden by subclasses for performance reasons.
       //
       /**
  -     * Updates a user record to match the supplied User.
  -     * This is a very basic, remove-then-insert implementation,
  -     * which should really be overridden, but will work.
  -     */
  -    protected void doUpdateUser(DefaultJamesUser user)
  -    {
  -        doRemoveUser(user);
  -        doAddUser(user);
  -    }
  -
  -    /**
        * Produces the complete list of User names, with correct case.
        * @return a <code>List</code> of <code>String</code>s representing
        *         user names.
  @@ -70,7 +64,7 @@
           Iterator users = listAllUsers();
           List userNames = new LinkedList();
           while ( users.hasNext() ) {
  -            JamesUser user = (JamesUser)users.next();
  +            User user = (User)users.next();
               userNames.add(user.getUserName());
           }
   
  @@ -88,7 +82,7 @@
           Iterator users = listAllUsers();
           while ( users.hasNext() ) 
           {
  -            JamesUser user = (JamesUser)users.next();
  +            User user = (User)users.next();
               String username = user.getUserName();
               if (( !ignoreCase && username.equals(name) ) ||
                   ( ignoreCase && username.equalsIgnoreCase(name) )) {
  @@ -100,35 +94,6 @@
       }
   
       //
  -    // User conversion.
  -    //
  -    /**
  -     * This method is hackery to get JamesUser instances, regardless of what 
  -     * user implementation is passed.
  -     * Ideally, the UsersRepository interface would be updated to accept only 
  -     *  JamesUsers, or we could combine the 2.
  -     */
  -    protected DefaultJamesUser getJamesUser(User user)
  -    {
  -        // Return JamesUser instances directly.
  -        if ( user instanceof DefaultJamesUser ) {
  -            return (DefaultJamesUser)user;
  -        }
  -        // Build a JamesUser with a DefaultUser.
  -        else if ( user instanceof DefaultUser ) {
  -            DefaultUser defaultUser = (DefaultUser)user;
  -            return new DefaultJamesUser(defaultUser.getUserName(), 
  -                                        defaultUser.getHashedPassword(), 
  -                                        defaultUser.getHashAlgorithm());
  -        }
  -        // Shouldn't be any other implementations.
  -        else {
  -            throw new RuntimeException("An unknown implementation of User was found. This implementation cannot be persisted to a UsersJDBCRepsitory.");
  -        }
  -
  -    }
  -
  -    //
       // UsersRepository interface implementation.
       //
       /**
  @@ -146,7 +111,7 @@
               return false;
           }
           
  -        doAddUser(getJamesUser(user));
  +        doAddUser(user);
           return true;
       }
   
  @@ -156,7 +121,17 @@
        */
       public void addUser(String name, Object attributes) 
       {
  -        throw new RuntimeException("Improper use of deprecated method - read javadocs");
  +	if (attributes instanceof String)
  +        {
  +	    User newbie = new DefaultUser(name, "SHA");
  +            newbie.setPassword( (String) attributes );
  +	    addUser(newbie);
  +	}
  +        else
  +        {
  +            throw new RuntimeException("Improper use of deprecated method" 
  +                                       + " - use addUser(User user)");
  +        }
       }
   
       /**
  @@ -172,7 +147,7 @@
               return false;
           }
           else {
  -            doUpdateUser(getJamesUser(user));
  +            doUpdateUser(user);
               return true;
           }
       }
  @@ -184,7 +159,7 @@
       {
           User user = getUserByName(name);
           if ( user != null ) {
  -            doRemoveUser(getJamesUser(user));
  +            doRemoveUser(user);
           }
       }
   
  
  
  
  1.1                  jakarta-james/src/java/org/apache/james/userrepository/AbstractJdbcUsersRepository.java
  
  Index: AbstractJdbcUsersRepository.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.userrepository;
  
  import org.apache.james.services.*;
  import org.apache.james.util.SqlResources;
  import org.apache.mailet.MailAddress;
  import org.apache.avalon.framework.*;
  import org.apache.avalon.framework.activity.*;
  import org.apache.avalon.framework.component.*;
  import org.apache.avalon.framework.configuration.*;
  import org.apache.avalon.framework.context.*;
  import org.apache.avalon.framework.logger.*;
  import org.apache.avalon.excalibur.datasource.*;
  import org.apache.avalon.cornerstone.services.datasource.DataSourceSelector;
  
  import java.sql.*;
  import java.util.*;
  import java.io.File;
  
  /**
   * An abstract base class for creating UserRepository implementation
   * which use a database for persistence.
   * 
   * To implement a new UserRepository using by extending this class,
   * you need to implement the 3 abstract methods defined below,
   * and define the required SQL statements in an SQLResources
   * file.
   * 
   * The SQL statements used by this implementation are:
   * <TABLE>
   * <TH><TD><B>Required</B></TD></TH>
   * <TR><TD>select</TD><TD>Select all users.</TD></TR>
   * <TR><TD>insert</TD><TD>Insert a user.</TD></TR>
   * <TR><TD>update</TD><TD>Update a user.</TD></TR>
   * <TR><TD>delete</TD><TD>Delete a user by name.</TD></TR>
   * <TR><TD>createTable</TD><TD>Create the users table.</TD></TR>
   * <TH><TD><B>Optional</B></TD></TH>
   * <TR><TD>selectByLowercaseName</TD><TD>Select a user by name (case-insensitive lowercase).</TD></TR>
   * </TABLE>
   * 
   * @author Darrell DeBoer <dd...@bigdaz.com>
   */
  public abstract class AbstractJdbcUsersRepository extends AbstractUsersRepository
      implements UsersRepository, Loggable, Component, Composable, Configurable, Initializable
  {
      protected Map m_sqlParameters;
      private String m_sqlFileName;
      private String m_datasourceName;
      private DataSourceSelector m_datasources;
      private DataSourceComponent m_datasource;
  
      // Fetches all Users from the db.
      private String m_getUsersSql;
      
      // This fetch a user by name, ensuring case-insensitive matching.
      private String m_userByNameCaseInsensitiveSql;
  
      // Insert, update and delete sql statements are not guaranteed 
      //  to be case-insensitive; this is handled in code.
      private String m_insertUserSql;
      private String m_updateUserSql;
      private String m_deleteUserSql;
  
      // Creates a single table with "username" the Primary Key.
      private String m_createUserTableSql;
  
  
      /**
       * Compose the repository with the DataSourceSelector component.
       */
      public void compose( final ComponentManager componentManager )
          throws ComponentException
      {
          getLogger().debug(this.getClass().getName() + ".compose()");
  
          m_datasources = 
              (DataSourceSelector)componentManager.lookup( DataSourceSelector.ROLE );
      }
  
      /**
       * Configures the UserRepository for JDBC access.
       * 
       * Requires a configuration element in the .conf.xml file of the form:
       * 
       *  <repository name="LocalUsers"
       *              class="org.apache.james.userrepository.JamesUsersJdbcRepository">
       *      <!-- Name of the datasource to use -->
       *      <data-source>MailDb</data-source>
       *      <!-- File to load the SQL definitions from -->
       *      <sqlFile>dist/conf/sqlResources.xml</sqlFile>
       *      <!-- replacement parameters for the sql file -->
       *      <sqlParameters table="JamesUsers"/>
       *  </repository>
       */
      public void configure(Configuration configuration) throws ConfigurationException 
      {
          getLogger().debug(this.getClass().getName() +  ".configure()");
  
          // Parse the DestinationURL for the name of the datasource, 
          // the table to use, and the (optional) repository Key.
          String destUrl = configuration.getAttribute("destinationURL");
          // normalise the destination, to simplify processing.
          if ( ! destUrl.endsWith("/") ) {
              destUrl += "/";
          }
          // Split on "/", starting after "db://"
          List urlParams = new LinkedList();
          int start = 5;
          int end = destUrl.indexOf('/', start);
          while ( end > -1 ) {
              urlParams.add(destUrl.substring(start, end));
              start = end + 1;
              end = destUrl.indexOf('/', start);
          }
  
          // Build SqlParameters and get datasource name from URL parameters
          m_sqlParameters = new HashMap();
          switch ( urlParams.size() ) {
          case 3:
              m_sqlParameters.put("key", urlParams.get(2));
          case 2:
              m_sqlParameters.put("table", urlParams.get(1));
          case 1:
              m_datasourceName = (String)urlParams.get(0);
              break;
          default:
              throw new ConfigurationException
                  ("Malformed destinationURL - " +
                   "Must be of the format \"db://<data-source>[/<table>[/<key>]]\".");
          }
  
          getLogger().debug("Parsed URL: table = '" + m_sqlParameters.get("table") + 
                            "', key = '" + m_sqlParameters.get("key") + "'");
          
          // Get the SQL file location
          m_sqlFileName = configuration.getChild("sqlFile", true).getValue();
  
          // Get other sql parameters from the configuration object,
          // if any.
          Configuration sqlParamsConfig = configuration.getChild("sqlParameters");
          String[] paramNames = sqlParamsConfig.getAttributeNames();
          for (int i = 0; i < paramNames.length; i++ ) {
              String paramName = paramNames[i];
              String paramValue = sqlParamsConfig.getAttribute(paramName);
              m_sqlParameters.put(paramName, paramValue);
          }
      }
  
      /**
       * Initialises the JDBC repository.
       * 1) Tests the connection to the database.
       * 2) Loads SQL strings from the SQL definition file,
       *     choosing the appropriate SQL for this connection, 
       *     and performing paramter substitution,
       * 3) Initialises the database with the required tables, if necessary.
       * 
       */
      public void initialize() throws Exception 
      {
          getLogger().debug( this.getClass().getName() + ".initialize()");
  
          // Get the data-source required.
          m_datasource = (DataSourceComponent)m_datasources.select(m_datasourceName);
  
          // Test the connection to the database, by getting the DatabaseMetaData.
          Connection conn = openConnection();
          try{
              DatabaseMetaData dbMetaData = conn.getMetaData();
  
              // Initialise the sql strings.
              java.io.File sqlFile = new java.io.File(m_sqlFileName);
              
              getLogger().debug("Reading SQL resources from file: " + 
                                sqlFile.getAbsolutePath() + ", section " +
                                this.getClass().getName() + ".");
  
              SqlResources sqlStatements = new SqlResources();
              sqlStatements.init(sqlFile, this.getClass().getName(), 
                                 conn, m_sqlParameters);
  
              // Create the SQL Strings to use for this table.
              // Fetches all Users from the db.
              m_getUsersSql = sqlStatements.getSqlString("select", true);
  
              // Get a user by lowercase name. (optional)
              // If not provided, the entire list is iterated to find a user.
              m_userByNameCaseInsensitiveSql = 
                  sqlStatements.getSqlString("selectByLowercaseName");
  
              // Insert, update and delete are not guaranteed to be case-insensitive
              // Will always be called with correct case in username..
              m_insertUserSql = sqlStatements.getSqlString("insert", true);
              m_updateUserSql = sqlStatements.getSqlString("update", true);
              m_deleteUserSql = sqlStatements.getSqlString("delete", true);
  
              // Creates a single table with "username" the Primary Key.
              m_createUserTableSql = sqlStatements.getSqlString("createTable", true);
  
              // Check if the required table exists. If not, create it.
              // The table name is defined in the SqlResources.
              String tableName = sqlStatements.getSqlString("tableName", true);
              
              // Need to ask in the case that identifiers are stored, ask the DatabaseMetaInfo.
              // NB this should work, but some drivers (eg mm MySQL) 
              // don't return the right details, hence the hackery below.
              /*
              String tableName = m_tableName;
              if ( dbMetaData.storesLowerCaseIdentifiers() ) {
                  tableName = tableName.toLowerCase();
              }
              else if ( dbMetaData.storesUpperCaseIdentifiers() ) {
                  tableName = tableName.toUpperCase();
              }
              */
  
              // Try UPPER, lower, and MixedCase, to see if the table is there.
              if (! ( tableExists(dbMetaData, tableName) ||
                      tableExists(dbMetaData, tableName.toUpperCase()) ||
                      tableExists(dbMetaData, tableName.toLowerCase()) )) 
              {
                  // Users table doesn't exist - create it.
                  PreparedStatement createStatement = 
                      conn.prepareStatement(m_createUserTableSql);
                  createStatement.execute();
                  createStatement.close();
  
                  getLogger().info(this.getClass().getName() + ": Created table \'" + 
                                   tableName + "\'.");
              }
              else {
                  getLogger().debug("Using table: " + tableName);
              }
          
          }
          finally {
              closeConnection( conn );
          }
      }
  
      private boolean tableExists(DatabaseMetaData dbMetaData, String tableName)
          throws SQLException
      {
          ResultSet rsTables = dbMetaData.getTables(null, null, tableName, null);
          boolean found = rsTables.next();
          rsTables.close();
          return found;
      }
  
      //
      // Superclass methods - overridden in AbstractUsersRepository
      //
      /**
       * Returns a list populated with all of the Users in the repository.
       * @return an <code>Iterator</code> of <code>JamesUser</code>s.
       */
      protected Iterator listAllUsers() {
          List userList = new LinkedList(); // Build the users into this list.
  
          Connection conn = openConnection();
          try {
              // Get a ResultSet containing all users.
              PreparedStatement getUsersStatement = 
                  conn.prepareStatement(m_getUsersSql);
              ResultSet rsUsers = getUsersStatement.executeQuery();
  
              // Loop through and build a User for every row.
              while ( rsUsers.next() ) {
                  User user = readUserFromResultSet(rsUsers);
                  userList.add(user);
              }
  
              rsUsers.close();
              getUsersStatement.close();
          }
          catch ( SQLException sqlExc) {
              sqlExc.printStackTrace();
              throw new CascadingRuntimeException("Error accessing database", sqlExc);
          }
          finally {
              closeConnection(conn);
          }
  
          return userList.iterator();
      }
  
      /**
       * Adds a user to the underlying Repository.
       * The user name must not clash with an existing user.
       */
      protected void doAddUser(User user) {
          Connection conn = openConnection();
          // Insert into the database.
          try {
              // Get a PreparedStatement for the insert.
              PreparedStatement addUserStatement = 
                  conn.prepareStatement(m_insertUserSql);
  
              setUserForInsertStatement(user, addUserStatement);
  
              addUserStatement.execute();
              addUserStatement.close();
          }
          catch ( SQLException sqlExc) {
              sqlExc.printStackTrace();
              throw new CascadingRuntimeException("Error accessing database", sqlExc);
          }
          finally {
              closeConnection(conn);
          }
      }
  
      /**
       * Removes a user from the underlying repository.
       * If the user doesn't exist, returns ok.
       */
      protected void doRemoveUser(User user) {
          String username = user.getUserName();
  
          Connection conn = openConnection();
          // Delete from the database.
          try {
              PreparedStatement removeUserStatement = conn.prepareStatement(m_deleteUserSql);
              removeUserStatement.setString(1, username);
              removeUserStatement.execute();
              removeUserStatement.close();
          }
          catch ( SQLException sqlExc ) {
              sqlExc.printStackTrace();
              throw new CascadingRuntimeException("Error accessing database", sqlExc);
          }
          finally {
              closeConnection(conn);
          }
      }
  
      /**
       * Updates a user record to match the supplied User.
       */
      protected void doUpdateUser(User user)
      {
          Connection conn = openConnection();
  
          // Update the database.
          try {
              PreparedStatement updateUserStatement = conn.prepareStatement(m_updateUserSql);
  
              setUserForUpdateStatement(user, updateUserStatement);
  
              updateUserStatement.execute();
  
              updateUserStatement.close();
          }
          catch ( SQLException sqlExc ) {
              sqlExc.printStackTrace();
              throw new CascadingRuntimeException("Error accessing database", sqlExc);
          }
          finally {
              closeConnection(conn);
          }
      }
  
      /**
       * Gets a user by name, ignoring case if specified.
       * If the specified SQL statement has been defined, this method
       * overrides the basic implementation in AbstractUsersRepository
       * to increase performance.
       */
      protected User getUserByName(String name, boolean ignoreCase)
      {
          // See if this statement has been set, if not, use
          // simple superclass method.
          if ( m_userByNameCaseInsensitiveSql == null ) {
              return super.getUserByName(name, ignoreCase);
          }
  
          // Always get the user via case-insensitive SQL,
          // then check case if necessary.
          Connection conn = openConnection();
          try {
              // Get a ResultSet containing all users.
              String sql = m_userByNameCaseInsensitiveSql;
              PreparedStatement getUsersStatement = 
                  conn.prepareStatement(sql);
  
              getUsersStatement.setString(1, name.toLowerCase());
  
              ResultSet rsUsers = getUsersStatement.executeQuery();
  
              // For case-insensitive matching, the first matching user will be returned.
              User user = null;
              while ( rsUsers.next() ) {
                  User rowUser = readUserFromResultSet(rsUsers);
                  String actualName = rowUser.getUserName();
                      
                  // Check case before we assume it's the right one.
                  if ( ignoreCase || actualName.equals(name) ) {
                      user = rowUser;
                      break;
                  }
              }
              return user;
          }
          catch ( SQLException sqlExc ) {
              sqlExc.printStackTrace();
              throw new CascadingRuntimeException("Error accessing database", sqlExc);
          }
          finally {
              closeConnection(conn);
          }
      }
  
  
      /**
       * Reads properties for a User from an open ResultSet.
       * Subclass implementations of this method must have knowledge of the fields
       * presented by the "select" and "selectByLowercaseName" SQL statements.
       * These implemenations may generate a subclass-specific User instance.
       * 
       * @param rsUsers A ResultSet with a User record in the current row.
       * @return A User instance
       * @exception SQLException
       *                   if an exception occurs reading from the ResultSet
       */
      protected abstract User readUserFromResultSet(ResultSet rsUsers)
          throws SQLException;
  
      /**
       * Set parameters of a PreparedStatement object with 
       * property values from a User instance.
       * Implementations of this method have knowledge of the parameter
       * ordering of the "insert" SQL statement definition.
       * 
       * @param user       a User instance, which should be an implementation class which
       *                   is handled by this Repostory implementation.
       * @param userInsert a PreparedStatement initialised with SQL taken from the "insert" SQL definition.
       * @exception SQLException
       *                   if an exception occurs while setting parameter values.
       */
      protected abstract void setUserForInsertStatement(User user, 
                                                        PreparedStatement userInsert)
          throws SQLException;
  
      /**
       * Set parameters of a PreparedStatement object with
       * property values from a User instance.
       * Implementations of this method have knowledge of the parameter
       * ordering of the "update" SQL statement definition.
       * 
       * @param user       a User instance, which should be an implementation class which
       *                   is handled by this Repostory implementation.
       * @param userUpdate a PreparedStatement initialised with SQL taken from the "update" SQL definition.
       * @exception SQLException
       *                   if an exception occurs while setting parameter values.
       */
      protected abstract void setUserForUpdateStatement(User user, 
                                                        PreparedStatement userUpdate)
          throws SQLException;
  
      /**
       * Opens a connection, handling exceptions.
       */
      private Connection openConnection()
      {
          try {
              return m_datasource.getConnection();
          }
          catch (SQLException sqle) {
              throw new CascadingRuntimeException(
                  "An exception occurred getting a database connection.", sqle);
          }
      }
  
      /**
       * Closes a connection, handling exceptions.
       */
      private void closeConnection(Connection conn)
      {
          try {
              conn.close();
          }
          catch (SQLException sqle) {
              throw new CascadingRuntimeException(
                  "An exception occurred closing a database connection.", sqle);
          }
      }
  
  }    
  
  
  
  
  
  1.1                  jakarta-james/src/java/org/apache/james/userrepository/DefaultUsersJdbcRepository.java
  
  Index: DefaultUsersJdbcRepository.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.userrepository;
  
  import org.apache.james.services.User;
  import java.sql.*;
  
  
  /**
   * A Jdbc-backed UserRepository which handles User instances
   * of the <CODE>DefaultUser</CODE> class.
   * Although this repository can handle subclasses of DefaultUser,
   * like <CODE>DefaultJamesUser</CODE>, only properties from
   * the DefaultUser class are persisted.
   * 
   * @author Darrell DeBoer <dd...@bigdaz.com>
   */
  public class DefaultUsersJdbcRepository extends AbstractJdbcUsersRepository
  {
      protected User readUserFromResultSet(ResultSet rsUsers) throws SQLException 
      {
          // Get the username, and build a DefaultUser with it.
          String username = rsUsers.getString(1);
          String passwordAlg = rsUsers.getString(2);
          String passwordHash = rsUsers.getString(3);
          DefaultUser user = new DefaultUser(username, passwordHash, passwordAlg);
          return user;
      }
  
      protected void setUserForInsertStatement(User user, 
                                               PreparedStatement userInsert) 
          throws SQLException 
      {
          DefaultUser defUser = (DefaultUser)user;
          userInsert.setString(1, defUser.getUserName());
          userInsert.setString(2, defUser.getHashAlgorithm());
          userInsert.setString(3, defUser.getHashedPassword());
      }
  
      protected void setUserForUpdateStatement(User user, 
                                               PreparedStatement userUpdate) 
          throws SQLException 
      {
          DefaultUser defUser = (DefaultUser)user;
          userUpdate.setString(3, defUser.getUserName());
          userUpdate.setString(1, defUser.getHashAlgorithm());
          userUpdate.setString(2, defUser.getHashedPassword());
      }
  }
  
  
  
  
  1.1                  jakarta-james/src/java/org/apache/james/userrepository/JamesUsersJdbcRepository.java
  
  Index: JamesUsersJdbcRepository.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.userrepository;
  
  import org.apache.james.services.User;
  import org.apache.mailet.MailAddress;
  
  import java.sql.ResultSet;
  import java.sql.PreparedStatement;
  import java.sql.SQLException;
  
  /**
   * A Jdbc-backed UserRepository which handles User instances
   * of the <CODE>DefaultJamesUser</CODE> class, or any superclass.
   * 
   * @author Darrell DeBoer <dd...@bigdaz.com>
   */
  public class JamesUsersJdbcRepository extends AbstractJdbcUsersRepository
  {
      protected User readUserFromResultSet(ResultSet rsUsers) throws SQLException 
      {
          // Get the column values
          String username = rsUsers.getString(1);
          String pwdHash = rsUsers.getString(2);
          String pwdAlgorithm = rsUsers.getString(3);
          boolean useForwarding = rsUsers.getBoolean(4);
          String forwardingDestination = rsUsers.getString(5);
          boolean useAlias = rsUsers.getBoolean(6);
          String alias = rsUsers.getString(7);
  
          MailAddress forwardAddress = null;
          if ( forwardingDestination != null ) {
              try {
                  forwardAddress = new MailAddress(forwardingDestination);
              }
              catch (javax.mail.internet.ParseException pe) {
                  throw new RuntimeException(
                      "Invalid mail address in database: " + forwardingDestination + 
                      ", for user " + username + ".");
              }
          }
  
          // Build a DefaultJamesUser with these values, and add to the list.
          DefaultJamesUser user = new DefaultJamesUser(username, pwdHash, pwdAlgorithm);
          user.setForwarding(useForwarding);
          user.setForwardingDestination(forwardAddress);
          user.setAliasing(useAlias);
          user.setAlias(alias);
  
          return user;
      }
  
      protected void setUserForInsertStatement(User user, 
                                               PreparedStatement userInsert) 
          throws SQLException 
      {
          setUserForStatement(user, userInsert, false);
      }
  
      protected void setUserForUpdateStatement(User user, 
                                               PreparedStatement userUpdate) 
          throws SQLException 
      {
          setUserForStatement(user, userUpdate, true);
      }
  
      private void setUserForStatement(User user, PreparedStatement stmt,
                                       boolean userNameLast) throws SQLException
      {
          // Determine column offsets to use, based on username column pos.
          int nameIndex = 1;
          int colOffset = 1;
          if ( userNameLast ) {
              nameIndex = 7;
              colOffset = 0;
          }
  
          // Can handle instances of DefaultJamesUser and DefaultUser.
          DefaultJamesUser jamesUser;
          if (user instanceof DefaultJamesUser) {
              jamesUser = (DefaultJamesUser)user;
          }
          else if ( user instanceof DefaultUser ) {
              DefaultUser aUser = (DefaultUser)user;
              jamesUser = new DefaultJamesUser(aUser.getUserName(),
                                               aUser.getHashedPassword(),
                                               aUser.getHashAlgorithm());
          } 
          // Can't handle any other implementations.
          else {
              throw new RuntimeException("An unknown implementation of User was " + 
                                         "found. This implementation cannot be " + 
                                         "persisted to a UsersJDBCRepsitory.");
          }
  
          // Get the user details to save.
          stmt.setString(nameIndex, jamesUser.getUserName());
          stmt.setString(1 + colOffset, jamesUser.getHashedPassword());
          stmt.setString(2 + colOffset, jamesUser.getHashAlgorithm());
          stmt.setInt(3 + colOffset, (jamesUser.getForwarding() ? 1 : 0));
  
          MailAddress forwardAddress = jamesUser.getForwardingDestination();
          String forwardDestination = null;
          if ( forwardAddress != null ) {
              forwardDestination = forwardAddress.toString();
          }
          stmt.setString(4 + colOffset, forwardDestination);
          stmt.setInt(5 + colOffset, (jamesUser.getAliasing() ? 1 : 0));
          stmt.setString(6 + colOffset, jamesUser.getAlias());
      }
  }
  
  
  
  1.1                  jakarta-james/src/java/org/apache/james/userrepository/ListUsersJdbcRepository.java
  
  Index: ListUsersJdbcRepository.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.userrepository;
  
  import org.apache.james.services.User;
  import java.sql.*;
  
  /**
   * A very lightweight UserRepository, which persists a list
   * of user names in a database. Password information is not 
   * persisted.
   * 
   * @author Darrell DeBoer <dd...@bigdaz.com>
   */
  public class ListUsersJdbcRepository extends AbstractJdbcUsersRepository
  {
      protected User readUserFromResultSet(ResultSet rsUsers) throws SQLException 
      {
          // Get the username, and build a DefaultUser with it.
          String username = rsUsers.getString(1);
          DefaultUser user = new DefaultUser(username, "SHA");
          return user;
      }
      protected void setUserForInsertStatement(User user, 
                                               PreparedStatement userInsert) 
          throws SQLException 
      {
          userInsert.setString(1, user.getUserName());
      }
  
      protected void setUserForUpdateStatement(User user, 
                                               PreparedStatement userUpdate) 
          throws SQLException 
      {
          throw new UnsupportedOperationException("Can't update a List User - " +
                                                  "only has a single attribute.");
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: james-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: james-dev-help@jakarta.apache.org