pgoldstein 2002/08/12 00:41:37
Modified: src/java/org/apache/james/userrepository
AbstractJdbcUsersRepository.java
src/java/org/apache/james/mailrepository
JDBCMailRepository.java JDBCSpoolRepository.java
MimeMessageJDBCSource.java
src/java/org/apache/james/transport/mailets JDBCAlias.java
JDBCListserv.java
src/java/org/apache/james/util/mordred JdbcDataSource.java
Added: src/java/org/apache/james/util JDBCUtil.java
Log:
This is a patch to resolve observed issues with database resource
cleanup when an exceptional condition is encountered. This is
a modification of the patch submitted by Samuel Sadek at the end
of May. Noel Bergman made very substantial contributions to this
patch.
The paradigm for resource closure, contrary to the original patch,
is the use of finally clauses to ensure that the resources are
closed under all conditions.
Revision Changes Path
1.7 +103 -71
jakarta-james/src/java/org/apache/james/userrepository/AbstractJdbcUsersRepository.java
Index: AbstractJdbcUsersRepository.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/userrepository/AbstractJdbcUsersRepository.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- AbstractJdbcUsersRepository.java 28 Jul 2002 20:49:29 -0000 1.6
+++ AbstractJdbcUsersRepository.java 12 Aug 2002 07:41:36 -0000 1.7
@@ -23,6 +23,7 @@
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.phoenix.BlockContext;
import org.apache.james.services.User;
+import org.apache.james.util.JDBCUtil;
import org.apache.james.util.SqlResources;
import java.io.File;
@@ -77,6 +78,8 @@
// Creates a single table with "username" the Primary Key.
private String m_createUserTableSql;
+ // The JDBCUtil helper class
+ private JDBCUtil theJDBCUtil;
public void contextualize(final Context context)
throws ContextException {
@@ -89,7 +92,15 @@
public void compose( final ComponentManager componentManager )
throws ComponentException
{
- getLogger().debug(this.getClass().getName() + ".compose()");
+ StringBuffer logBuffer = null;
+ if (getLogger().isDebugEnabled())
+ {
+ logBuffer =
+ new StringBuffer(64)
+ .append(this.getClass().getName())
+ .append(".compose()");
+ getLogger().debug( logBuffer.toString() );
+ }
m_datasources =
(DataSourceSelector)componentManager.lookup( DataSourceSelector.ROLE );
@@ -112,7 +123,14 @@
*/
public void configure(Configuration configuration) throws
ConfigurationException
{
- getLogger().debug(this.getClass().getName() + ".configure()");
+ StringBuffer logBuffer = null;
+ if (getLogger().isDebugEnabled()) {
+ logBuffer =
+ new StringBuffer(64)
+ .append(this.getClass().getName())
+ .append(".configure()");
+ getLogger().debug( logBuffer.toString() );
+ }
// Parse the DestinationURL for the name of the datasource,
// the table to use, and the (optional) repository Key.
@@ -147,8 +165,16 @@
"Must be of the format \"db://<data-source>[/<table>[/<key>]]\".");
}
- getLogger().debug("Parsed URL: table = '" + m_sqlParameters.get("table") +
- "', key = '" + m_sqlParameters.get("key") + "'");
+ if (getLogger().isDebugEnabled()) {
+ logBuffer =
+ new StringBuffer(128)
+ .append("Parsed URL: table = '")
+ .append(m_sqlParameters.get("table"))
+ .append("', key = '")
+ .append(m_sqlParameters.get("key"))
+ .append("'");
+ getLogger().debug(logBuffer.toString());
+ }
// Get the SQL file location
m_sqlFileName = configuration.getChild("sqlFile", true).getValue();
@@ -179,7 +205,21 @@
*/
public void initialize() throws Exception
{
- getLogger().debug( this.getClass().getName() + ".initialize()");
+ StringBuffer logBuffer = null;
+ if (getLogger().isDebugEnabled()) {
+ logBuffer =
+ new StringBuffer(128)
+ .append(this.getClass().getName())
+ .append(".initialize()");
+ getLogger().debug( logBuffer.toString() );
+ }
+
+ theJDBCUtil =
+ new JDBCUtil() {
+ protected void delegatedLog(String logString) {
+
AbstractJdbcUsersRepository.this.getLogger().warn("AbstractJdbcUsersRepository: " +
logString);
+ }
+ };
// Get the data-source required.
m_datasource = (DataSourceComponent)m_datasources.select(m_datasourceName);
@@ -197,9 +237,16 @@
}
File sqlFile = (new File(fileName)).getCanonicalFile();
- getLogger().debug("Reading SQL resources from file: " +
- sqlFile.getAbsolutePath() + ", section " +
- this.getClass().getName() + ".");
+ if (getLogger().isDebugEnabled()) {
+ logBuffer =
+ new StringBuffer(256)
+ .append("Reading SQL resources from file: ")
+ .append(sqlFile.getAbsolutePath())
+ .append(", section ")
+ .append(this.getClass().getName())
+ .append(".");
+ getLogger().debug(logBuffer.toString());
+ }
SqlResources sqlStatements = new SqlResources();
sqlStatements.init(sqlFile, this.getClass().getName(),
@@ -233,46 +280,46 @@
/*
String tableName = m_tableName;
if ( dbMetaData.storesLowerCaseIdentifiers() ) {
- tableName = tableName.toLowerCase();
+ tableName = tableName.toLowerCase(Locale.US);
}
else if ( dbMetaData.storesUpperCaseIdentifiers() ) {
- tableName = tableName.toUpperCase();
+ tableName = tableName.toUpperCase(Locale.US);
}
*/
// Try UPPER, lower, and MixedCase, to see if the table is there.
- if (! ( tableExists(dbMetaData, tableName) ||
- tableExists(dbMetaData, tableName.toUpperCase()) ||
- tableExists(dbMetaData, tableName.toLowerCase()) ))
+ if (! theJDBCUtil.tableExists(dbMetaData, tableName))
{
// Users table doesn't exist - create it.
- PreparedStatement createStatement =
- conn.prepareStatement(m_createUserTableSql);
- createStatement.execute();
- createStatement.close();
+ PreparedStatement createStatement = null;
+ try {
+ createStatement =
+ conn.prepareStatement(m_createUserTableSql);
+ createStatement.execute();
+ } finally {
+ theJDBCUtil.closeJDBCStatement(createStatement);
+ }
- getLogger().info(this.getClass().getName() + ": Created table \'" +
- tableName + "\'.");
+ logBuffer =
+ new StringBuffer(128)
+ .append(this.getClass().getName())
+ .append(": Created table \'")
+ .append(tableName)
+ .append("\'.");
+ getLogger().info(logBuffer.toString());
}
else {
- getLogger().debug("Using table: " + tableName);
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Using table: " + tableName);
+ }
}
}
finally {
- closeConnection( conn );
+ theJDBCUtil.closeJDBCConnection( 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
//
@@ -284,27 +331,28 @@
List userList = new LinkedList(); // Build the users into this list.
Connection conn = openConnection();
+ PreparedStatement getUsersStatement = null;
+ ResultSet rsUsers = null;
try {
// Get a ResultSet containing all users.
- PreparedStatement getUsersStatement =
+ getUsersStatement =
conn.prepareStatement(m_getUsersSql);
- ResultSet rsUsers = getUsersStatement.executeQuery();
+ 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);
+ theJDBCUtil.closeJDBCResultSet(rsUsers);
+ theJDBCUtil.closeJDBCStatement(getUsersStatement);
+ theJDBCUtil.closeJDBCConnection(conn);
}
return userList.iterator();
@@ -316,23 +364,24 @@
*/
protected void doAddUser(User user) {
Connection conn = openConnection();
+ PreparedStatement addUserStatement = null;
+
// Insert into the database.
try {
// Get a PreparedStatement for the insert.
- PreparedStatement addUserStatement =
+ 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);
+ } finally {
+ theJDBCUtil.closeJDBCStatement(addUserStatement);
+ theJDBCUtil.closeJDBCConnection(conn);
}
}
@@ -344,19 +393,20 @@
String username = user.getUserName();
Connection conn = openConnection();
+ PreparedStatement removeUserStatement = null;
+
// Delete from the database.
try {
- PreparedStatement removeUserStatement =
conn.prepareStatement(m_deleteUserSql);
+ 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);
+ } finally {
+ theJDBCUtil.closeJDBCStatement(removeUserStatement);
+ theJDBCUtil.closeJDBCConnection(conn);
}
}
@@ -366,23 +416,20 @@
protected void doUpdateUser(User user)
{
Connection conn = openConnection();
+ PreparedStatement updateUserStatement = null;
// Update the database.
try {
- PreparedStatement updateUserStatement =
conn.prepareStatement(m_updateUserSql);
-
+ 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);
+ } finally {
+ theJDBCUtil.closeJDBCStatement(updateUserStatement);
+ theJDBCUtil.closeJDBCConnection(conn);
}
}
@@ -409,7 +456,7 @@
PreparedStatement getUsersStatement =
conn.prepareStatement(sql);
- getUsersStatement.setString(1, name.toLowerCase());
+ getUsersStatement.setString(1, name.toLowerCase(Locale.US));
ResultSet rsUsers = getUsersStatement.executeQuery();
@@ -432,7 +479,7 @@
throw new CascadingRuntimeException("Error accessing database", sqlExc);
}
finally {
- closeConnection(conn);
+ theJDBCUtil.closeJDBCConnection(conn);
}
}
@@ -496,21 +543,6 @@
"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/util/JDBCUtil.java
Index: JDBCUtil.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.util;
import java.sql.*;
import java.util.Locale;
/**
* Helper class for managing common JDBC tasks.
*
* This class is abstract to allow implementations to
* take advantage of different logging capabilities/interfaces in
* different parts of the code.
*
* @author Noel Bergman <[EMAIL PROTECTED]>
* @author Peter M. Goldstein <[EMAIL PROTECTED]>
*
*/
abstract public class JDBCUtil
{
abstract protected void delegatedLog(String errorString);
/**
* Checks database metadata to see if a table exists.
* Try UPPER, lower, and MixedCase, to see if the table is there.
*
* @param dbMetaData the database metadata to be used to look up this table
* @param tableName the table name
*
* @exception SQLException thrown if an exception is encountered while accessing
the database
*/
public boolean tableExists(DatabaseMetaData dbMetaData, String tableName)
throws SQLException {
return ( tableExistsCaseSensitive(dbMetaData, tableName) ||
tableExistsCaseSensitive(dbMetaData,
tableName.toUpperCase(Locale.US)) ||
tableExistsCaseSensitive(dbMetaData,
tableName.toLowerCase(Locale.US)) );
}
/**
* Checks database metadata to see if a table exists. This method
* is sensitive to the case of the provided table name.
*
* @param dbMetaData the database metadata to be used to look up this table
* @param tableName the case sensitive table name
*
* @exception SQLException thrown if an exception is encountered while accessing
the database
*/
public boolean tableExistsCaseSensitive(DatabaseMetaData dbMetaData, String
tableName)
throws SQLException {
ResultSet rsTables = dbMetaData.getTables(null, null, tableName, null);
try {
boolean found = rsTables.next();
return found;
} finally {
closeJDBCResultSet(rsTables);
}
}
/**
* Closes database connection and logs if an error
* is encountered
*
* @param conn the connection to be closed
*/
public void closeJDBCConnection(Connection conn) {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException sqle) {
// Log exception and continue
subclassLogWrapper("Unexpected exception while closing database
connection.");
}
}
/**
* Closes database statement and logs if an error
* is encountered
*
* @param stmt the statement to be closed
*/
public void closeJDBCStatement(Statement stmt) {
try {
if (stmt != null) {
stmt.close();
}
} catch (SQLException sqle) {
// Log exception and continue
subclassLogWrapper("Unexpected exception while closing database
statement.");
}
}
/**
* Closes database result set and logs if an error
* is encountered
*
* @param aResultSet the result set to be closed
*/
public void closeJDBCResultSet(ResultSet aResultSet ) {
try {
if (aResultSet != null) {
aResultSet.close();
}
} catch (SQLException sqle) {
// Log exception and continue
subclassLogWrapper("Unexpected exception while closing database result
set.");
}
}
/**
* Wraps the delegated call to the subclass logging method with a Throwable
* wrapper. All throwables generated by the subclass logging method are
* caught and ignored.
*
* @param logString the raw string to be passed to the logging method implemented
* by the subclass
*/
private void subclassLogWrapper(String logString)
{
try {
delegatedLog(logString);
}
catch(Throwable t) {
// Throwables generated by the logging system are ignored
}
}
}
1.21 +268 -168
jakarta-james/src/java/org/apache/james/mailrepository/JDBCMailRepository.java
Index: JDBCMailRepository.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/mailrepository/JDBCMailRepository.java,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- JDBCMailRepository.java 28 Jul 2002 20:49:28 -0000 1.20
+++ JDBCMailRepository.java 12 Aug 2002 07:41:36 -0000 1.21
@@ -28,6 +28,7 @@
import org.apache.james.core.MailImpl;
import org.apache.james.core.MimeMessageWrapper;
import org.apache.james.services.MailRepository;
+import org.apache.james.util.JDBCUtil;
import org.apache.james.util.Lock;
import org.apache.james.util.SqlResources;
import org.apache.mailet.MailAddress;
@@ -35,6 +36,7 @@
import javax.mail.internet.MimeMessage;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.IOException;
import java.io.OutputStream;
import java.sql.*;
import java.util.*;
@@ -84,6 +86,8 @@
// Contains all of the sql strings for this component.
protected SqlResources sqlQueries;
+ // The JDBCUtil helper class
+ protected JDBCUtil theJDBCUtil;
public void contextualize(final Context context)
throws ContextException {
@@ -91,10 +95,12 @@
}
public void configure(Configuration conf) throws ConfigurationException {
- getLogger().debug(this.getClass().getName() + ".configure()");
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(this.getClass().getName() + ".configure()");
+ }
destination = conf.getAttribute("destinationURL");
- // normalise the destination, to simplify processing.
+ // normalize the destination, to simplify processing.
if ( ! destination.endsWith("/") ) {
destination += "/";
}
@@ -116,9 +122,12 @@
// Build SqlParameters and get datasource name from URL parameters
if (urlParams.size() == 0) {
- throw new ConfigurationException
- ("Malformed destinationURL - Must be of the format '" +
- "db://<data-source>[/<table>[/<repositoryName>]]'. Was passed " +
conf.getAttribute("destinationURL"));
+ StringBuffer exceptionBuffer =
+ new StringBuffer(256)
+ .append("Malformed destinationURL - Must be of the format
'")
+ .append("db://<data-source>[/<table>[/<repositoryName>]]'.
Was passed ")
+ .append(conf.getAttribute("destinationURL"));
+ throw new ConfigurationException(exceptionBuffer.toString());
}
if (urlParams.size() >= 1) {
datasourceName = (String)urlParams.get(0);
@@ -136,8 +145,16 @@
}
}
- getLogger().debug("Parsed URL: table = '" + tableName +
- "', repositoryName = '" + repositoryName + "'");
+ if (getLogger().isDebugEnabled()) {
+ StringBuffer logBuffer =
+ new StringBuffer(128)
+ .append("Parsed URL: table = '")
+ .append(tableName)
+ .append("', repositoryName = '")
+ .append(repositoryName)
+ .append("'");
+ getLogger().debug(logBuffer.toString());
+ }
filestore = conf.getChild("filestore").getValue(null);
sqlFileName = conf.getChild("sqlFile").getValue();
@@ -149,9 +166,16 @@
public void compose( final ComponentManager componentManager )
throws ComponentException {
- getLogger().debug(this.getClass().getName() + ".compose()");
+ StringBuffer logBuffer = null;
+ if (getLogger().isDebugEnabled()) {
+ logBuffer =
+ new StringBuffer(64)
+ .append(this.getClass().getName())
+ .append(".compose()");
+ getLogger().debug(logBuffer.toString());
+ }
- // Get the DataSourceSelector block
+ // Get the DataSourceSelector service
datasources = (DataSourceSelector)componentManager.lookup(
DataSourceSelector.ROLE );
try {
@@ -168,11 +192,20 @@
streamConfiguration.setAttribute( "model", "SYNCHRONOUS" );
sr = (StreamRepository) store.select(streamConfiguration);
- getLogger().debug("Got filestore for JdbcMailRepository: " +
filestore);
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Got filestore for JdbcMailRepository: " +
filestore);
+ }
}
lock = new Lock();
- getLogger().debug(this.getClass().getName() + " created according to "
+ destination);
+ if (getLogger().isDebugEnabled()) {
+ logBuffer =
+ new StringBuffer(128)
+ .append(this.getClass().getName())
+ .append(" created according to ")
+ .append(destination);
+ getLogger().debug(logBuffer.toString());
+ }
} catch (Exception e) {
final String message = "Failed to retrieve Store component:" +
e.getMessage();
getLogger().error(message, e);
@@ -191,13 +224,23 @@
*
*/
public void initialize() throws Exception {
- getLogger().debug(this.getClass().getName() + ".initialize()");
+ StringBuffer logBuffer = null;
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(this.getClass().getName() + ".initialize()");
+ }
+ theJDBCUtil =
+ new JDBCUtil() {
+ protected void delegatedLog(String logString) {
+ JDBCMailRepository.this.getLogger().warn("JDBCMailRepository: "
+ logString);
+ }
+ };
// Get the data-source required.
datasource = (DataSourceComponent)datasources.select(datasourceName);
// Test the connection to the database, by getting the DatabaseMetaData.
Connection conn = datasource.getConnection();
+ PreparedStatement createStatement = null;
try {
// Initialise the sql strings.
@@ -210,9 +253,16 @@
String resourceName =
"org.apache.james.mailrepository.JDBCMailRepository";
- getLogger().debug("Reading SQL resources from file: " +
- sqlFile.getAbsolutePath() + ", section " +
- this.getClass().getName() + ".");
+ if (getLogger().isDebugEnabled()) {
+ logBuffer =
+ new StringBuffer(128)
+ .append("Reading SQL resources from file: ")
+ .append(sqlFile.getAbsolutePath())
+ .append(", section ")
+ .append(this.getClass().getName())
+ .append(".");
+ getLogger().debug(logBuffer.toString());
+ }
// Build the statement parameters
Map sqlParameters = new HashMap();
@@ -231,36 +281,28 @@
DatabaseMetaData dbMetaData = conn.getMetaData();
// Need to ask in the case that identifiers are stored, ask the
DatabaseMetaInfo.
// Try UPPER, lower, and MixedCase, to see if the table is there.
- if (! ( tableExists(dbMetaData, tableName) ||
- tableExists(dbMetaData, tableName.toUpperCase()) ||
- tableExists(dbMetaData, tableName.toLowerCase()) )) {
+ if (!(theJDBCUtil.tableExists(dbMetaData, tableName))) {
// Users table doesn't exist - create it.
- PreparedStatement createStatement =
+ createStatement =
conn.prepareStatement(sqlQueries.getSqlString("createTable",
true));
createStatement.execute();
- createStatement.close();
- getLogger().info("JdbcMailRepository: Created table '" +
- tableName + "'.");
+ if (getLogger().isInfoEnabled()) {
+ logBuffer =
+ new StringBuffer(64)
+ .append("JdbcMailRepository: Created table '")
+ .append(tableName)
+ .append("'.");
+ getLogger().info(logBuffer.toString());
+ }
}
} finally {
- try {
- conn.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
+ theJDBCUtil.closeJDBCStatement(createStatement);
+ theJDBCUtil.closeJDBCConnection(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;
- }
-
public synchronized boolean unlock(String key) {
if (lock.unlock(key)) {
notifyAll();
@@ -294,41 +336,55 @@
//Begin a transaction
conn.setAutoCommit(false);
- PreparedStatement checkMessageExists =
-
conn.prepareStatement(sqlQueries.getSqlString("checkMessageExistsSQL", true));
- checkMessageExists.setString(1, mc.getName());
- checkMessageExists.setString(2, repositoryName);
- ResultSet rsExists = checkMessageExists.executeQuery();
- boolean exists = rsExists.next() && rsExists.getInt(1) > 0;
- rsExists.close();
- checkMessageExists.close();
+ PreparedStatement checkMessageExists = null;
+ ResultSet rsExists = null;
+ boolean exists = false;
+ try {
+ checkMessageExists =
+
conn.prepareStatement(sqlQueries.getSqlString("checkMessageExistsSQL", true));
+ checkMessageExists.setString(1, mc.getName());
+ checkMessageExists.setString(2, repositoryName);
+ rsExists = checkMessageExists.executeQuery();
+ exists = rsExists.next() && rsExists.getInt(1) > 0;
+ } finally {
+ theJDBCUtil.closeJDBCResultSet(rsExists);
+ theJDBCUtil.closeJDBCStatement(checkMessageExists);
+ }
if (exists) {
//Update the existing record
- PreparedStatement updateMessage =
-
conn.prepareStatement(sqlQueries.getSqlString("updateMessageSQL", true));
- updateMessage.setString(1, mc.getState());
- updateMessage.setString(2, mc.getErrorMessage());
- if (mc.getSender() == null) {
- updateMessage.setNull(3, java.sql.Types.VARCHAR);
- } else {
- updateMessage.setString(3, mc.getSender().toString());
- }
- StringBuffer recipients = new StringBuffer();
- for (Iterator i = mc.getRecipients().iterator(); i.hasNext(); ) {
- recipients.append(i.next().toString());
- if (i.hasNext()) {
- recipients.append("\r\n");
+ PreparedStatement updateMessage = null;
+
+ try {
+ updateMessage =
+
conn.prepareStatement(sqlQueries.getSqlString("updateMessageSQL", true));
+ updateMessage.setString(1, mc.getState());
+ updateMessage.setString(2, mc.getErrorMessage());
+ if (mc.getSender() == null) {
+ updateMessage.setNull(3, java.sql.Types.VARCHAR);
+ } else {
+ updateMessage.setString(3, mc.getSender().toString());
}
+ StringBuffer recipients = new StringBuffer();
+ for (Iterator i = mc.getRecipients().iterator(); i.hasNext(); )
{
+ recipients.append(i.next().toString());
+ if (i.hasNext()) {
+ recipients.append("\r\n");
+ }
+ }
+ updateMessage.setString(4, recipients.toString());
+ updateMessage.setString(5, mc.getRemoteHost());
+ updateMessage.setString(6, mc.getRemoteAddr());
+ updateMessage.setTimestamp(7, new
java.sql.Timestamp(mc.getLastUpdated().getTime()));
+ updateMessage.setString(8, mc.getName());
+ updateMessage.setString(9, repositoryName);
+ updateMessage.execute();
+ } finally {
+ Statement localUpdateMessage = updateMessage;
+ // Clear reference to statement
+ updateMessage = null;
+ theJDBCUtil.closeJDBCStatement(localUpdateMessage);
}
- updateMessage.setString(4, recipients.toString());
- updateMessage.setString(5, mc.getRemoteHost());
- updateMessage.setString(6, mc.getRemoteAddr());
- updateMessage.setTimestamp(7, new
java.sql.Timestamp(mc.getLastUpdated().getTime()));
- updateMessage.setString(8, mc.getName());
- updateMessage.setString(9, repositoryName);
- updateMessage.execute();
- updateMessage.close();
//Determine whether the message body has changed, and possibly avoid
// updating the database.
@@ -342,75 +398,87 @@
}
if (saveBody) {
- updateMessage =
-
conn.prepareStatement(sqlQueries.getSqlString("updateMessageBodySQL", true));
- ByteArrayOutputStream headerOut = new ByteArrayOutputStream();
- OutputStream bodyOut = null;
- if (sr == null) {
- //If there is no filestore, use the byte array to store
headers
- // and the body
- bodyOut = headerOut;
- } else {
- //Store the body in the stream repository
- bodyOut = sr.put(mc.getName());
+ try {
+ updateMessage =
+
conn.prepareStatement(sqlQueries.getSqlString("updateMessageBodySQL", true));
+ ByteArrayOutputStream headerOut = new
ByteArrayOutputStream();
+ OutputStream bodyOut = null;
+ try {
+ if (sr == null) {
+ //If there is no filestore, use the byte array to
store headers
+ // and the body
+ bodyOut = headerOut;
+ } else {
+ //Store the body in the stream repository
+ bodyOut = sr.put(mc.getName());
+ }
+
+ //Write the message to the headerOut and bodyOut.
bodyOut goes straight to the file
+ MimeMessageWrapper.writeTo(messageBody, headerOut,
bodyOut);
+
+ //Store the headers in the database
+ updateMessage.setBytes(1, headerOut.toByteArray());
+ } finally {
+ closeOutputStreams(headerOut, bodyOut);
+ }
+ updateMessage.setString(2, mc.getName());
+ updateMessage.setString(3, repositoryName);
+ updateMessage.execute();
+ } finally {
+ theJDBCUtil.closeJDBCStatement(updateMessage);
}
-
- //Write the message to the headerOut and bodyOut. bodyOut goes
straight to the file
- MimeMessageWrapper.writeTo(messageBody, headerOut, bodyOut);
- bodyOut.close();
-
- //Store the headers in the database
- updateMessage.setBytes(1, headerOut.toByteArray());
- updateMessage.setString(2, mc.getName());
- updateMessage.setString(3, repositoryName);
- updateMessage.execute();
- updateMessage.close();
}
} else {
//Insert the record into the database
- PreparedStatement insertMessage =
-
conn.prepareStatement(sqlQueries.getSqlString("insertMessageSQL", true));
- insertMessage.setString(1, mc.getName());
- insertMessage.setString(2, repositoryName);
- insertMessage.setString(3, mc.getState());
- insertMessage.setString(4, mc.getErrorMessage());
- if (mc.getSender() == null) {
- insertMessage.setNull(5, java.sql.Types.VARCHAR);
- } else {
- insertMessage.setString(5, mc.getSender().toString());
- }
- StringBuffer recipients = new StringBuffer();
- for (Iterator i = mc.getRecipients().iterator(); i.hasNext(); ) {
- recipients.append(i.next().toString());
- if (i.hasNext()) {
- recipients.append("\r\n");
+ PreparedStatement insertMessage = null;
+ try {
+ insertMessage =
+
conn.prepareStatement(sqlQueries.getSqlString("insertMessageSQL", true));
+ insertMessage.setString(1, mc.getName());
+ insertMessage.setString(2, repositoryName);
+ insertMessage.setString(3, mc.getState());
+ insertMessage.setString(4, mc.getErrorMessage());
+ if (mc.getSender() == null) {
+ insertMessage.setNull(5, java.sql.Types.VARCHAR);
+ } else {
+ insertMessage.setString(5, mc.getSender().toString());
}
+ StringBuffer recipients = new StringBuffer();
+ for (Iterator i = mc.getRecipients().iterator(); i.hasNext(); )
{
+ recipients.append(i.next().toString());
+ if (i.hasNext()) {
+ recipients.append("\r\n");
+ }
+ }
+ insertMessage.setString(6, recipients.toString());
+ insertMessage.setString(7, mc.getRemoteHost());
+ insertMessage.setString(8, mc.getRemoteAddr());
+ insertMessage.setTimestamp(9, new
java.sql.Timestamp(mc.getLastUpdated().getTime()));
+ MimeMessage messageBody = mc.getMessage();
+
+ ByteArrayOutputStream headerOut = new ByteArrayOutputStream();
+ OutputStream bodyOut = null;
+ try {
+ if (sr == null) {
+ //If there is no sr, then use the same byte array to
hold the headers
+ // and the body
+ bodyOut = headerOut;
+ } else {
+ //Store the body in the file system.
+ bodyOut = sr.put(mc.getName());
+ }
+
+ //Write the message to the headerOut and bodyOut. bodyOut
goes straight to the file
+ MimeMessageWrapper.writeTo(messageBody, headerOut, bodyOut);
+ insertMessage.setBytes(10, headerOut.toByteArray());
+ } finally {
+ closeOutputStreams(headerOut, bodyOut);
+ }
+ //Store the headers in the database
+ insertMessage.execute();
+ } finally {
+ theJDBCUtil.closeJDBCStatement(insertMessage);
}
- insertMessage.setString(6, recipients.toString());
- insertMessage.setString(7, mc.getRemoteHost());
- insertMessage.setString(8, mc.getRemoteAddr());
- insertMessage.setTimestamp(9, new
java.sql.Timestamp(mc.getLastUpdated().getTime()));
- MimeMessage messageBody = mc.getMessage();
-
- ByteArrayOutputStream headerOut = new ByteArrayOutputStream();
- OutputStream bodyOut = null;
- if (sr == null) {
- //If there is no sr, then use the same byte array to hold the
headers
- // and the body
- bodyOut = headerOut;
- } else {
- //Store the body in the file system.
- bodyOut = sr.put(mc.getName());
- }
-
- //Write the message to the headerOut and bodyOut. bodyOut goes
straight to the file
- MimeMessageWrapper.writeTo(messageBody, headerOut, bodyOut);
- bodyOut.close();
-
- //Store the headers in the database
- insertMessage.setBytes(10, headerOut.toByteArray());
- insertMessage.execute();
- insertMessage.close();
}
conn.commit();
@@ -423,13 +491,7 @@
e.printStackTrace();
throw new RuntimeException("Exception caught while storing mail
Container: " + e);
} finally {
- if (conn != null) {
- try {
- conn.close();
- } catch (SQLException sqle) {
- //ignore
- }
- }
+ theJDBCUtil.closeJDBCConnection(conn);
}
}
@@ -438,22 +500,30 @@
System.err.println("retrieving " + key);
}
Connection conn = null;
+ PreparedStatement retrieveMessage = null;
+ ResultSet rsMessage = null;
try {
conn = datasource.getConnection();
if (DEEP_DEBUG) {
System.err.println("got a conn " + key);
}
- PreparedStatement retrieveMessage =
+ retrieveMessage =
conn.prepareStatement(sqlQueries.getSqlString("retrieveMessageSQL",
true));
retrieveMessage.setString(1, key);
retrieveMessage.setString(2, repositoryName);
- ResultSet rsMessage = retrieveMessage.executeQuery();
+ rsMessage = retrieveMessage.executeQuery();
if (DEEP_DEBUG) {
System.err.println("ran the query " + key);
}
if (!rsMessage.next()) {
- throw new RuntimeException("Did not find a record " + key + " in "
+ repositoryName);
+ StringBuffer exceptionBuffer =
+ new StringBuffer(64)
+ .append("Did not find a record ")
+ .append(key)
+ .append(" in ")
+ .append(repositoryName);
+ throw new RuntimeException(exceptionBuffer.toString());
}
MailImpl mc = new MailImpl();
mc.setName(key);
@@ -478,8 +548,6 @@
MimeMessageJDBCSource source = new MimeMessageJDBCSource(this, key, sr);
MimeMessageWrapper message = new MimeMessageWrapper(source);
mc.setMessage(message);
- rsMessage.close();
- retrieveMessage.close();
return mc;
} catch (SQLException sqle) {
synchronized (System.err) {
@@ -495,13 +563,9 @@
me.printStackTrace();
throw new RuntimeException("Exception while retrieving mail: " +
me.getMessage());
} finally {
- if (conn != null) {
- try {
- conn.close();
- } catch (SQLException sqle) {
- //ignore
- }
- }
+ theJDBCUtil.closeJDBCResultSet(rsMessage);
+ theJDBCUtil.closeJDBCStatement(retrieveMessage);
+ theJDBCUtil.closeJDBCConnection(conn);
}
}
@@ -513,14 +577,14 @@
//System.err.println("removing " + key);
if (lock(key)) {
Connection conn = null;
+ PreparedStatement removeMessage = null;
try {
conn = datasource.getConnection();
- PreparedStatement removeMessage =
+ removeMessage =
conn.prepareStatement(sqlQueries.getSqlString("removeMessageSQL", true));
removeMessage.setString(1, key);
removeMessage.setString(2, repositoryName);
removeMessage.execute();
- removeMessage.close();
if (sr != null) {
sr.remove(key);
@@ -528,13 +592,8 @@
} catch (Exception me) {
throw new RuntimeException("Exception while removing mail: " +
me.getMessage());
} finally {
- if (conn != null) {
- try {
- conn.close();
- } catch (SQLException sqle) {
- //ignore
- }
- }
+ theJDBCUtil.closeJDBCStatement(removeMessage);
+ theJDBCUtil.closeJDBCConnection(conn);
unlock(key);
}
}
@@ -543,31 +602,27 @@
public Iterator list() {
//System.err.println("listing messages");
Connection conn = null;
+ PreparedStatement listMessages = null;
+ ResultSet rsListMessages = null;
try {
conn = datasource.getConnection();
- PreparedStatement listMessages =
+ listMessages =
conn.prepareStatement(sqlQueries.getSqlString("listMessagesSQL",
true));
listMessages.setString(1, repositoryName);
- ResultSet rsListMessages = listMessages.executeQuery();
+ rsListMessages = listMessages.executeQuery();
List messageList = new ArrayList();
while (rsListMessages.next()) {
messageList.add(rsListMessages.getString(1));
}
- rsListMessages.close();
- listMessages.close();
return messageList.iterator();
} catch (Exception me) {
me.printStackTrace();
throw new RuntimeException("Exception while listing mail: " +
me.getMessage());
} finally {
- if (conn != null) {
- try {
- conn.close();
- } catch (SQLException sqle) {
- //ignore
- }
- }
+ theJDBCUtil.closeJDBCResultSet(rsListMessages);
+ theJDBCUtil.closeJDBCStatement(listMessages);
+ theJDBCUtil.closeJDBCConnection(conn);
}
}
@@ -579,7 +634,52 @@
if (!(obj instanceof JDBCMailRepository)) {
return false;
}
+ // TODO: Figure out whether other instance variables should be part of
+ // the equals equation
JDBCMailRepository repository = (JDBCMailRepository)obj;
- return repository.tableName.equals(tableName) &&
repository.repositoryName.equals(repositoryName);
+ return ((repository.tableName == tableName) || ((repository.tableName !=
null) && repository.tableName.equals(tableName))) &&
+ ((repository.repositoryName == repositoryName) ||
((repository.repositoryName != null) &&
repository.repositoryName.equals(repositoryName)));
+ }
+
+ /**
+ * Provide a hash code that is consistent with equals for this class
+ *
+ * @return the hash code
+ */
+ public int hashCode() {
+ int result = 17;
+ if (tableName != null) {
+ result = 37 * tableName.hashCode();
+ }
+ if (repositoryName != null) {
+ result = 37 * repositoryName.hashCode();
+ }
+ return result;
+ }
+
+ /**
+ * Closes output streams used to update message
+ *
+ * @headerStream the stream containing header information - potentially the same
+ * as the body stream
+ * @bodyStream the stream containing body information
+ */
+ private void closeOutputStreams(OutputStream headerStream, OutputStream
bodyStream) {
+ try {
+ // If the header stream is not the same as the body stream,
+ // close the header stream here.
+ if ((headerStream != null) && (headerStream != bodyStream)) {
+ headerStream.close();
+ }
+ } catch (IOException ioe) {
+ getLogger().debug("JDBCMailRepository: Unexpected exception while
closing output stream.");
+ }
+ try {
+ if (bodyStream != null) {
+ bodyStream.close();
+ }
+ } catch (IOException ioe) {
+ getLogger().debug("JDBCMailRepository: Unexpected exception while
closing output stream.");
+ }
}
}
1.15 +21 -16
jakarta-james/src/java/org/apache/james/mailrepository/JDBCSpoolRepository.java
Index: JDBCSpoolRepository.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/mailrepository/JDBCSpoolRepository.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- JDBCSpoolRepository.java 27 Feb 2002 04:05:11 -0000 1.14
+++ JDBCSpoolRepository.java 12 Aug 2002 07:41:36 -0000 1.15
@@ -15,6 +15,7 @@
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.sql.Statement;
import java.util.LinkedList;
/**
@@ -108,7 +109,13 @@
//Nothing to do... sleep!
try {
synchronized (this) {
- //System.err.println("waiting : " + WAIT_LIMIT / 1000 + " in "
+ repositoryName);
+ //StringBuffer errorBuffer =
+ // new StringBuffer(128)
+ // .append("waiting : ")
+ // .append(WAIT_LIMIT/1000L)
+ // .append(" in ")
+ // .append(repositoryName);
+ //System.err.println(errorBuffer.toString());
wait(WAIT_LIMIT);
}
} catch (InterruptedException ignored) {
@@ -130,7 +137,7 @@
while ((next = getNextPendingMessage()) != null) {
//Check whether this is time to expire
boolean shouldProcess = false;
- if (next.state.equals(Mail.ERROR)) {
+ if (Mail.ERROR.equals(next.state)) {
//if it's an error message, test the time
long processingTime = delay + next.lastUpdated;
if (processingTime < System.currentTimeMillis()) {
@@ -156,8 +163,15 @@
}
try {
synchronized (this) {
- //System.err.println("waiting " + (sleepUntil -
System.currentTimeMillis()) / 1000 + " in " + repositoryName);
- wait(sleepUntil - System.currentTimeMillis());
+ long waitTime = sleepUntil - System.currentTimeMillis();
+ //StringBuffer errorBuffer =
+ // new StringBuffer(128)
+ // .append("waiting ")
+ // .append((waitTime) / 1000L)
+ // .append(" in ")
+ // .append(repositoryName);
+ //System.err.println(errorBuffer.toString());
+ wait(waitTime);
}
} catch (InterruptedException ignored) {
}
@@ -231,18 +245,9 @@
getLogger().error("Error retrieving pending messages", sqle);
pendingMessagesLoadTime = LOAD_TIME_MININUM * 10 +
System.currentTimeMillis();
} finally {
- try {
- rsListMessages.close();
- } catch (Exception e) {
- }
- try {
- listMessages.close();
- } catch (Exception e) {
- }
- try {
- conn.close();
- } catch (Exception e) {
- }
+ theJDBCUtil.closeJDBCResultSet(rsListMessages);
+ theJDBCUtil.closeJDBCStatement(listMessages);
+ theJDBCUtil.closeJDBCConnection(conn);
}
}
}
1.8 +68 -29
jakarta-james/src/java/org/apache/james/mailrepository/MimeMessageJDBCSource.java
Index: MimeMessageJDBCSource.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/mailrepository/MimeMessageJDBCSource.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- MimeMessageJDBCSource.java 20 Jun 2002 14:42:23 -0000 1.7
+++ MimeMessageJDBCSource.java 12 Aug 2002 07:41:36 -0000 1.8
@@ -9,6 +9,7 @@
import org.apache.avalon.cornerstone.services.store.StreamRepository;
import org.apache.james.core.MimeMessageSource;
+import org.apache.james.util.JDBCUtil;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -18,6 +19,7 @@
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.sql.Statement;
/**
* This class points to a specific message in a repository. This will return an
@@ -34,6 +36,15 @@
String retrieveMessageBodySQL = null;
String retrieveMessageBodySizeSQL = null;
+ // The JDBCUtil helper class
+ private static final JDBCUtil theJDBCUtil =
+ new JDBCUtil() {
+ protected void delegatedLog(String logString) {
+ // No logging available at this point in the code.
+ // Therefore this is a noop method.
+ }
+ };
+
/**
* Construct a MimeMessageSource based on a JDBC repository, a key, and a
* stream repository (where we might store the message body)
@@ -58,7 +69,12 @@
}
public String getSourceId() {
- return repository.repositoryName + "/" + key;
+ StringBuffer sourceIdBuffer =
+ new StringBuffer(128)
+ .append(repository.repositoryName)
+ .append("/")
+ .append(key);
+ return sourceIdBuffer.toString();
}
/**
@@ -67,7 +83,9 @@
* a repository with the entire message in the database, which is how James 1.2
worked.
*/
public synchronized InputStream getInputStream() throws IOException {
- Connection conn =null;
+ Connection conn = null;
+ PreparedStatement retrieveMessageStream = null;
+ ResultSet rsRetrieveMessageStream = null;
try {
conn = repository.getConnection();
@@ -78,25 +96,21 @@
start = System.currentTimeMillis();
System.out.println("starting");
}
- PreparedStatement retrieveMessageStream =
conn.prepareStatement(retrieveMessageBodySQL);
+ retrieveMessageStream = conn.prepareStatement(retrieveMessageBodySQL);
retrieveMessageStream.setString(1, key);
retrieveMessageStream.setString(2, repository.repositoryName);
- ResultSet rsRetrieveMessageStream =
retrieveMessageStream.executeQuery();
+ rsRetrieveMessageStream = retrieveMessageStream.executeQuery();
if (!rsRetrieveMessageStream.next()) {
throw new IOException("Could not find message");
}
headers = rsRetrieveMessageStream.getBytes(1);
- rsRetrieveMessageStream.close();
- retrieveMessageStream.close();
if (DEEP_DEBUG) {
System.err.println("stopping");
System.err.println(System.currentTimeMillis() - start);
}
-
-
InputStream in = new ByteArrayInputStream(headers);
try {
if (sr != null) {
@@ -109,12 +123,11 @@
return in;
} catch (SQLException sqle) {
throw new IOException(sqle.toString());
- }finally {
- try {
- conn.close();
- } catch (Exception e) {
- }
- }
+ } finally {
+ theJDBCUtil.closeJDBCResultSet(rsRetrieveMessageStream);
+ theJDBCUtil.closeJDBCStatement(retrieveMessageStream);
+ theJDBCUtil.closeJDBCConnection(conn);
+ }
}
/**
@@ -126,47 +139,54 @@
System.err.println("no SQL statement to find size");
return super.getMessageSize();
}
-Connection conn=null;
+ Connection conn = null;
+ PreparedStatement retrieveMessageSize = null;
+ ResultSet rsRetrieveMessageSize = null;
try {
conn = repository.getConnection();
- PreparedStatement retrieveMessageSize =
conn.prepareStatement(retrieveMessageBodySizeSQL);
+ retrieveMessageSize = conn.prepareStatement(retrieveMessageBodySizeSQL);
retrieveMessageSize.setString(1, key);
retrieveMessageSize.setString(2, repository.repositoryName);
- ResultSet rsRetrieveMessageSize = retrieveMessageSize.executeQuery();
+ rsRetrieveMessageSize = retrieveMessageSize.executeQuery();
if (!rsRetrieveMessageSize.next()) {
throw new IOException("Could not find message");
}
long size = rsRetrieveMessageSize.getLong(1);
- rsRetrieveMessageSize.close();
- retrieveMessageSize.close();
-
+ InputStream in = null;
try {
if (sr != null) {
- InputStream in = sr.get(key);
+ in = sr.get(key);
int len = 0;
byte[] block = new byte[1024];
while ((len = in.read(block)) > -1) {
size += len;
}
- in.close();
}
} catch (Exception e) {
//ignore this... either sr is null, or the file does not exist
// or something else
+ } finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException ioe) {
+ // Ignored - no access to logger at this point in the code
+ }
}
+
return size;
} catch (SQLException sqle) {
throw new IOException(sqle.toString());
- }finally {
- try {
- conn.close();
- } catch (Exception e) {
- }
- }
+ } finally {
+ theJDBCUtil.closeJDBCResultSet(rsRetrieveMessageSize);
+ theJDBCUtil.closeJDBCStatement(retrieveMessageSize);
+ theJDBCUtil.closeJDBCConnection(conn);
+ }
}
/**
@@ -174,9 +194,28 @@
*/
public boolean equals(Object obj) {
if (obj instanceof MimeMessageJDBCSource) {
+ // TODO: Figure out whether other instance variables should be part of
+ // the equals equation
MimeMessageJDBCSource source = (MimeMessageJDBCSource)obj;
- return source.key.equals(key) && source.repository.equals(repository);
+ return ((source.key == key) || ((source.key != null) &&
source.key.equals(key))) &&
+ ((source.repository == repository) || ((source.repository !=
null) && source.repository.equals(repository)));
}
return false;
}
+
+ /**
+ * Provide a hash code that is consistent with equals for this class
+ *
+ * @return the hash code
+ */
+ public int hashCode() {
+ int result = 17;
+ if (key != null) {
+ result = 37 * key.hashCode();
+ }
+ if (repository != null) {
+ result = 37 * repository.hashCode();
+ }
+ return result;
+ }
}
1.8 +44 -38
jakarta-james/src/java/org/apache/james/transport/mailets/JDBCAlias.java
Index: JDBCAlias.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/transport/mailets/JDBCAlias.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- JDBCAlias.java 18 Jan 2002 02:48:38 -0000 1.7
+++ JDBCAlias.java 12 Aug 2002 07:41:36 -0000 1.8
@@ -11,6 +11,7 @@
import org.apache.avalon.excalibur.datasource.DataSourceComponent;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.james.Constants;
+import org.apache.james.util.JDBCUtil;
import org.apache.mailet.GenericMailet;
import org.apache.mailet.Mail;
import org.apache.mailet.MailAddress;
@@ -21,6 +22,7 @@
import java.sql.*;
import java.util.Collection;
import java.util.Iterator;
+import java.util.Locale;
import java.util.Vector;
/**
@@ -41,6 +43,14 @@
protected DataSourceComponent datasource;
protected String query = null;
+ // The JDBCUtil helper class
+ private final JDBCUtil theJDBCUtil =
+ new JDBCUtil() {
+ protected void delegatedLog(String logString) {
+ log("JDBCAlias: " + logString);
+ }
+ };
+
public void init() throws MessagingException {
String mappingsURL = getInitParameter("mappings");
@@ -58,7 +68,7 @@
}
try {
ComponentManager componentManager =
(ComponentManager)getMailetContext().getAttribute(Constants.AVALON_COMPONENT_MANAGER);
- // Get the DataSourceSelector block
+ // Get the DataSourceSelector service
DataSourceSelector datasources =
(DataSourceSelector)componentManager.lookup(DataSourceSelector.ROLE);
// Get the data-source required.
datasource = (DataSourceComponent)datasources.select(datasourceName);
@@ -69,28 +79,34 @@
DatabaseMetaData dbMetaData = conn.getMetaData();
// Need to ask in the case that identifiers are stored, ask the
DatabaseMetaInfo.
// Try UPPER, lower, and MixedCase, to see if the table is there.
- if (! ( tableExists(dbMetaData, tableName) ||
- tableExists(dbMetaData, tableName.toUpperCase()) ||
- tableExists(dbMetaData, tableName.toLowerCase()) )) {
- throw new MailetException("Could not find table '" + tableName + "'
in datasource '" + datasourceName + "'");
+ if (!(theJDBCUtil.tableExists(dbMetaData, tableName))) {
+ StringBuffer exceptionBuffer =
+ new StringBuffer(128)
+ .append("Could not find table '")
+ .append(tableName)
+ .append("' in datasource '")
+ .append(datasourceName)
+ .append("'");
+ throw new MailetException(exceptionBuffer.toString());
}
//Build the query
- query = "SELECT " + getInitParameter("target_column")
- + " FROM " + tableName + " WHERE "
- + getInitParameter("source_column") + " = ?";
+ StringBuffer queryBuffer =
+ new StringBuffer(128)
+ .append("SELECT ")
+ .append(getInitParameter("target_column"))
+ .append(" FROM ")
+ .append(tableName)
+ .append(" WHERE ")
+ .append(getInitParameter("source_column"))
+ .append(" = ?");
+ query = queryBuffer.toString();
} catch (MailetException me) {
throw me;
} catch (Exception e) {
throw new MessagingException("Error initializing JDBCAlias", e);
} finally {
- try {
- if (conn != null) {
- conn.close();
- }
- } catch (SQLException sqle) {
- //ignore
- }
+ theJDBCUtil.closeJDBCConnection(conn);
}
}
@@ -127,26 +143,27 @@
recipientsToAdd.add(target);
} catch (ParseException pe) {
//Don't alias this address... there's an invalid address
mapping here
- log("There is an invalid alias from " + source + " to " +
mappingRS.getString(1));
+ StringBuffer exceptionBuffer =
+ new StringBuffer(128)
+ .append("There is an invalid alias from ")
+ .append(source)
+ .append(" to ")
+ .append(mappingRS.getString(1));
+ log(exceptionBuffer.toString());
continue;
}
} finally {
- mappingRS.close();
+ ResultSet localRS = mappingRS;
+ // Clear reference to result set
+ mappingRS = null;
+ theJDBCUtil.closeJDBCResultSet(localRS);
}
}
} catch (SQLException sqle) {
throw new MessagingException("Error accessing database", sqle);
} finally {
- try {
- mappingStmt.close();
- } catch (Exception e) {
- //ignore
- }
- try {
- conn.close();
- } catch (Exception e) {
- //ignore
- }
+ theJDBCUtil.closeJDBCStatement(mappingStmt);
+ theJDBCUtil.closeJDBCConnection(conn);
}
recipients.removeAll(recipientsToRemove);
@@ -155,17 +172,6 @@
public String getMailetInfo() {
return "JDBC aliasing mailet";
- }
-
- /**
- * Checks database metadata to see if a table exists.
- */
- 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;
}
}
1.7 +139 -54
jakarta-james/src/java/org/apache/james/transport/mailets/JDBCListserv.java
Index: JDBCListserv.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/transport/mailets/JDBCListserv.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- JDBCListserv.java 18 Jan 2002 02:48:38 -0000 1.6
+++ JDBCListserv.java 12 Aug 2002 07:41:36 -0000 1.7
@@ -11,6 +11,7 @@
import org.apache.avalon.excalibur.datasource.DataSourceComponent;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.james.Constants;
+import org.apache.james.util.JDBCUtil;
import org.apache.mailet.MailAddress;
import org.apache.mailet.MailetException;
@@ -18,6 +19,7 @@
import javax.mail.internet.ParseException;
import java.sql.*;
import java.util.Collection;
+import java.util.Locale;
import java.util.Vector;
/**
@@ -25,7 +27,7 @@
* is configured by passing the URL to a conn definition. You need to set
* the table name to check (or view) along with the source and target columns
* to use. For example,
- * <mailet match="All" class="JDBCAlias">
+ * <mailet match="All" class="JDBCListserv">
* <data_source>maildb</datasource>
* <listserv_id>mylistserv</listserv_id>
* <listserv_table>source_email_address</listserv_table>
@@ -58,6 +60,13 @@
protected String listservQuery = null;
protected String membersQuery = null;
+ // The JDBCUtil helper class
+ private final JDBCUtil theJDBCUtil =
+ new JDBCUtil() {
+ protected void delegatedLog(String logString) {
+ log("JDBCListserv: " + logString);
+ }
+ };
public void init() throws MessagingException {
if (getInitParameter("data_source") == null) {
@@ -90,7 +99,7 @@
try {
ComponentManager componentManager =
(ComponentManager)getMailetContext().getAttribute(Constants.AVALON_COMPONENT_MANAGER);
- // Get the DataSourceSelector block
+ // Get the DataSourceSelector service
DataSourceSelector datasources =
(DataSourceSelector)componentManager.lookup(DataSourceSelector.ROLE);
// Get the data-source required.
datasource = (DataSourceComponent)datasources.select(datasourceName);
@@ -101,39 +110,52 @@
DatabaseMetaData dbMetaData = conn.getMetaData();
// Need to ask in the case that identifiers are stored, ask the
DatabaseMetaInfo.
// Try UPPER, lower, and MixedCase, to see if the table is there.
- if (! ( tableExists(dbMetaData, listservTable) ||
- tableExists(dbMetaData, listservTable.toUpperCase()) ||
- tableExists(dbMetaData, listservTable.toLowerCase()) )) {
- throw new MailetException("Could not find table '" + listservTable
+ "' in datasource '" + datasourceName + "'");
+ if (!(theJDBCUtil.tableExists(dbMetaData, listservTable))) {
+ StringBuffer exceptionBuffer =
+ new StringBuffer(128)
+ .append("Could not find table '")
+ .append(listservTable)
+ .append("' in datasource '")
+ .append(datasourceName)
+ .append("'");
+ throw new MailetException(exceptionBuffer.toString());
}
// Check if the required members table exists. If not, complain.
// Need to ask in the case that identifiers are stored, ask the
DatabaseMetaInfo.
// Try UPPER, lower, and MixedCase, to see if the table is there.
- if (! ( tableExists(dbMetaData, membersTable) ||
- tableExists(dbMetaData, membersTable.toUpperCase()) ||
- tableExists(dbMetaData, membersTable.toLowerCase()) )) {
- throw new MailetException("Could not find table '" + membersTable +
"' in datasource '" + datasourceName + "'");
+ if (!( theJDBCUtil.tableExists(dbMetaData, membersTable))) {
+ StringBuffer exceptionBuffer =
+ new StringBuffer(128)
+ .append("Could not find table '")
+ .append(membersTable)
+ .append("' in datasource '")
+ .append(datasourceName)
+ .append("'");
+ throw new MailetException(exceptionBuffer.toString());
}
- listservQuery = "SELECT members_only, attachments_allowed,
reply_to_list, subject_prefix, list_address FROM "
- + listservTable + " WHERE listserv_id = ?";
- membersQuery = "SELECT member FROM " + membersTable + " WHERE
listserv_id = ?";
+ StringBuffer queryBuffer =
+ new StringBuffer(256)
+ .append("SELECT members_only, attachments_allowed,
reply_to_list, subject_prefix, list_address FROM ")
+ .append(listservTable)
+ .append(" WHERE listserv_id = ?");
+ listservQuery = queryBuffer.toString();
+ queryBuffer =
+ new StringBuffer(128)
+ .append("SELECT member FROM ")
+ .append(membersTable)
+ .append(" WHERE listserv_id = ?");
+ membersQuery = queryBuffer.toString();
//Always load settings at least once... if we aren't caching, we will
load at each getMembers() call
loadSettings();
} catch (MailetException me) {
throw me;
} catch (Exception e) {
- throw new MessagingException("Error initializing JDBCAlias", e);
+ throw new MessagingException("Error initializing JDBCListserv", e);
} finally {
- try {
- if (conn != null) {
- conn.close();
- }
- } catch (SQLException sqle) {
- //ignore
- }
+ closeJdbcConnection(conn);
}
}
@@ -193,29 +215,50 @@
try {
//Load members
conn = datasource.getConnection();
- stmt = conn.prepareStatement(membersQuery);
- stmt.setString(1, listservID);
- rs = stmt.executeQuery();
- Collection tmpMembers = new Vector();
- while (rs.next()) {
- String address = rs.getString(1);
- try {
- MailAddress mailAddress = new MailAddress(address);
- tmpMembers.add(mailAddress);
- } catch (ParseException pe) {
- //don't stop... just log and continue
- log("error parsing address '" + address + "' in listserv '" +
listservID + "'");
+ try {
+ stmt = conn.prepareStatement(membersQuery);
+ stmt.setString(1, listservID);
+ rs = stmt.executeQuery();
+ Collection tmpMembers = new Vector();
+ while (rs.next()) {
+ String address = rs.getString(1);
+ try {
+ MailAddress mailAddress = new MailAddress(address);
+ tmpMembers.add(mailAddress);
+ } catch (ParseException pe) {
+ //don't stop... just log and continue
+ StringBuffer exceptionBuffer =
+ new StringBuffer(64)
+ .append("error parsing address '")
+ .append(address)
+ .append("' in listserv '")
+ .append(listservID)
+ .append("'");
+ log(exceptionBuffer.toString());
+ }
}
+ members = tmpMembers;
+ } finally {
+ ResultSet localRS = rs;
+ // Clear reference to result set
+ rs = null;
+ closeJdbcResultSet(localRS);
+ Statement localStmt = stmt;
+ // Clear reference to statement
+ stmt = null;
+ closeJdbcStatement(localStmt);
}
- members = tmpMembers;
- rs.close();
- stmt.close();
stmt = conn.prepareStatement(listservQuery);
stmt.setString(1, listservID);
rs = stmt.executeQuery();
if (!rs.next()) {
- throw new MailetException("Could not find listserv record for '" +
listservID + "'");
+ StringBuffer exceptionBuffer =
+ new StringBuffer(64)
+ .append("Could not find listserv record for '")
+ .append(listservID)
+ .append("'");
+ throw new MailetException(exceptionBuffer.toString());
}
membersOnly = rs.getBoolean("members_only");
attachmentsAllowed = rs.getBoolean("attachments_allowed");
@@ -229,22 +272,23 @@
listservAddress = new MailAddress(address);
} catch (ParseException pe) {
//log and ignore
- log("invalid listserv address '" + listservAddress + "' for
listserv '" + listservID + "'");
+ StringBuffer logBuffer =
+ new StringBuffer(128)
+ .append("invalid listserv address '")
+ .append(listservAddress)
+ .append("' for listserv '")
+ .append(listservID)
+ .append("'");
+ log(logBuffer.toString());
listservAddress = null;
}
}
- rs.close();
- stmt.close();
} catch (SQLException sqle) {
throw new MailetException("Problem loading settings", sqle);
} finally {
- try {
- if (conn != null) {
- conn.close();
- }
- } catch (SQLException sqle) {
- //ignore
- }
+ closeJdbcResultSet(rs);
+ closeJdbcStatement(stmt);
+ closeJdbcConnection(conn);
}
}
@@ -253,13 +297,54 @@
}
/**
- * Checks database metadata to see if a table exists.
+ * Closes database connection and prints to the log if an error
+ * is encountered
+ *
+ * @conn the connection to be closed
*/
- 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;
+ private void closeJdbcConnection(Connection conn) {
+ try {
+ if (conn != null) {
+ conn.close();
+ }
+ } catch (SQLException sqle) {
+ // Log exception and continue
+ log("JDBCListserv : Unexpected exception while closing database
connection.");
+ }
}
+
+ /**
+ * Closes database statement and prints to the log if an error
+ * is encountered
+ *
+ * @stmt the statement to be closed
+ */
+ private void closeJdbcStatement(Statement stmt) {
+ try {
+ if (stmt != null) {
+ stmt.close();
+ }
+ } catch (SQLException sqle) {
+ // Log exception and continue
+ log("JDBCListserv : Unexpected exception while closing database
statement.");
+ }
+ }
+
+ /**
+ * Closes database result set and prints to the log if an error
+ * is encountered
+ *
+ * @aResultSet the result set to be closed
+ */
+ private void closeJdbcResultSet(ResultSet aResultSet ) {
+ try {
+ if (aResultSet != null) {
+ aResultSet.close();
+ }
+ } catch (SQLException sqle) {
+ // Log exception and continue
+ log("JDBCListserv : Unexpected exception while closing database result
set.");
+ }
+ }
+
}
1.12 +96 -35
jakarta-james/src/java/org/apache/james/util/mordred/JdbcDataSource.java
Index: JdbcDataSource.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/util/mordred/JdbcDataSource.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- JdbcDataSource.java 27 Jul 2002 08:15:48 -0000 1.11
+++ JdbcDataSource.java 12 Aug 2002 07:41:36 -0000 1.12
@@ -109,8 +109,13 @@
//If we find one, book it.
int count = total_served++;
if(DEEP_DEBUG) {
- System.out.println(new java.util.Date() + " trying to get a connection
(" + count +
- ")");
+ StringBuffer deepDebugBuffer =
+ new StringBuffer(128)
+ .append((new java.util.Date()).toString())
+ .append(" trying to get a connection (")
+ .append(count)
+ .append(")");
+ System.out.println(deepDebugBuffer.toString());
}
for(int attempts = 1; attempts <= 100; attempts++) {
synchronized(pool) {
@@ -121,9 +126,13 @@
try {
if(entry.lock()) {
if(DEEP_DEBUG) {
- System.out.println(
- new java.util.Date() + " return a
connection (" + count +
- ")");
+ StringBuffer deepDebugBuffer =
+ new StringBuffer(128)
+ .append((new
java.util.Date()).toString())
+ .append(" return a connection (")
+ .append(count)
+ .append(")");
+ System.out.println(deepDebugBuffer.toString());
}
return entry;
}
@@ -146,9 +155,13 @@
PoolConnEntry entry = createConn();
if(entry != null) {
if(DEEP_DEBUG) {
- System.out.println(
- new java.util.Date() + " returning new
connection (" + count +
- ")");
+ StringBuffer deepDebugBuffer =
+ new StringBuffer(128)
+ .append((new java.util.Date()).toString())
+ .append(" returning new connection (")
+ .append(count)
+ .append(")");
+ System.out.println(deepDebugBuffer.toString());
}
return entry;
}
@@ -162,7 +175,12 @@
PoolConnEntry entry = createConn();
if(entry != null) {
if(DEEP_DEBUG) {
- System.out.println(" returning new connection (" +
count + "(");
+ StringBuffer deepDebugBuffer =
+ new StringBuffer(32)
+ .append(" returning new connection (")
+ .append(count)
+ .append(")");
+ System.out.println(deepDebugBuffer.toString());
}
return entry;
} else {
@@ -176,7 +194,9 @@
PrintWriter pout = new PrintWriter(sout, true);
pout.println("Error creating connection: ");
sqle.printStackTrace(pout);
- getLogger().error(sout.toString());
+ if (getLogger().isErrorEnabled()) {
+ getLogger().error(sout.toString());
+ }
}
//otherwise sleep 50ms 10 times, then create a connection
try {
@@ -211,11 +231,17 @@
throw new ConfigurationException("You need to specify a valid
driver, e.g., <driver>my.class</driver>");
}
try {
- getLogger().debug("Loading new driver: " + jdbcDriver);
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Loading new driver: " + jdbcDriver);
+ }
Class.forName(jdbcDriver, true,
Thread.currentThread().getContextClassLoader());
} catch(ClassNotFoundException cnfe) {
- throw new ConfigurationException("'" + jdbcDriver +
- "' could not be found in
classloader. Please specify a valid JDBC driver");
+ StringBuffer exceptionBuffer =
+ new StringBuffer(128)
+ .append("'")
+ .append(jdbcDriver)
+ .append("' could not be found in classloader. Please
specify a valid JDBC driver");
+ throw new ConfigurationException(exceptionBuffer.toString());
}
if(jdbcURL == null) {
throw new ConfigurationException("You need to specify a valid JDBC
connection string, e.g., <dburl>jdbc:driver:database</dburl>");
@@ -223,12 +249,14 @@
if(maxConn < 0) {
throw new ConfigurationException("Maximum number of connections
specified must be at least 1 (0 means no limit).");
}
- getLogger().debug("Starting connection pooler");
- getLogger().debug("driver = " + jdbcDriver);
- getLogger().debug("dburl = " + jdbcURL);
- getLogger().debug("username = " + jdbcUsername);
- //We don't show the password
- getLogger().debug("max connections = " + maxConn);
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Starting connection pooler");
+ getLogger().debug("driver = " + jdbcDriver);
+ getLogger().debug("dburl = " + jdbcURL);
+ getLogger().debug("username = " + jdbcUsername);
+ //We don't show the password
+ getLogger().debug("max connections = " + maxConn);
+ }
pool = new Vector();
reaperActive = true;
reaper = new Thread(this);
@@ -286,9 +314,19 @@
if(verifyConnSQL != null) {
try {
// Test this connection
- java.sql.Statement stmt = entry.createStatement();
- stmt.execute(verifyConnSQL);
- stmt.close();
+ java.sql.Statement stmt = null;
+ try {
+ stmt = entry.createStatement();
+ stmt.execute(verifyConnSQL);
+ } finally {
+ try {
+ if (stmt != null) {
+ stmt.close();
+ }
+ } catch (SQLException sqle) {
+ // Failure to close ignored on test connection
+ }
+ }
// Passed test... recycle the entry
entry.unlock();
} catch(SQLException e1) {
@@ -301,7 +339,9 @@
}
return;
} else {
- getLogger().warn("----> Could not find connection to kill!!!");
+ if (getLogger().isWarnEnabled()) {
+ getLogger().warn("----> Could not find connection to kill!!!");
+ }
new Throwable().printStackTrace();
return;
}
@@ -319,7 +359,9 @@
entry.unlock();
return;
} else {
- getLogger().warn("----> Could not find the connection to free!!!");
+ if (getLogger().isWarnEnabled()) {
+ getLogger().warn("----> Could not find the connection to free!!!");
+ }
return;
}
}
@@ -336,9 +378,15 @@
synchronized(entry) {
if((entry.getStatus() == PoolConnEntry.ACTIVE) &&
(age > ACTIVE_CONN_TIME_LIMIT)) {
- getLogger().info(
- " ***** connection " + entry.getId() + " is way too
old: " + age +
- " > " + ACTIVE_CONN_TIME_LIMIT);
+ StringBuffer logBuffer =
+ new StringBuffer(128)
+ .append(" ***** connection ")
+ .append(entry.getId())
+ .append(" is way too old: ")
+ .append(age)
+ .append(" > ")
+ .append(ACTIVE_CONN_TIME_LIMIT);
+ getLogger().info(logBuffer.toString());
// This connection is way too old...
// kill it no matter what
finalizeEntry(entry);
@@ -401,9 +449,17 @@
connLastCreated = now;
} else {
// We've already hit a limit... fail silently
- getLogger().debug(
- "Connection limit hit... " + pool.size() + " in pool and " +
- connCreationsInProgress + " + on the way.");
+ if (getLogger().isDebugEnabled())
+ {
+ StringBuffer logBuffer =
+ new StringBuffer(128)
+ .append("Connection limit hit... ")
+ .append(pool.size())
+ .append(" in pool and ")
+ .append(connCreationsInProgress)
+ .append(" + on the way.");
+ getLogger().debug(logBuffer.toString());
+ }
return null;
}
}
@@ -412,7 +468,10 @@
java.sql.DriverManager.getConnection(jdbcURL,
jdbcUsername,
jdbcPassword),
++connectionCount);
- getLogger().debug("Opening connection " + entry);
+ if (getLogger().isDebugEnabled())
+ {
+ getLogger().debug("Opening connection " + entry);
+ }
entry.lock();
pool.addElement(entry);
return entry;
@@ -423,8 +482,10 @@
PrintWriter pout = new PrintWriter(sout, true);
pout.println("Error creating connection: ");
sqle.printStackTrace(pout);
- getLogger().error(sout.toString());
- return null;
+ if (getLogger().isErrorEnabled()) {
+ getLogger().error(sout.toString());
+ }
+ return null;
} finally {
synchronized(this) {
connCreationsInProgress--;
@@ -444,4 +505,4 @@
}
pool.removeElement(entry);
}
-}
\ No newline at end of file
+}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>