craigmcc 01/04/13 12:57:45
Modified: catalina/src/share/org/apache/catalina/realm JDBCRealm.java
Log:
Refactor so that this class can be easily specialized by subclassing (including
the creation of an implementation that uses a connection pool instead).
Revision Changes Path
1.13 +104 -57
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.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- JDBCRealm.java 2001/04/11 01:46:09 1.12
+++ JDBCRealm.java 2001/04/13 19:57:45 1.13
@@ -86,14 +86,14 @@
* See the JDBCRealm.howto for more details on how to set up the database and
* for configuration options.
*
- * TODO:
- * - Make sure no bad chars can get in and trick the auth and hasrole
- * - Use a database connection pool for faster simultaneous access
+ * <p><strong>TODO</strong> - Support connection pooling (including message
+ * format objects) so that <code>authenticate()</code> does not have to be
+ * synchronized.</p>
*
* @author Craig R. McClanahan
* @author Carson McDonald
* @author Ignacio Ortega
- * @version $Revision: 1.12 $ $Date: 2001/04/11 01:46:09 $
+ * @version $Revision: 1.13 $ $Date: 2001/04/13 19:57:45 $
*/
public class JDBCRealm
@@ -307,57 +307,28 @@
* event is also logged, and the connection will be closed so that
* a subsequent request will automatically re-open it.
*
- * <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
* authenticating this username
*/
- public synchronized Principal authenticate(String username,
- String credentials) {
+ public Principal authenticate(String username, String credentials) {
+
+ Connection dbConnection = null;
try {
- // Ensure that our database connection is open
- open();
+ // Ensure that we have an open database connection
+ dbConnection = open();
- // 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);
+ // Acquire a Principal object for this user
+ Principal principal = authenticate(dbConnection,
+ username, credentials);
- // 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));
- return (null);
- }
-
- // 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();
+ // Release the database connection we just used
+ release(dbConnection);
- // Create and return a suitable Principal for this user
- return (new GenericPrincipal(this, username, credentials, list));
+ // Return the Principal (if any)
+ return (principal);
} catch (SQLException e) {
@@ -365,7 +336,8 @@
log(sm.getString("jdbcRealm.exception"), e);
// Close the connection so that it gets reopened next time
- close();
+ if (dbConnection != null)
+ close(dbConnection);
// Return "not authenticated" for this request
return (null);
@@ -382,10 +354,68 @@
/**
- * Close any database connection that is currently open.
+ * Return the Principal associated with the specified username and
+ * credentials, if there is one; otherwise return <code>null</code>.
+ *
+ * @param dbConnection The database connection to be used
+ * @param username Username of the Principal to look up
+ * @param credentials Password or other credentials to use in
+ * authenticating this username
+ *
+ * @exception SQLException if a database error occurs
*/
- protected void close() {
+ public synchronized Principal authenticate(Connection dbConnection,
+ String username,
+ String credentials)
+ throws SQLException {
+
+ // Look up the user's credentials
+ String dbCredentials = null;
+ PreparedStatement stmt = credentials(dbConnection, 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));
+ return (null);
+ }
+
+ // Accumulate the user's roles
+ ArrayList list = new ArrayList();
+ stmt = roles(dbConnection, 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));
+
+ }
+
+
+ /**
+ * Close the specified database connection.
+ *
+ * @param dbConnection The connection to be closed
+ */
+ protected void close(Connection dbConnection) {
+
// Do nothing if the database connection is already closed
if (dbConnection == null)
return;
@@ -410,9 +440,9 @@
}
// Release resources associated with the closed connection
- dbConnection = null;
- preparedCredentials = null;
- preparedRoles = null;
+ this.dbConnection = null;
+ this.preparedCredentials = null;
+ this.preparedRoles = null;
}
@@ -421,11 +451,13 @@
* Return a PreparedStatement configured to perform the SELECT required
* to retrieve user credentials for the specified username.
*
+ * @param dbConnection The database connection to be used
* @param username Username for which credentials should be retrieved
*
* @exception SQLException if a database error occurs
*/
- protected PreparedStatement credentials(String username)
+ protected PreparedStatement credentials(Connection dbConnection,
+ String username)
throws SQLException {
if (preparedCredentials == null) {
@@ -477,15 +509,16 @@
/**
- * Open a database connection for use by this Realm.
+ * Open (if necessary) and return a database connection for use by
+ * this Realm.
*
* @exception SQLException if a database error occurs
*/
- protected void open() throws SQLException {
+ protected Connection open() throws SQLException {
// Do nothing if there is a database connection already open
if (dbConnection != null)
- return;
+ return (dbConnection);
// Instantiate our database driver if necessary
if (driver == null) {
@@ -504,6 +537,19 @@
if (connectionPassword != null)
props.put("password", connectionPassword);
dbConnection = driver.connect(connectionURL, props);
+ return (dbConnection);
+
+ }
+
+
+ /**
+ * Release our use of this connection so that it can be recycled.
+ *
+ * @param dbConnnection The connection to be released
+ */
+ protected void release(Connection dbConnection) {
+
+ ; // NO-OP since we are not pooling anything
}
@@ -512,11 +558,12 @@
* Return a PreparedStatement configured to perform the SELECT required
* to retrieve user roles for the specified username.
*
+ * @param dbConnection The database connection to be used
* @param username Username for which roles should be retrieved
*
* @exception SQLException if a database error occurs
*/
- protected PreparedStatement roles(String username)
+ protected PreparedStatement roles(Connection dbConnection, String username)
throws SQLException {
if (preparedRoles == null) {
@@ -580,7 +627,7 @@
super.stop();
// Close any open DB connection
- close();
+ close(this.dbConnection);
}