craigmcc    01/04/10 18:46:10

  Modified:    catalina/src/share/org/apache/catalina/realm
                        GenericPrincipal.java JDBCRealm.java
                        LocalStrings.properties MemoryRealm.java
                        RealmBase.java
  Log:
  General refactoring and cleanup of the org.apache.catalina.realm package:
  * Migrated digest processing into the base class so that it can be
    used by MemoryRealm as well.
  * Migrated standard hasRole() into the base class so that Realm
    implementations using GenericPrincipal do not need to do anything.
  * Modified JDBCRealm to use GenericPrincipal.
  * Clean up code in JDBCRealm for opening and closing the database
    connection, reporting errors in start() and stop(), and creating
    prepared statements.  You can now subclass and specialize if needed.
  * Add a "commit()" call inside authenticate() in case the underlying
    database does not like a long-running transaction.
  * Cosmetic cleanup to code and Javadocs to be consistent with the
    rest of Catalina.
  
  There should be no functionality change, except for the new ability to use
  digest-encoded passwords in MemoryRealm.
  
  Updates to the config documentation will be done later tonight.
  
  Revision  Changes    Path
  1.2       +8 -9      
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/GenericPrincipal.java
  
  Index: GenericPrincipal.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/GenericPrincipal.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- GenericPrincipal.java     2001/04/01 02:29:46     1.1
  +++ GenericPrincipal.java     2001/04/11 01:46:09     1.2
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/GenericPrincipal.java,v
 1.1 2001/04/01 02:29:46 craigmcc Exp $
  - * $Revision: 1.1 $
  - * $Date: 2001/04/01 02:29:46 $
  + * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/GenericPrincipal.java,v
 1.2 2001/04/11 01:46:09 craigmcc Exp $
  + * $Revision: 1.2 $
  + * $Date: 2001/04/11 01:46:09 $
    *
    * ====================================================================
    *
  @@ -66,6 +66,7 @@
   
   
   import java.security.Principal;
  +import java.util.Arrays;
   import java.util.List;
   import org.apache.catalina.Realm;
   
  @@ -77,7 +78,7 @@
    * private to avoid interference from applications.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.1 $ $Date: 2001/04/01 02:29:46 $
  + * @version $Revision: 1.2 $ $Date: 2001/04/11 01:46:09 $
    */
   
   class GenericPrincipal implements Principal {
  @@ -120,6 +121,8 @@
           if (roles != null) {
               this.roles = new String[roles.size()];
               this.roles = (String[]) roles.toArray(this.roles);
  +            if (this.roles.length > 0)
  +                Arrays.sort(this.roles);
           }
   
       }
  @@ -198,11 +201,7 @@
   
           if (role == null)
               return (false);
  -        for (int i = 0; i < roles.length; i++) {
  -            if (role.equals(roles[i]))
  -                return (true);
  -        }
  -        return (false);
  +        return (Arrays.binarySearch(roles, role) >= 0);
   
       }
   
  
  
  
  1.12      +257 -406  
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/JDBCRealm.java
  
  Index: JDBCRealm.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/JDBCRealm.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- JDBCRealm.java    2001/04/10 09:06:49     1.11
  +++ JDBCRealm.java    2001/04/11 01:46:09     1.12
  @@ -59,10 +59,15 @@
   package org.apache.catalina.realm;
   
   
  -import java.beans.PropertyChangeListener;
  -import java.beans.PropertyChangeSupport;
  -import java.security.Principal;
   import java.io.File;
  +import java.security.Principal;
  +import java.sql.Connection;
  +import java.sql.Driver;
  +import java.sql.PreparedStatement;
  +import java.sql.ResultSet;
  +import java.sql.SQLException;
  +import java.util.ArrayList;
  +import java.util.Properties;
   import org.apache.catalina.Container;
   import org.apache.catalina.Lifecycle;
   import org.apache.catalina.LifecycleEvent;
  @@ -72,17 +77,9 @@
   import org.apache.catalina.Realm;
   import org.apache.catalina.util.LifecycleSupport;
   import org.apache.catalina.util.StringManager;
  -//import org.apache.catalina.util.xml.SaxContext;
  -//import org.apache.catalina.util.xml.XmlAction;
  -//import org.apache.catalina.util.xml.XmlMapper;
  -import org.xml.sax.AttributeList;
   import org.apache.catalina.util.Base64;
  -import org.apache.catalina.util.HexUtils;
   
  -import java.security.*;
  -import java.sql.*;
   
  -
   /**
    *
    * Implmentation of <b>Realm</b> that works with any JDBC supported database.
  @@ -90,11 +87,13 @@
    * for configuration options.
    *
    * TODO:
  - *    - Work on authentication with non-plaintext passwords
    *    - Make sure no bad chars can get in and trick the auth and hasrole
  + *    - Use a database connection pool for faster simultaneous access
    *
    * @author Craig R. McClanahan
    * @author Carson McDonald
  + * @author Ignacio Ortega
  + * @version $Revision: 1.12 $ $Date: 2001/04/11 01:46:09 $
    */
   
   public class JDBCRealm
  @@ -104,113 +103,126 @@
       // ----------------------------------------------------- Instance Variables
   
   
  +    /**
  +     * The connection username to use when trying to connect to the database.
  +     */
  +    protected String connectionName = null;
  +
  +
       /**
  -     * The connection URL to use when trying to connect to the databse
  +     * The connection URL to use when trying to connect to the database.
        */
  -    private String connectionURL = null;
  +    protected String connectionPassword = null;
   
   
       /**
  +     * The connection URL to use when trying to connect to the database.
  +     */
  +    protected String connectionURL = null;
  +
  +
  +    /**
        * The connection to the database.
  +     */
  +    protected Connection dbConnection = null;
  +
  +
  +    /**
  +     * Instance of the JDBC Driver class we use as a connection factory.
        */
  -    private Connection dbConnection = null;
  +    protected Driver driver = null;
   
   
       /**
        * The JDBC driver to use.
        */
  -    private String driverName = null;
  +    protected String driverName = null;
   
   
       /**
        * Descriptive information about this Realm implementation.
        */
  +    protected static final String info =
  +        "org.apache.catalina.realm.JDBCRealm/1.0";
   
  -    protected static final String info = "org.apache.catalina.realm.JDBCRealm/1.0";
   
       /**
        * Descriptive information about this Realm implementation.
        */
  +    protected static final String name = "JDBCRealm";
   
  -    private static final String name = "JDBCRealm";
   
  -
       /**
        * The PreparedStatement to use for authenticating users.
        */
  -    private PreparedStatement preparedAuthenticate = null;
  +    protected PreparedStatement preparedCredentials = null;
   
   
       /**
        * The PreparedStatement to use for identifying the roles for
        * a specified user.
        */
  -    private PreparedStatement preparedRoles = null;
  +    protected PreparedStatement preparedRoles = null;
   
   
       /**
        * The column in the user role table that names a role
        */
  -    private String roleNameCol = null;
  +    protected String roleNameCol = null;
   
   
       /**
        * The string manager for this package.
        */
  -    private static final StringManager sm =
  +    protected static final StringManager sm =
        StringManager.getManager(Constants.Package);
   
   
       /**
  -     * Has this component been started?
  -     */
  -    private boolean started = false;
  -
  -
  -    /**
        * The column in the user table that holds the user's credintials
        */
  -    private String userCredCol = null;
  +    protected String userCredCol = null;
   
   
       /**
        * The column in the user table that holds the user's name
        */
  -    private String userNameCol = null;
  +    protected String userNameCol = null;
   
   
       /**
        * The table that holds the relation between user's and roles
        */
  -    private String userRoleTable = null;
  +    protected String userRoleTable = null;
   
   
       /**
        * The table that holds user data.
        */
  -    private String userTable = null;
  +    protected String userTable = null;
   
  -    /**
  -     * The connection URL to use when trying to connect to the databse
  -     */
  -    private String connectionName = null;
   
  -    /**
  -     * The connection URL to use when trying to connect to the databse
  -     */
  -    private String connectionPassword = null;
  +    // ------------------------------------------------------------- Properties
   
  -     /**
  -     *
  -     * Digest algorithm used in passwords thit is same values
  -     * accepted by MessageDigest  for algorithm
  -     * plus "No" ( no encode ) that is the default
  +
  +    /**
  +     * Set the username to use to connect to the database.
        *
  +     * @param connectionName Username
        */
  +    public void setConnectionName(String connectionName) {
  +        this.connectionName = connectionName;
  +    }
   
  -    private String digest="";
   
  -   // ------------------------------------------------------------- Properties
  +    /**
  +     * Set the password to use to connect to the database.
  +     *
  +     * @param connectionPassword User password
  +     */
  +    public void setConnectionPassword(String connectionPassword) {
  +        this.connectionPassword = connectionPassword;
  +    }
   
   
       /**
  @@ -234,9 +246,9 @@
   
   
       /**
  -     * Set the column in the user role table that names a role
  +     * Set the column in the user role table that names a role.
        *
  -     * @param userRoleNameCol The column name
  +     * @param roleNameCol The column name
        */
       public void setRoleNameCol( String roleNameCol ) {
           this.roleNameCol = roleNameCol;
  @@ -244,7 +256,7 @@
   
   
       /**
  -     * Set the column in the user table that holds the user's credintials
  +     * Set the column in the user table that holds the user's credentials.
        *
        * @param userCredCol The column name
        */
  @@ -254,7 +266,7 @@
   
   
       /**
  -     * Set the column in the user table that holds the user's name
  +     * Set the column in the user table that holds the user's name.
        *
        * @param userNameCol The column name
        */
  @@ -264,7 +276,7 @@
   
   
       /**
  -     * Set the table that holds the relation between user's and roles
  +     * Set the table that holds the relation between user's and roles.
        *
        * @param userRoleTable The table name
        */
  @@ -282,85 +294,22 @@
         this.userTable = userTable;
       }
   
  -    /**
  -     * Set the name to use to connect to the database.
  -     *
  -     * @param connectionName User name
  -     */
  -    public void setConnectionName(String connectionName) {
  -        this.connectionName = connectionName;
  -    }
  -
  -    /**
  -     * Set the password to use to connect to the database.
  -     *
  -     * @param connectionPassword User password
  -     */
  -    public void setConnectionPassword(String connectionPassword) {
  -        this.connectionPassword = connectionPassword;
  -    }
  -
  -
  -    /**
  -     * Gets the digest algorithm  used for credentials in the database
  -     * could be the same that MessageDigest accepts vor algorithm
  -     * and "No" that is the Default
  -     *
  -     */
  -
  -    public String getDigest() {
  -        return digest;
  -    }
  -
  -    /**
  -     * Gets the digest algorithm  used for credentials in the database
  -     * could be the same that MessageDigest accepts vor algorithm
  -     * and "No" that is the Default
  -     *
  -     * @param algorithm the Encode type
  -     */
  -
  -    public void setDigest(String algorithm) {
  -        digest = algorithm;
  -    }
  -
  -
  -    /**
  -     * Return descriptive information about this Realm implementation and
  -     * the corresponding version number, in the format
  -     * <code>&lt;description&gt;/&lt;version&gt;</code>.
  -     */
  -    public String getInfo() {
  -
  -     return this.info;
  -
  -    }
  -
  -    /**
  -     * Return short name of this Realm implementation
  -     */
  -    public String getName() {
  -
  -     return name;
   
  -    }
  -
       // --------------------------------------------------------- Public Methods
   
   
       /**
  -     *
        * Return the Principal associated with the specified username and
        * credentials, if there is one; otherwise return <code>null</code>.
        *
        * If there are any errors with the JDBC connection, executing 
        * the query or anything we return null (don't authenticate). This
  -     * event is also logged. 
  +     * event is also logged, and the connection will be closed so that
  +     * a subsequent request will automatically re-open it.
        *
  -     * If there is some SQL exception the connection is set to null. 
  -     * This will allow a retry on the next auth attempt. This might not
  -     * be the best thing to do but it will keep Catalina from needing a
  -     * restart if the database goes down.
  +     * <strong>IMPLEMENTATION NOTE</strong> - This method is synchronized
  +     * because we are sharing a single connection (and its associated
  +     * prepared statements) across all request threads.
        *
        * @param username Username of the Principal to look up
        * @param credentials Password or other credentials to use in
  @@ -370,97 +319,53 @@
                                               String credentials) {
   
           try {
  +
  +            // Ensure that our database connection is open
  +            open();
   
  -            if (!checkConnection()) return null;
  -         // Create the authentication search prepared statement if necessary
  -         if (preparedAuthenticate == null) {
  -             String sql = "SELECT " + userCredCol + " FROM " + userTable +
  -                 " WHERE " + userNameCol + " = ?";
  -             if (debug >= 1)
  -                 log("JDBCRealm.authenticate: " + sql);
  -             preparedAuthenticate = dbConnection.prepareStatement(sql);
  -         }
  -
  -         // Create the roles search prepared statement if necessary
  -         if (preparedRoles == null) {
  -             String sql = "SELECT " + roleNameCol + " FROM " +
  -                 userRoleTable + " WHERE " + userNameCol + " = ?";
  -             if (debug >= 1)
  -                 log("JDBCRealm.roles: " + sql);
  -             preparedRoles = dbConnection.prepareStatement(sql);
  -         }
  -
  -         // Perform the authentication search
  -         preparedAuthenticate.setString(1, username);
  -         ResultSet rs1 = preparedAuthenticate.executeQuery();
  -         boolean found = false;
  -         if (rs1.next()) {
  -                String dbCredentials=rs1.getString(1).trim();
  -                if( digest.equals("") || digest.equalsIgnoreCase("No")){
  -                    if(credentials.equals(dbCredentials)) {
  -                        if(debug >= 2)
  -                            log(sm.getString("jdbcRealm.authenticateSuccess",
  -                                             username));
  -                        found = true;
  -                    }
  -                } else{
  -                    if (Digest(credentials,digest).equals(dbCredentials)) {
  -                        if (debug >= 2)
  -                            log(sm.getString("jdbcRealm.authenticateSuccess",
  +            // Look up the user's credentials
  +            String dbCredentials = null;
  +            PreparedStatement stmt = credentials(username);
  +            ResultSet rs = stmt.executeQuery();
  +            while (rs.next()) {
  +                dbCredentials = rs.getString(1).trim();
  +            }
  +            rs.close();
  +            if (dbCredentials == null)
  +                return (null);
  +
  +            // Validate the user's credentials
  +            if (digest(credentials).equals(dbCredentials)) {
  +                if (debug >= 2)
  +                    log(sm.getString("jdbcRealm.authenticateSuccess",
  +                                     username));
  +            } else {
  +                if (debug >= 2)
  +                    log(sm.getString("jdbcRealm.authenticateFailure",
                                        username));
  -                        found = true;
  -                    }
  -                }
  -         }
  -         rs1.close();
  -         if (!found) {
  -             if (debug >= 2)
  -                 log(sm.getString("jdbcRealm.authenticateFailure",
  -                                  username));
  -             return (null);
  -         }
  -
  -         // Prepare and return a suitable Principal to be returned
  -         JDBCRealmPrincipal principal =
  -             new JDBCRealmPrincipal(username, credentials);
  -         preparedRoles.setString(1, username);
  -         ResultSet rs2 = preparedRoles.executeQuery();
  -         while (rs2.next()) {
  -             principal.addRole(rs2.getString(1).trim());
  -         }
  -         rs2.close();
  -         return (principal);
  +                return (null);
  +            }
   
  -     } catch( SQLException ex ) {
  +            // Accumulate the user's roles
  +            ArrayList list = new ArrayList();
  +            stmt = roles(username);
  +            rs = stmt.executeQuery();
  +            while (rs.next()) {
  +                list.add(rs.getString(1).trim());
  +            }
  +            rs.close();
  +            dbConnection.commit();
  +
  +            // Create and return a suitable Principal for this user
  +            return (new GenericPrincipal(this, username, credentials, list));
  +
  +     } catch (SQLException e) {
   
            // Log the problem for posterity
  -         log("JDBCRealm.authenticate", ex);
  +         log(sm.getString("jdbcRealm.exception"), e);
   
  -         // Clean up the JDBC objects so that they get recreated next time
  -         if (preparedRoles != null) {
  -             try {
  -                 preparedRoles.close();
  -             } catch (Throwable t) {
  -                 ;
  -             }
  -             preparedRoles = null;
  -         }
  -         if (preparedAuthenticate != null) {
  -             try {
  -                 preparedAuthenticate.close();
  -             } catch (Throwable t) {
  -                 ;
  -             }
  -             preparedAuthenticate = null;
  -         }
  -         if (dbConnection != null) {
  -             try {
  -                 dbConnection.close();
  -             } catch (Throwable t) {
  -                 ;
  -             }
  -             dbConnection = null;
  -         }
  +            // Close the connection so that it gets reopened next time
  +            close();
   
            // Return "not authenticated" for this request
            return (null);
  @@ -470,268 +375,214 @@
       }
   
   
  +    // -------------------------------------------------------- Package Methods
  +
  +
  +    // ------------------------------------------------------ Protected Methods
  +
  +
       /**
  +     * Close any database connection that is currently open.
  +     */
  +    protected void close() {
  +
  +        // Do nothing if the database connection is already closed
  +        if (dbConnection == null)
  +            return;
  +
  +        // Close our prepared statements (if any)
  +        try {
  +            preparedCredentials.close();
  +        } catch (Throwable f) {
  +            ;
  +        }
  +        try {
  +            preparedRoles.close();
  +        } catch (Throwable f) {
  +            ;
  +        }
  +
  +        // Close this database connection, and log any errors
  +        try {
  +            dbConnection.close();
  +        } catch (SQLException e) {
  +            log(sm.getString("jdbcRealm.close"), e); // Just log it here
  +        }
  +
  +        // Release resources associated with the closed connection
  +        dbConnection = null;
  +        preparedCredentials = null;
  +        preparedRoles = null;
  +
  +    }
  +
  +
  +    /**
  +     * Return a PreparedStatement configured to perform the SELECT required
  +     * to retrieve user credentials for the specified username.
  +     *
  +     * @param username Username for which credentials should be retrieved
        *
  -     * Return <code>true</code> if the specified Principal has the specified
  -     * security role, within the context of this Realm; otherwise return
  -     * <code>false</code>.
  -     *
  -     * If there are any errors with the JDBC connection, executing
  -     * the query or anything we return false (not in role set). This
  -     * event is also logged.
  -     *
  -     * If there is some SQL exception the connection is set to null.
  -     * This will allow a retry on the next auth attempt. This might not
  -     * be the best thing to do but it will keep Catalina from needing a
  -     * restart if the database goes down.
  -     *
  -     * @param principal Principal for whom the role is to be checked
  -     * @param role Security role to be checked
  -     */
  -    public boolean hasRole(Principal principal, String role) {
  -        String username = principal.getName();
  -
  -     // Is the specified Principal one that we created?
  -     if (!(principal instanceof JDBCRealmPrincipal))
  -         return (false);
  +     * @exception SQLException if a database error occurs
  +     */
  +    protected PreparedStatement credentials(String username)
  +        throws SQLException {
   
  -     // Ask this Principal for the answer
  -     return (((JDBCRealmPrincipal) principal).hasRole(role));
  +        if (preparedCredentials == null) {
  +            StringBuffer sb = new StringBuffer("SELECT ");
  +            sb.append(userCredCol);
  +            sb.append(" FROM ");
  +            sb.append(userTable);
  +            sb.append(" WHERE ");
  +            sb.append(userNameCol);
  +            sb.append(" = ?");
  +            preparedCredentials =
  +                dbConnection.prepareStatement(sb.toString());
  +        }
  +
  +        preparedCredentials.setString(1, username);
  +        return (preparedCredentials);
   
       }
   
   
  -    // -------------------------------------------------------- Package Methods
  +    /**
  +     * Return a short name for this Realm implementation.
  +     */
  +    protected String getName() {
   
  +        return (this.name);
   
  -    // ------------------------------------------------------ Protected Methods
  +    }
   
  +
       /**
        * Return the password associated with the given principal's user name.
        */
       protected String getPassword(String username) {
  +
           return (null);
  +
       }
   
  +
       /**
        * Return the Principal associated with the given user name.
        */
       protected Principal getPrincipal(String username) {
  +
           return (null);
  +
       }
   
   
       /**
  -     *
  -     * Prepare for active use of the public methods of this Component.
  -     *
  -     * The DriverManager is initiated here. The initial database connection
  -     * is also formed.
  +     * Open a database connection for use by this Realm.
        *
  -     * @exception IllegalStateException if this component has already been
  -     *  started
  -     * @exception LifecycleException if this component detects a fatal error
  -     *  that prevents it from being started
  +     * @exception SQLException if a database error occurs
        */
  -    public synchronized void start() throws LifecycleException {
  -     // Validate and update our current component state
  -     if (started) {
  -         throw new LifecycleException (sm.getString("jdbcRealm.alreadyStarted"));
  -        }
  -     lifecycle.fireLifecycleEvent(START_EVENT, null);
  -     started = true;
  -        if(!checkConnection()) {
  -            throw new LifecycleException (sm.getString("jdbcRealm.alreadyStarted"));
  +    protected void open() throws SQLException {
  +
  +        // Do nothing if there is a database connection already open
  +        if (dbConnection != null)
  +            return;
  +
  +        // Instantiate our database driver if necessary
  +        if (driver == null) {
  +            try {
  +                Class clazz = Class.forName(driverName);
  +                driver = (Driver) clazz.newInstance();
  +            } catch (Throwable e) {
  +                throw new SQLException(e.getMessage());
  +            }
           }
   
  +        // Open a new connection
  +        Properties props = new Properties();
  +        if (connectionName != null)
  +            props.put("user", connectionName);
  +        if (connectionPassword != null)
  +            props.put("password", connectionPassword);
  +        dbConnection = driver.connect(connectionURL, props);
  +
       }
   
   
       /**
  -     *
  -     * Gracefully shut down active use of the public methods of this Component.
  +     * Return a PreparedStatement configured to perform the SELECT required
  +     * to retrieve user roles for the specified username.
        *
  -     * If there is a connection it is closed.
  +     * @param username Username for which roles should be retrieved
        *
  -     * @exception IllegalStateException if this component has not been started
  -     * @exception LifecycleException if this component detects a fatal error
  -     *  that needs to be reported
  +     * @exception SQLException if a database error occurs
        */
  -    public synchronized void stop() throws LifecycleException {
  -     // Validate and update our current component state
  -     if (!started) {
  -         throw new LifecycleException (sm.getString("jdbcRealm.notStarted"));
  -        }
  -     lifecycle.fireLifecycleEvent(STOP_EVENT, null);
  -     started = false;
  +    protected PreparedStatement roles(String username)
  +        throws SQLException {
   
  -     // Close any open DB connection
  -        if( dbConnection != null ) {
  -          try {
  -            dbConnection.close();
  -          }
  -          catch( SQLException ex ) {
  -            // XXX: Don't know if this is the best thing to do. Maybe just ignore.
  -         throw new LifecycleException (sm.getString("jdbcRealm.notStarted"));
  -          }
  +        if (preparedRoles == null) {
  +            StringBuffer sb = new StringBuffer("SELECT ");
  +            sb.append(roleNameCol);
  +            sb.append(" FROM ");
  +            sb.append(userRoleTable);
  +            sb.append(" WHERE ");
  +            sb.append(userNameCol);
  +            sb.append(" = ?");
  +            preparedRoles =
  +                dbConnection.prepareStatement(sb.toString());
           }
  -    }
   
  -    /**
  -     * Digest password using the algorithm especificied and
  -     * convert the result to a corresponding hex string.
  -     * If exception, the plain credentials string is returned
  -     *
  -     * @param credentials Password or other credentials to use in
  -     *  authenticating this username
  -     *
  -     * @param algorithm Algorithm used to do th digest
  -     *
  -     */
  -    final public static String Digest(String credentials,String algorithm) {
  -        try {
  -            // Obtain a new message digest with "digest" encryption
  -            MessageDigest md = 
(MessageDigest)MessageDigest.getInstance(algorithm).clone();
  -            // encode the credentials
  -            md.update( credentials.getBytes() );
  -            // obtain the byte array from the digest
  -            byte[] dig = md.digest();
  -            // convert the byte array to hex string
  -            return HexUtils.convert(dig);
  -
  -        } catch( Exception ex ) {
  -                ex.printStackTrace();
  -                return credentials;
  -        }
  -    }
  +        preparedRoles.setString(1, username);
  +        return (preparedRoles);
   
  -    private boolean checkConnection(){
  -        try {
  -            if( (dbConnection == null) || dbConnection.isClosed() ) {
  -                Class.forName(driverName);
  -                log(sm.getString("jdbcRealm.checkConnectionDBClosed"));
  -                if ((connectionName == null || connectionName.equals("")) ||
  -                        (connectionPassword == null || 
connectionPassword.equals(""))) {
  -                        dbConnection = DriverManager.getConnection(connectionURL);
  -                } else {
  -                        dbConnection = DriverManager.getConnection(connectionURL,
  -                                                                   connectionName,
  -                                                                   
connectionPassword);
  -                }
  -                if( dbConnection == null || dbConnection.isClosed() ) {
  -                  log(sm.getString("jdbcRealm.checkConnectionDBReOpenFail"));
  -                  return false;
  -                }
  -            }
  -            return true;
  -        }catch (SQLException ex){
  -            log(sm.getString("jdbcRealm.checkConnectionSQLException"),ex);
  -            return false;
  -        }
  -        catch( ClassNotFoundException ex ) {
  -            log(sm.getString("jdbcRealm.checkConnectionClassNotFoundException"),ex);
  -            return false;
  -        }
       }
   
  -    public static void main(String args[] ) {
  -        if (args.length >= 2) {
  -            if( args[0].equalsIgnoreCase("-a")){
  -                for( int i=2; i < args.length ; i++){
  -                    System.out.print(args[i]+":");
  -                    System.out.println(Digest(args[i],args[1]));
  -                }
  -            }
  -        }
  -
  -    }
   
  -}
  +    // -------------------------------------------------------- Private Methods
   
   
  -/**
  - * Private class representing an individual user's Principal object.
  - */
  -final class JDBCRealmPrincipal implements Principal {
  +    // ------------------------------------------------------ Lifecycle Methods
   
   
       /**
  -     * The password for this Principal.
  -     */
  -    private String password = null;
  -
  -
  -    /**
  -     * The role names possessed by this Principal.
  +     *
  +     * Prepare for active use of the public methods of this Component.
  +     *
  +     * @exception IllegalStateException if this component has already been
  +     *  started
  +     * @exception LifecycleException if this component detects a fatal error
  +     *  that prevents it from being started
        */
  -    private String roles[] = new String[0];
  -
  +    public void start() throws LifecycleException {
   
  -    /**
  -     * The username for this Principal.
  -     */
  -    private String username = null;
  +        // Validate that we can open our connection
  +        try {
  +            open();
  +        } catch (SQLException e) {
  +            throw new LifecycleException(sm.getString("jdbcRealm.open"), e);
  +        }
   
  +        // Perform normal superclass initialization
  +        super.start();
   
  -    /**
  -     * Construct a new JDBCRealmPrincipal instance.
  -     *
  -     * @param username The username for this Principal
  -     * @param password The password for this Principal
  -     */
  -    public JDBCRealmPrincipal(String username, String password) {
  -     this.username = username;
  -     this.password = password;
       }
   
   
       /**
  -     * Add a new role assigned to this Principal.
  -     * @param role The new role to be assigned
  +     * Gracefully shut down active use of the public methods of this Component.
  +     *
  +     * @exception IllegalStateException if this component has not been started
  +     * @exception LifecycleException if this component detects a fatal error
  +     *  that needs to be reported
        */
  -    void addRole(String role) {
  -     if (role == null)
  -         return;
  -     for (int i = 0; i < roles.length; i++) {
  -         if (role.equals(roles[i]))
  -             return;
  -     }
  -     String results[] = new String[roles.length + 1];
  -     for (int i = 0; i < roles.length; i++)
  -         results[i] = roles[i];
  -     results[roles.length] = role;
  -        roles = results;
  -    }
  +    public void stop() throws LifecycleException {
   
  +        // Perform normal superclass finalization
  +        super.stop();
   
  -    /**
  -     * Return the name of this Principal.
  -     */
  -    public String getName() {
  -     return (username);
  -    }
  -
  +     // Close any open DB connection
  +        close();
   
  -    /**
  -     * Return the password of this Principal.
  -     */
  -    public String getPassword() {
  -     return (password);
       }
   
  -
  -    /**
  -     * Does this user have the specified role assigned?
  -     * @param role The role to be checked
  -     */
  -    boolean hasRole(String role) {
  -     if (role == null)
  -         return (false);
  -     for (int i = 0; i < roles.length; i++) {
  -         if (role.equals(roles[i]))
  -             return (true);
  -     }
  -     return (false);
  -    }
   
   }
  
  
  
  1.3       +17 -23    
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/LocalStrings.properties,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- LocalStrings.properties   2000/12/31 16:30:35     1.2
  +++ LocalStrings.properties   2001/04/11 01:46:09     1.3
  @@ -1,28 +1,22 @@
  -# $Id: LocalStrings.properties,v 1.2 2000/12/31 16:30:35 nacho Exp $
  +# $Id: LocalStrings.properties,v 1.3 2001/04/11 01:46:09 craigmcc Exp $
   
   # language 
   
   # package org.apache.catalina.realm
   
  -
  -memoryRealm.alreadyStarted=This Realm has already been started
  -memoryRealm.authenticateFailure=Authentication unsuccessful for user {0}
  -memoryRealm.authenticateSuccess=Authentication successful for user {0}
  -memoryRealm.hasRoleFailure=User {0} does NOT have role {1}
  -memoryRealm.hasRoleNone=No user has role {0}
  -memoryRealm.hasRoleSuccess=User {0} has role {1}
  -memoryRealm.hasRoleUser=User {0} is not in this realm database
  -memoryRealm.loadExist=Memory realm file {0} does not exist
  -memoryRealm.loadPath=Loading memory realm file {0}
  -memoryRealm.notStarted=This Realm has not yet been started
  -jdbcRealm.alreadyStarted=This Realm has already been started
  -jdbcRealm.authenticateFailure=Authentication unsuccessful for user {0}
  -jdbcRealm.authenticateSuccess=Authentication successful for user {0}
  -jdbcRealm.authenticateSQLException=There was an SQLException while in authenticate: 
{0}
  -jdbcRealm.hasRoleFailure=User {0} does NOT have role {1}
  -jdbcRealm.hasRoleSuccess=User {0} has role {1}
  -jdbcRealm.hasRoleSQLException=There was an SQLException while in hasRole: {0}
  -jdbcRealm.notStarted=This Realm has not yet been started
  -jdbcRealm.checkConnectionDBClosed=The database connection is null or was found to 
be closed. Trying to re-open it.
  -jdbcRealm.checkConnectionDBReOpenFail=The re-open on the database failed. The 
database could be down.
  -jdbcRealm.checkConnectionClassNotFoundException=JDBC driver class not found {0}
  +jdbcRealm.authenticateFailure=Username {0} NOT successfully authenticated
  +jdbcRealm.authenticateSuccess=Username {0} successfully authenticated
  +jdbcRealm.close=Exception closing database connection
  +jdbcRealm.exception=Exception performing authentication
  +jdbcRealm.open=Exception opening database connection
  +memoryRealm.authenticateFailure=Username {0} NOT successfully authenticated
  +memoryRealm.authenticateSuccess=Username {0} successfully authenticated
  +memoryRealm.loadExist=Memory database file {0} cannot be read
  +memoryRealm.loadPath=Loading users from memory database file {0}
  +memoryRealm.readXml=Exception while reading memory database file
  +realmBase.algorithm=Invalid message digest algorithm {0} specified
  +realmBase.alreadyStarted=This Realm has already been started
  +realmBase.digest=Error digesting user credentials
  +realmBase.hasRoleFailure=Username {0} does NOT have role {1}
  +realmBase.hasRoleSuccess=Username {0} has role {1}
  +realmBase.notStarted=This Realm has not yet been started
  
  
  
  1.4       +49 -60    
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/MemoryRealm.java
  
  Index: MemoryRealm.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/MemoryRealm.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- MemoryRealm.java  2001/04/01 02:29:46     1.3
  +++ MemoryRealm.java  2001/04/11 01:46:09     1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/MemoryRealm.java,v
 1.3 2001/04/01 02:29:46 craigmcc Exp $
  - * $Revision: 1.3 $
  - * $Date: 2001/04/01 02:29:46 $
  + * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/MemoryRealm.java,v
 1.4 2001/04/11 01:46:09 craigmcc Exp $
  + * $Revision: 1.4 $
  + * $Date: 2001/04/11 01:46:09 $
    *
    * ====================================================================
    *
  @@ -65,8 +65,6 @@
   package org.apache.catalina.realm;
   
   
  -import java.beans.PropertyChangeListener;
  -import java.beans.PropertyChangeSupport;
   import java.security.Principal;
   import java.io.File;
   import java.util.ArrayList;
  @@ -97,7 +95,7 @@
    * synchronization is performed around accesses to the principals collection.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.3 $ $Date: 2001/04/01 02:29:46 $
  + * @version $Revision: 1.4 $ $Date: 2001/04/11 01:46:09 $
    */
   
   public final class MemoryRealm
  @@ -167,17 +165,30 @@
   
       }
   
  +
       /**
  -     * Return short name of this Realm implementation
  +     * Return the pathname of our XML file containing user definitions.
        */
  -    public String getName() {
  +    public String getPathname() {
   
  -     return name;
  +        return pathname;
   
       }
   
   
  +    /**
  +     * Set the pathname of our XML file containing user definitions.  If a
  +     * relative pathname is specified, it is resolved against "catalina.home".
  +     *
  +     * @param pathname The new pathname
  +     */
  +    public void setPathname(String pathname) {
  +
  +        this.pathname = pathname;
   
  +    }
  +
  +
       // --------------------------------------------------------- Public Methods
   
   
  @@ -194,12 +205,12 @@
        GenericPrincipal principal =
            (GenericPrincipal) principals.get(username);
        if ((principal != null) &&
  -         (credentials.equals(principal.getPassword()))) {
  -         if (debug > 1)
  +         (digest(credentials).equals(principal.getPassword()))) {
  +         if (debug >= 2)
                log(sm.getString("memoryRealm.authenticateSuccess", username));
            return (principal);
        } else {
  -         if (debug > 1)
  +         if (debug >= 2)
                log(sm.getString("memoryRealm.authenticateFailure", username));
            return (null);
        }
  @@ -207,35 +218,6 @@
       }
   
   
  -    /**
  -     * Return <code>true</code> if the specified Principal has the specified
  -     * security role, within the context of this Realm; otherwise return
  -     * <code>false</code>.
  -     *
  -     * @param principal Principal for whom the role is to be checked
  -     * @param role Security role to be checked
  -     */
  -    public boolean hasRole(Principal principal, String role) {
  -
  -     if ((principal == null) || (role == null) ||
  -         !(principal instanceof GenericPrincipal))
  -         return (false);
  -        GenericPrincipal gp = (GenericPrincipal) principal;
  -        if (!(gp.getRealm() == this))
  -            return (false);
  -     boolean result = gp.hasRole(role);
  -     if (debug > 1) {
  -         String name = principal.getName();
  -         if (result)
  -             log(sm.getString("memoryRealm.hasRoleSuccess", name, role));
  -         else
  -             log(sm.getString("memoryRealm.hasRoleFailure", name, role));
  -     }
  -     return (result);
  -
  -    }
  -
  -
       // -------------------------------------------------------- Package Methods
   
   
  @@ -272,9 +254,20 @@
   
   
       /**
  +     * Return a short name for this Realm implementation.
  +     */
  +    protected String getName() {
  +
  +        return (this.name);
  +
  +    }
  +
  +
  +    /**
        * Return the password associated with the given principal's user name.
        */
       protected String getPassword(String username) {
  +
        GenericPrincipal principal =
            (GenericPrincipal) principals.get(username);
        if (principal != null) {
  @@ -282,6 +275,7 @@
        } else {
            return (null);
        }
  +
       }
   
   
  @@ -289,9 +283,10 @@
        * Return the Principal associated with the given user name.
        */
       protected Principal getPrincipal(String username) {
  +
        return (Principal) principals.get(username);
  -    }
   
  +    }
   
   
       // ------------------------------------------------------ Lifecycle Methods
  @@ -307,33 +302,31 @@
        */
       public synchronized void start() throws LifecycleException {
   
  -     // Validate and update our current component state
  -     if (started)
  -         throw new LifecycleException
  -             (sm.getString("memoryRealm.alreadyStarted"));
  -     lifecycle.fireLifecycleEvent(START_EVENT, null);
  -     started = true;
  -
        // Validate the existence of our database file
        File file = new File(pathname);
        if (!file.isAbsolute())
            file = new File(System.getProperty("catalina.home") +
                            File.separator + pathname);
  -     if (!file.exists())
  +     if (!file.exists() || !file.canRead())
            throw new LifecycleException
  -             (sm.getString("memoryRealm.loadExist", pathname));
  +             (sm.getString("memoryRealm.loadExist",
  +                              file.getAbsolutePath()));
   
        // Load the contents of the database file
  -     if (debug > 0)
  -         log(sm.getString("memoryRealm.loadPath", pathname));
  +     if (debug >= 1)
  +         log(sm.getString("memoryRealm.loadPath",
  +                             file.getAbsolutePath()));
        XmlMapper mapper = new XmlMapper();
        mapper.addRule("tomcat-users/user", new MemoryRealmUserAction());
        try {
            mapper.readXml(file, this);
        } catch (Exception e) {
  -         throw new LifecycleException("MemoryRealm.start.readXml: " + e, e);
  +         throw new LifecycleException("memoryRealm.readXml", e);
        }
   
  +        // Perform normal superclass initialization
  +        super.start();
  +
       }
   
   
  @@ -346,12 +339,8 @@
        */
       public synchronized void stop() throws LifecycleException {
   
  -     // Validate and update our current component state
  -     if (!started)
  -         throw new LifecycleException
  -             (sm.getString("memoryRealm.notStarted"));
  -     lifecycle.fireLifecycleEvent(STOP_EVENT, null);
  -     started = false;
  +        // Perform normal superclass finalization
  +        super.stop();
   
        // No shutdown activities required
   
  
  
  
  1.3       +148 -50   
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/RealmBase.java
  
  Index: RealmBase.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/RealmBase.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- RealmBase.java    2000/12/31 16:30:35     1.2
  +++ RealmBase.java    2001/04/11 01:46:09     1.3
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/RealmBase.java,v
 1.2 2000/12/31 16:30:35 nacho Exp $
  - * $Revision: 1.2 $
  - * $Date: 2000/12/31 16:30:35 $
  + * $Header: 
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/RealmBase.java,v
 1.3 2001/04/11 01:46:09 craigmcc Exp $
  + * $Revision: 1.3 $
  + * $Date: 2001/04/11 01:46:09 $
    *
    * ====================================================================
    *
  @@ -78,6 +78,7 @@
   import org.apache.catalina.LifecycleListener;
   import org.apache.catalina.Logger;
   import org.apache.catalina.Realm;
  +import org.apache.catalina.util.HexUtils;
   import org.apache.catalina.util.LifecycleSupport;
   import org.apache.catalina.util.StringManager;
   import org.apache.catalina.util.MD5Encoder;
  @@ -93,7 +94,7 @@
    * location) are identical to those currently supported by Tomcat 3.X.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.2 $ $Date: 2000/12/31 16:30:35 $
  + * @version $Revision: 1.3 $ $Date: 2001/04/11 01:46:09 $
    */
   
   public abstract class RealmBase
  @@ -116,6 +117,15 @@
   
   
       /**
  +     * Digest algorithm used in storing passwords in a non-plaintext format.
  +     * Valid values are those accepted for the algorithm name by the
  +     * MessageDigest class, or <code>null</code> if no digesting should
  +     * be performed.
  +     */
  +    protected String digest = null;
  +
  +
  +    /**
        * Descriptive information about this Realm implementation.
        */
       protected static final String info =
  @@ -123,45 +133,46 @@
   
   
       /**
  -     * Short name for this Realm Implementation
  +     * The lifecycle event support for this component.
        */
  -    protected static final String name = "RealmBase";
  +    protected LifecycleSupport lifecycle = new LifecycleSupport(this);
   
  +
       /**
  -     * The lifecycle event support for this component.
  +     * The MessageDigest object for digesting user credentials (passwords).
        */
  -    protected LifecycleSupport lifecycle = new LifecycleSupport(this);
  +    protected MessageDigest md = null;
   
   
       /**
  -     * The string manager for this package.
  +     * The MD5 helper object for this class.
        */
  -    protected static StringManager sm =
  -     StringManager.getManager(Constants.Package);
  +    protected static final MD5Encoder md5Encoder = new MD5Encoder();
   
   
       /**
  -     * Has this component been started?
  +     * MD5 message digest provider.
        */
  -    protected boolean started = false;
  +    protected static MessageDigest md5Helper;
   
   
       /**
  -     * The property change support for this component.
  +     * The string manager for this package.
        */
  -    protected PropertyChangeSupport support = new PropertyChangeSupport(this);
  +    protected static StringManager sm =
  +     StringManager.getManager(Constants.Package);
   
   
       /**
  -     * MD5 message digest provider.
  +     * Has this component been started?
        */
  -    protected static MessageDigest md5Helper;
  +    protected boolean started = false;
   
   
       /**
  -     * The MD5 helper object for this class.
  +     * The property change support for this component.
        */
  -    protected static final MD5Encoder md5Encoder = new MD5Encoder();
  +    protected PropertyChangeSupport support = new PropertyChangeSupport(this);
   
   
       // ------------------------------------------------------------- Properties
  @@ -194,7 +205,9 @@
        * Return the debugging detail level for this component.
        */
       public int getDebug() {
  +
        return (this.debug);
  +
       }
   
   
  @@ -204,30 +217,46 @@
        * @param debug The new debugging detail level
        */
       public void setDebug(int debug) {
  +
        this.debug = debug;
  +
       }
   
   
       /**
  -     * Return descriptive information about this Realm implementation and
  -     * the corresponding version number, in the format
  -     * <code>&lt;description&gt;/&lt;version&gt;</code>.
  +     * Return the digest algorithm  used for storing credentials.
        */
  -    public String getInfo() {
  +    public String getDigest() {
   
  -     return info;
  +        return digest;
   
       }
   
  +
       /**
  -     * Return short name of this Realm implementation
  +     * Set the digest algorithm used for storing credentials.
  +     *
  +     * @param digest The new digest algorithm
        */
  -    public String getName() {
  +    public void setDigest(String digest) {
   
  -     return name;
  +        this.digest = digest;
   
       }
   
  +
  +    /**
  +     * Return descriptive information about this Realm implementation and
  +     * the corresponding version number, in the format
  +     * <code>&lt;description&gt;/&lt;version&gt;</code>.
  +     */
  +    public String getInfo() {
  +
  +     return info;
  +
  +    }
  +
  +
       // --------------------------------------------------------- Public Methods
   
   
  @@ -332,14 +361,35 @@
       /**
        * Return <code>true</code> if the specified Principal has the specified
        * security role, within the context of this Realm; otherwise return
  -     * <code>false</code>.
  +     * <code>false</code>.  This method can be overridden by Realm
  +     * implementations, but the default is adequate when an instance of
  +     * <code>GenericPrincipal</code> is used to represent authenticated
  +     * Principals from this Realm.
        *
        * @param principal Principal for whom the role is to be checked
        * @param role Security role to be checked
        */
  -    public abstract boolean hasRole(Principal principal, String role);
  +    public boolean hasRole(Principal principal, String role) {
   
  +     if ((principal == null) || (role == null) ||
  +         !(principal instanceof GenericPrincipal))
  +         return (false);
  +        GenericPrincipal gp = (GenericPrincipal) principal;
  +        if (!(gp.getRealm() == this))
  +            return (false);
  +     boolean result = gp.hasRole(role);
  +     if (debug >= 2) {
  +         String name = principal.getName();
  +         if (result)
  +             log(sm.getString("realmBase.hasRoleSuccess", name, role));
  +         else
  +             log(sm.getString("realmBase.hasRoleFailure", name, role));
  +     }
  +     return (result);
  +
  +    }
   
  +
       /**
        * Remove a property change listener from this component.
        *
  @@ -390,16 +440,25 @@
        * @exception LifecycleException if this component detects a fatal error
        *  that prevents this component from being used
        */
  -    public void start()
  -        throws LifecycleException {
  +    public void start() throws LifecycleException {
   
        // Validate and update our current component state
        if (started)
  -         throw new LifecycleException
  -             (sm.getString("memoryRealm.alreadyStarted"));
  +         throw new IllegalStateException
  +             (sm.getString("realmBase.alreadyStarted"));
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;
   
  +        // Create a MessageDigest instance for credentials, if desired
  +        if (digest != null) {
  +            try {
  +                md = MessageDigest.getInstance(digest);
  +            } catch (NoSuchAlgorithmException e) {
  +                throw new LifecycleException
  +                    (sm.getString("realmBase.algorithm", digest), e);
  +            }
  +        }
  +
       }
   
   
  @@ -418,11 +477,14 @@
   
        // Validate and update our current component state
        if (!started)
  -         throw new LifecycleException
  -             (sm.getString("memoryRealm.notStarted"));
  +         throw new IllegalStateException
  +             (sm.getString("realmBase.notStarted"));
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;
   
  +        // Clean up allocated resources
  +        md = null;
  +
       }
   
   
  @@ -430,6 +492,39 @@
   
   
       /**
  +     * Digest the password using the specified algorithm and
  +     * convert the result to a corresponding hexadecimal string.
  +     * If exception, the plain credentials string is returned.
  +     *
  +     * <strong>IMPLEMENTATION NOTE</strong> - This implementation is
  +     * synchronized because it reuses the MessageDigest instance.
  +     * This should be faster than cloning the instance on every request.
  +     *
  +     * @param credentials Password or other credentials to use in
  +     *  authenticating this username
  +     */
  +    protected String digest(String credentials)  {
  +
  +        // If no MessageDigest instance is specified, return unchanged
  +        if (md == null)
  +            return (credentials);
  +
  +        // Digest the user credentials and return as hexadecimal
  +        synchronized (this) {
  +            try {
  +                md.reset();
  +                md.update(credentials.getBytes());
  +                return (HexUtils.convert(md.digest()));
  +            } catch (Exception e) {
  +                log(sm.getString("realmBase.digest"), e);
  +                return (credentials);
  +            }
  +        }
  +
  +    }
  +
  +
  +    /**
        * Return the digest associated with given principal's user name.
        */
       protected String getDigest(String username, String realmName) {
  @@ -450,6 +545,13 @@
   
   
       /**
  +     * Return a short name for this Realm implementation, for use in
  +     * log messages.
  +     */
  +    protected abstract String getName();
  +
  +
  +    /**
        * Return the password associated with the given principal's user name.
        */
       protected abstract String getPassword(String username);
  @@ -467,21 +569,20 @@
        * @param message Message to be logged
        */
       protected void log(String message) {
  -     Logger logger = null;
   
  +     Logger logger = null;
  +        String name = null;
        if (container != null) {
            logger = container.getLogger();
  +            name = container.getName();
           }
   
        if (logger != null) {
  -         logger.log(getName()+"[" + container.getName() + "]: " + message);
  +         logger.log(getName()+"[" + name + "]: " + message);
           } else {
  -         String containerName = null;
  -         if (container != null) {
  -             containerName = container.getName();
  -            }
  -         System.out.println(getName()+"[" + containerName + "]: " + message);
  +         System.out.println(getName()+"[" + name + "]: " + message);
        }
  +
       }
   
   
  @@ -492,21 +593,18 @@
        * @param throwable Associated exception
        */
       protected void log(String message, Throwable throwable) {
  -     Logger logger = null;
   
  +     Logger logger = null;
  +        String name = null;
        if (container != null) {
            logger = container.getLogger();
  +            name = container.getName();
           }
   
        if (logger != null) {
  -         logger.log(getName()+"[" + container.getName() + "]: " + message, 
throwable);
  +         logger.log(getName()+"[" + name + "]: " + message, throwable);
           } else {
  -         String containerName = null;
  -         if (container != null) {
  -             containerName = container.getName();
  -            }
  -         System.out.println(getName()+"[" + containerName + "]: " + message);
  -         System.out.println("" + throwable);
  +         System.out.println(getName()+"[" + name + "]: " + message);
            throwable.printStackTrace(System.out);
        }
       }
  
  
  

Reply via email to