You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by hu...@apache.org on 2003/05/09 12:15:39 UTC
cvs commit: jakarta-struts/contrib/struts-legacy/src/java/org/apache/struts/legacy GenericDataSource.java GenericConnection.java
husted 2003/05/09 03:15:39
Added: contrib/struts-legacy/src/java/org/apache/struts/legacy
GenericDataSource.java GenericConnection.java
Log:
+ "Whiteboard" struts-legacy package to host the original GenericDataSource.
Revision Changes Path
1.1 jakarta-struts/contrib/struts-legacy/src/java/org/apache/struts/legacy/GenericDataSource.java
Index: GenericDataSource.java
===================================================================
/*
* $Header: /home/cvs/jakarta-struts/contrib/struts-legacy/src/java/org/apache/struts/legacy/GenericDataSource.java,v 1.1 2003/05/09 10:15:38 husted Exp $
* $Revision: 1.1 $
* $Date: 2003/05/09 10:15:38 $
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Struts", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.struts.legacy;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* <p>Generic data source implementation of the <code>DataSource</code>
* interface. <b>WARNING</b> - This implementation does not know how to
* provide connections with different username/password combinations.
* Calling this version of the implementation using the
* getConnection(username,password) signature will throw an exception.</p>
*
* <p>The following properties are supported by the standard
* <code>GenericDataSource</code> implementation:</p>
* <table>
* <tr>
* <th width="15%">Property</th>
* <th width="85%">Description</th>
* </tr>
* <tr>
* <td align="center">autoCommit</td>
* <td>Set to <code>true</code> if you want the connections returned to you
* by calling <code>getConnection()</code> to be configured in
* "auto-commit after every statement" mode. The default value is
* <code>true</code>, to conform to JDBC standard conventions.</td>
* </tr>
* <tr>
* <td align="center">description</td>
* <td>A short textual description of this data source. This property is
* required by the <code>javax.sql.DataSource</code> interface, but is
* not used within this implementation.</td>
* </tr>
* <tr>
* <td align="center">driverClass</td>
* <td>The fully qualified class name of the JDBC driver to be utilized for
* the connections created by this data source. Consult the
* documentation for your JDBC driver to identify the value to be
* configured for this property.</td>
* </tr>
* <tr>
* <td align="center">maxCount</td>
* <td>The maximum number of JDBC connections that will be created by this
* data source. This value must be greater than or equal to the value
* specified for the <code>minCount</count> property.</td>
* </tr>
* <tr>
* <td align="center">minCount</td>
* <td>The minimum number of JDBC connections to establish when this data
* source is first opened. This value must be less than or equal to the
* value specified for the <code>maxCount</code> property.</td>
* </tr>
* <tr>
* <td align="center">password</td>
* <td>The database password used to establish the connections created by
* this connection pool, in conjunction with the username specified in
* the <code>user</code> property.</td>
* </tr>
* <tr>
* <td align="center">pingCommand</td>
* <td>A non-query SQL command that, if specified, will be executed before
* a connection is returned by a call to <code>getConnection()</code>.
* If any SQLException is thrown by the execution of this statement,
* it is assumed that this connection is stale and it will be discarded.
* Because this happens on every connection allocation, you should ensure
* that the statement executes very quickly.</td>
* </tr>
* <tr>
* <td align="center">pingQuery</td>
* <td>A query SQL command (i.e. a SELECT) that, if specified, will be
* executed before a connection is returned by a call to
* <code>getConnection()</code>. If any SQLException is thrown by the
* execution of this query (or by the subsequent processing of the
* entire returned <code>ResultSet</code>), it is assumed that this
* connection is stale and it will be discarded. Because this happens
* on every connection allocation, you should ensure that the
* statement executes very quickly.</td>
* </tr>
* <tr>
* <td align="center">readOnly</td>
* <td>Set to <code>true</code> if you want the connections returned to you
* by calling <code>getConnection()</code> to be configured for read only
* operations. This can result in more efficient database access,
* because the database will know it does not need to retain undo logs
* for rolling back the transaction. The default value is
* <code>false</code>.</td>
* </tr>
* <tr>
* <td align="center">url</td>
* <td>The connection URL to be passed to our JDBC driver when establishing
* a new connection. The value specified typically starts with
* <code>jdbc:</code>, and includes a reference to the host (and,
* optionally, the port number) at which the database server is listening
* for connections, plus the name of the database to be opened. Consult
* the documentation for your JDBC driver to identify the value to be
* configured for this property.</td>
* </tr>
* <tr>
* <td align="center">user</td>
* <td>The database username used to establish the connections created by
* this connection pool, in conjunction with the password specified in
* the <code>password</code> property.</td>
* </tr>
* </table>
*
* <p>In addition, you can add to the set of <code>Properties</code> passed to
* the JDBC driver by calling <code>addProperty()</code>.</p>
* <p>
* This class was originally maintained in the core Struts util package [revision 1.11].
* </p>
*
* @author Craig R. McClanahan
* @author Ted Husted
* @version $Revision: 1.1 $ $Date: 2003/05/09 10:15:38 $
*/
public class GenericDataSource implements DataSource {
// ----------------------------------------------------------- Util Methods
/**
* Return the <code>Class</code> object for the specified fully qualified
* class name, from this web application's class loader.
* <p>
* See util.RequestUtils.applicationClass for maintained original.
*
* @param className Fully qualified class name to be loaded
* @return Class object
* @exception ClassNotFoundException if the class cannot be found
*/
private static Class applicationClass(String className) throws ClassNotFoundException {
// Look up the class loader to be used
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = GenericDataSource.class.getClassLoader();
}
// Attempt to load the specified class
return (classLoader.loadClass(className));
}
/**
* Return a new instance of the specified fully qualified class name,
* after loading the class from this web application's class loader.
* The specified class <strong>MUST</strong> have a public zero-arguments
* constructor.
* <p>
* See util.RequestUtils.applicationClass for maintained original.
*
* @param className Fully qualified class name to use
* @return new instance of class
* @exception ClassNotFoundException if the class cannot be found
* @exception IllegalAccessException if the class or its constructor
* is not accessible
* @exception InstantiationException if this class represents an
* abstract class, an interface, an array class, a primitive type,
* or void
* @exception InstantiationException if this class has no
* zero-arguments constructor
*/
private static Object applicationInstance(String className)
throws ClassNotFoundException, IllegalAccessException, InstantiationException {
return (applicationClass(className).newInstance());
}
// ----------------------------------------------------- Instance Constants
private static final String SQLEXCEPTION_GETCONNECTION =
"getConnection(String username, String password) Method not supported. Use getConnection() instead.";
// ----------------------------------------------------- Instance Variables
/**
* Has this data source been closed?
*/
protected boolean closed = false;
/**
* The list of Connections (wrapped in our associated wrapper class) that
* have been created but are not currently in use.
*/
protected LinkedList connections = new LinkedList();
/**
* The JDBC driver that we use as a connection factory.
*/
protected Driver driver = null;
/**
* Commons Logging instance.
*/
protected Log log = LogFactory.getLog(this.getClass());
/**
* The login timeout for this data source.
*/
protected int loginTimeout = 0;
/**
* The log writer for this data source.
*/
protected PrintWriter logWriter = null;
// ------------------------------------------------------------- Properties
/**
* Add a generic property to the list of connection properties to be used.
*
* @param name Name of the generic property
* @param value Corresponding generic property value
*/
public void addProperty(String name, String value) {
properties.put(name, value);
}
/**
* The number of connections that have been created by this data source.
*/
protected int activeCount = 0;
public int getActiveCount() {
return (this.activeCount);
}
/**
* The default auto-commit state for newly created connections.
*/
protected boolean autoCommit = true;
public boolean getAutoCommit() {
return (this.autoCommit);
}
public void setAutoCommit(boolean autoCommit) {
this.autoCommit = autoCommit;
}
/**
* The debugging detail level for this data source.
*/
protected int debug = 0;
public int getDebug() {
return (this.debug);
}
public void setDebug(int debug) {
this.debug = debug;
}
/**
* The description of this data source.
*/
protected String description = null;
public String getDescription() {
return (this.description);
}
public void setDescription(String description) {
this.description = description;
}
/**
* The Java class name of the JDBC driver to use.
*/
protected String driverClass = null;
public String getDriverClass() {
return (this.driverClass);
}
public void setDriverClass(String driverClass) {
this.driverClass = driverClass;
}
/**
* The maximum number of connections to be created.
*/
protected int maxCount = 2;
public int getMaxCount() {
return (this.maxCount);
}
public void setMaxCount(int maxCount) {
this.maxCount = maxCount;
}
/**
* The minimum number of connections to be created.
*/
protected int minCount = 1;
public int getMinCount() {
return (this.minCount);
}
public void setMinCount(int minCount) {
this.minCount = minCount;
}
/**
* The database password for use in establishing a connection.
*/
protected String password = null;
public String getPassword() {
return (this.password);
}
public void setPassword(String password) {
this.password = password;
addProperty("password", this.password);
}
/**
* The non-query SQL command used to ping an allocated connection.
*/
protected String pingCommand = null;
public String getPingCommand() {
return (this.pingCommand);
}
public void setPingCommand(String pingCommand) {
this.pingCommand = pingCommand;
}
/**
* The query SQL command used to ping an allocated connection.
*/
protected String pingQuery = null;
public String getPingQuery() {
return (this.pingQuery);
}
public void setPingQuery(String pingQuery) {
this.pingQuery = pingQuery;
}
/**
* The connection properties for use in establishing connections.
*/
protected Properties properties = new Properties();
/**
* The default read-only state for newly created connections.
*/
protected boolean readOnly = false;
public boolean getReadOnly() {
return (this.readOnly);
}
public void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
}
/**
* The JDBC URL for the database connection to be opened.
*/
protected String url = null;
public String getUrl() {
return (this.url);
}
public void setUrl(String url) {
this.url = url;
}
/**
* The number of connections created by this data source that are
* currently in use.
*/
protected int useCount = 0;
public int getUseCount() {
return (this.useCount);
}
/**
* The database username for use in establishing a connection.
*/
protected String user = null;
public String getUser() {
return (this.user);
}
public void setUser(String user) {
this.user = user;
addProperty("user", this.user);
}
// ----------------------------------------------------- DataSource Methods
/**
* Attempt to establish a database connection.
*
* @exception SQLException if a database access error occurs
*/
public Connection getConnection() throws SQLException {
int seconds = 0;
if (log.isInfoEnabled()) {
log.info(" getConnection()");
}
// Validate the opened status of this data source
if (closed) {
throw new SQLException("getConnection: Data source is closed");
}
if (driver == null) {
open();
}
while (true) {
// Have we timed out yet?
if (log.isInfoEnabled()) {
log.info(" Check for timeout, activeCount=" + activeCount +
", useCount=" + useCount);
}
if ((loginTimeout > 0) && (seconds >= loginTimeout)) {
break;
}
// Return an existing connection from the pool if there is one
synchronized (connections) {
if (!connections.isEmpty()) {
// Allocate the first available connection
GenericConnection connection =
(GenericConnection) connections.removeFirst();
if (log.isInfoEnabled()) {
log.info(" Found available connection");
}
// Make sure this connection is not stale
connection.setClosed(false);
try {
ping(connection);
} catch (SQLException e) {
log.warn(" Connection stale, releasing");
try {
connection.getConnection().close();
} catch (SQLException f) {
;
}
activeCount--;
continue;
}
// unclose the connection's wrapper and return it
useCount++;
if (log.isInfoEnabled()) {
log.info(" Return allocated connection, activeCount=" +
activeCount + ", useCount=" + useCount);
}
return(connection);
}
}
// Create a new connection if we are not yet at the maximum
if (activeCount < maxCount) {
Connection connection = createConnection();
if (connection != null) {
try {
ping(connection);
} catch (SQLException e) {
throw e;
}
useCount++;
if (log.isInfoEnabled()) {
log.info(" Return new connection, activeCount=" +
activeCount + ", useCount=" + useCount);
}
return (connection);
}
}
// Wait for an existing connection to be returned
if (log.isInfoEnabled()) {
log.info(" Sleep until next test");
}
try {
Thread.sleep(1000);
seconds++;
} catch (InterruptedException e) {
;
}
}
// We have timed out awaiting an available connection
if (log.isInfoEnabled()) {
log.info(" Timeout awaiting connection");
}
throw new SQLException
("getConnection: Timeout awaiting connection");
}
/**
* Attempt to establish a database connection. <b>WARNING</b> - The
* specified username and password are not supported by this
* implementation.
*
* @param username Database username for this connection
* @param password Database password for this connection
*
* @exception SQLException if a database access error occurs
*/
public Connection getConnection(String username, String password)
throws SQLException {
throw new SQLException(SQLEXCEPTION_GETCONNECTION); // Not implemented
}
/**
* Return the login timeout for this data source.
*
* @exception SQLException if a database access error occurs
*/
public int getLoginTimeout() throws SQLException {
return (this.loginTimeout);
}
/**
* Return the log writer for this data source.
*
* @exception SQLException if a database access error occurs
*/
public PrintWriter getLogWriter() throws SQLException {
return (this.logWriter);
}
/**
* Set the login timeout for this data source.
*
* @param loginTimeout The new login timeout
*
* @exception SQLException if a database access error occurs
*/
public void setLoginTimeout(int loginTimeout) throws SQLException {
this.loginTimeout = loginTimeout;
}
/**
* Set the log writer for this data source.
*
* @param logWriter The new log writer
*
* @exception SQLException if a database access error occurs
*/
public void setLogWriter(PrintWriter logWriter) throws SQLException {
this.logWriter = logWriter;
}
// --------------------------------------------------------- Public Methods
/**
* Close all connections that have been created by this data source.
*
* @exception SQLException if a database access error occurs
*/
public void close() throws SQLException {
if (closed)
throw new SQLException("close: Data Source already closed");
if (log.isDebugEnabled()) {
log.debug(" close()");
}
// Shut down all active connections
while (activeCount > 0) {
GenericConnection conn = (GenericConnection) getConnection();
conn.getConnection().close();
activeCount--;
}
// Mark this data source as having been closed and release our driver
closed = true;
driver = null;
}
/**
* Open the initial connections that are appropriate for this data source.
*
* @exception SQLException if a database access error occurs
*/
public void open() throws SQLException {
// Have we already been opened?
if (driver != null)
return;
if (log.isDebugEnabled()) {
log.debug(" open()");
}
// Instantiate our database driver
try {
driver = (Driver) applicationInstance(driverClass);
} catch (Throwable t) {
throw new SQLException("open: " + t);
}
// Create the initial minimum number of required connections
synchronized (connections) {
for (int i = 0; i < minCount; i++) {
connections.addLast(createConnection());
}
}
closed = false;
}
/**
* Return a string representation of this component.
*/
public String toString() {
StringBuffer sb = new StringBuffer("GenericDataSource[");
sb.append("activeCount=");
sb.append(activeCount);
sb.append(", autoCommit=");
sb.append(autoCommit);
sb.append(", closed=");
sb.append(closed);
if (description != null) {
sb.append(", description=");
sb.append(description);
}
sb.append(", driverClass=");
sb.append(driverClass);
sb.append(", loginTimeout=");
sb.append(loginTimeout);
sb.append(", maxCount=");
sb.append(maxCount);
sb.append(", minCount=");
sb.append(minCount);
sb.append(", password=");
sb.append(password);
sb.append(", readOnly=");
sb.append(readOnly);
sb.append(", url=");
sb.append(url);
sb.append(", useCount=");
sb.append(useCount);
sb.append(", user=");
sb.append(user);
sb.append("]");
return (sb.toString());
}
// ------------------------------------------------------ Protected Methods
/**
* Create, configure, and return a new JDBC Connection that has been
* wrapped in our corresponding wrapper.
*
* @exception SQLException if a database access error occurs
*/
protected synchronized Connection createConnection() throws SQLException {
if (activeCount < maxCount) {
if (log.isInfoEnabled()) {
log.info(" createConnection()");
}
Connection conn = driver.connect(url, properties);
activeCount++;
return (new GenericConnection(this, conn, autoCommit, readOnly));
}
log.error(" createConnection() returning null");
return (null);
}
/**
* Log the specified message to our log writer, if we have one.
*
* @param message The message to be logged
*/
protected void log(String message) {
if (logWriter != null) {
logWriter.print("GenericDataSource[");
logWriter.print(description);
logWriter.print("]: ");
logWriter.println(message);
}
}
/**
* Log the specified message and exception to our log writer, if we
* have one.
*
* @param message The message to be logged
* @param throwable The exception to be logged
*/
protected void log(String message, Throwable throwable) {
if (logWriter != null) {
logWriter.print("GenericDataSource[");
logWriter.print(description);
logWriter.print("]: ");
logWriter.println(message);
throwable.printStackTrace(logWriter);
}
}
/**
* Perform any configured <code>pingCommand</code> and/or
* <code>pingQuery</code> on the specified connection, returning any
* SQLException that is encountered along the way.
*
* @param conn The connection to be pinged
*/
protected void ping(Connection conn) throws SQLException {
if (pingCommand != null) {
if (log.isDebugEnabled()) {
log.debug(" ping(" + pingCommand + ")");
}
Statement stmt = conn.createStatement();
try {
stmt.execute(pingCommand);
stmt.close();
} catch (SQLException e) {
log.warn("ping failed: " + e.getMessage(), e);
try {
if (stmt != null) {
stmt.close();
}
} catch (SQLException f) {
;
}
throw e;
}
}
if (pingQuery != null) {
if (log.isDebugEnabled()) {
log.debug(" ping(" + pingQuery + ")");
}
ResultSet rs = null;
Statement stmt = conn.createStatement();
try {
rs = stmt.executeQuery(pingQuery);
while (rs.next()) {
;
}
rs.close();
stmt.close();
} catch (SQLException e) {
log.warn("ping failed: " + e.getMessage(), e);
try {
if (rs != null)
rs.close();
} catch (SQLException f) {
;
}
try {
if (stmt != null)
stmt.close();
} catch (SQLException f) {
;
}
throw e;
}
}
}
// -------------------------------------------------------- Package Methods
/**
* Return this connection to the available connection pool.
*
* @param conn The connection being returned
*/
void returnConnection(GenericConnection conn) {
if (log.isInfoEnabled()) {
log.info(" releaseConnection(), activeCount=" + activeCount +
", useCount=" + (useCount - 1));
}
synchronized (connections) {
connections.addLast(conn);
useCount--;
}
}
}
1.1 jakarta-struts/contrib/struts-legacy/src/java/org/apache/struts/legacy/GenericConnection.java
Index: GenericConnection.java
===================================================================
/*
* $Header: /home/cvs/jakarta-struts/contrib/struts-legacy/src/java/org/apache/struts/legacy/GenericConnection.java,v 1.1 2003/05/09 10:15:38 husted Exp $
* $Revision: 1.1 $
* $Date: 2003/05/09 10:15:38 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Struts", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.struts.legacy;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.sql.Savepoint;
import java.util.Map;
import javax.sql.DataSource;
/**
* Generic wrapper implementation of a <strong>Connection</strong> that
* works with <code>GenericDataSource</code> to wrap connections for any
* JDBC driver.
* <p>
* This version of the source MUST be compiled under Java 1.4 or later.
* </p>
* <p>
* This class was originally maintained in the core Struts util package.
* </p>
*
* @author Craig R. McClanahan
* @author Ted Husted
* @version $Revision: 1.1 $ $Date: 2003/05/09 10:15:38 $
*/
public class GenericConnection implements Connection {
// ---------------------------------------------- since 1.4 - not supported
// To compile under 1.3, this block of signatures can be commented out.
public void setHoldability(int holdability) throws SQLException {
throw new UnsupportedOperationException();
}
public int getHoldability() throws SQLException{
throw new UnsupportedOperationException();
}
public Savepoint setSavepoint() throws SQLException {
throw new UnsupportedOperationException();
}
public Savepoint setSavepoint(String name) throws SQLException {
throw new UnsupportedOperationException();
}
public void rollback(Savepoint savepoint) throws SQLException {
throw new UnsupportedOperationException();
}
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
throw new UnsupportedOperationException();
}
public Statement createStatement(int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
throw new UnsupportedOperationException();
}
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
throw new UnsupportedOperationException();
}
public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
throw new UnsupportedOperationException();
}
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
throws SQLException {
throw new UnsupportedOperationException();
}
public PreparedStatement prepareStatement(String sql, int columnIndexes[])
throws SQLException {
throw new UnsupportedOperationException();
}
public PreparedStatement prepareStatement(String sql, String columnNames[])
throws SQLException {
throw new UnsupportedOperationException();
}
// ----------------------------------------------------------- Constructors
/**
* Construct a new GenericConnection wrapping the specified connection.
*
* @param source The data source that owns this connection
* @param conn The connection to wrap
* @param autoCommit Desired auto-commit state for this connection
* @param readOnly Desired read-only state for this connection
*
* @exception SQLException if an SQL processing error occurs
*/
public GenericConnection(GenericDataSource source, Connection conn,
boolean autoCommit, boolean readOnly)
throws SQLException {
super();
this.source = source;
this.conn = conn;
this.autoCommit = autoCommit;
this.catalog = conn.getCatalog();
this.level = conn.getTransactionIsolation();
try {
this.map = conn.getTypeMap();
} catch (SQLException e) {
; // PostgreSQL throws a "not yet implemented" exception
} catch (UnsupportedOperationException e) {
; // JDBC-ODBC bridge throws this
} catch (AbstractMethodError e) {
; // mm.mysql throws this
}
this.readOnly = readOnly;
this.conn.setAutoCommit(this.autoCommit);
try {
this.conn.setReadOnly(this.readOnly);
} catch (SQLException e) {
; // Informix throws a "not supported" exception
}
}
// ----------------------------------------------------- Instance Constants
private final static String SQLEXCEPTION_CLOSED = "Connection was closed.";
// ----------------------------------------------------- Instance Variables
/**
* The initial auto-commit state to which we should return after release.
*/
protected boolean autoCommit = false;
/**
* The initial catalog to which we should return after release.
*/
protected String catalog = null;
/**
* The closed flag for this wrapped connection.
*/
private boolean closed = false;
/**
* The Connection that is being wrapped.
*/
protected Connection conn = null;
/**
* The initial transaction isolation level to which we should return
* after release.
*/
protected int level = 0;
/**
* The initial type map to which we should return after release.
*/
protected Map map = null;
/**
* The initial read-only state to which we should return after release.
*/
protected boolean readOnly = false;
/**
* The GenericDataSource that owns this connection.
*/
protected GenericDataSource source = null;
// --------------------------------------------------------- Public Methods
/**
* Clear all warnings reported for this Connection.
*
* @exception SQLException if a database access error occurs
*/
public void clearWarnings() throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
conn.clearWarnings();
}
/**
* Return this wrapped Connection to our data source connection pool.
*
* @exception SQLException if a database access error occurs
*/
public void close() throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
// Clean up any outstanding transaction as best we can
try {
conn.rollback();
} catch (SQLException e) {
;
}
try {
conn.setAutoCommit(this.autoCommit);
} catch (SQLException e) {
;
}
try {
conn.setCatalog(this.catalog);
} catch (SQLException e) {
;
}
try {
conn.setTransactionIsolation(this.level);
} catch (SQLException e) {
;
}
try {
conn.setTypeMap(this.map);
} catch (SQLException e) {
; // PostgreSQL throws a "not yet implemented" exception
} catch (UnsupportedOperationException e) {
; // JDBC-ODBC driver throws this
} catch (AbstractMethodError e) {
; // mm.mysql throws this
}
try {
conn.setReadOnly(this.readOnly);
} catch (SQLException e) {
; // Informix throws a "not supported" exception
}
try {
conn.clearWarnings();
} catch (SQLException e) {
;
}
// Flag that this connection is closed
// All methods accessing conn will now throw SQLEXCEPTION_CLOSED
closed = true;
// Return this connection to the available connection pool
source.returnConnection(this);
}
/**
* Make all changes made since the previous commit or rollback
* permanent, and releases any database locks currently held.
*
* @exception SQLException if a database access error occurs
*/
public void commit() throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
conn.commit();
}
/**
* Create a <code>Statement</code> for sending SQL statements to the
* database.
*
* @exception SQLException if a database access error occurs
*/
public Statement createStatement() throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.createStatement());
}
/**
* (JDBC 2.0) Create a Statement that will create a ResultSet of the
* specified type and concurrency.
*
* @param resultSetType A result set type
* @param resultSetConcurrency A result set concurrency
*
* @exception SQLException if a database access error occurs
*/
public Statement createStatement(int resultSetType,
int resultSetConcurrency)
throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.createStatement(resultSetType, resultSetConcurrency));
}
/**
* Return the current auto-commit state.
*
* @exception SQLException if a database access error occurs
*/
public boolean getAutoCommit() throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.getAutoCommit());
}
/**
* Return the current catalog name for this Connection.
*
* @exception SQLException if a database access error occurs
*/
public String getCatalog() throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.getCatalog());
}
/**
* Get the metadata regarding this connection's database.
*
* @exception SQLException if a database access error occurs
*/
public DatabaseMetaData getMetaData() throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.getMetaData());
}
/**
* Return this Connection's current transaction isolation level.
*
* @exception SQLException if a database access error occurs
*/
public int getTransactionIsolation() throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.getTransactionIsolation());
}
/**
* (JDBC 2.0) Return the type map for this connection.
*
* @exception SQLException if a database access error occurs
*/
public Map getTypeMap() throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.getTypeMap());
}
/**
* Return the first warning reported by calls to this Connection.
*
* @exception SQLException if a database access error occurs
*/
public SQLWarning getWarnings() throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.getWarnings());
}
/**
* Return <code>true</code> if this Connection is closed.
*
* The GenericConnection.isClosed() method is only guaranteed to return true after
* GenericConnection.closed() has been called. This method cannot be called, in
* general, to determine if a database connection is valid or invalid.
*
* A typical JDBC client can determine that a connection is invalid by catching the
* exception that is thrown when a JDBC operation is attempted.
*
* @exception SQLException if a database access error occurs
*/
public boolean isClosed() throws SQLException {
return (closed);
}
/**
* Return <code>true</code> if this Connection is in read-only mode.
*
* @exception SQLException if a database access error occurs
*/
public boolean isReadOnly() throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.isReadOnly());
}
/**
* Convert the given SQL statement into the system's native SQL grammer.
*
* @param sql Statement to be processed
*/
public String nativeSQL(String sql) throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.nativeSQL(sql));
}
/**
* Create a <code>CallableStatement</code> object for calling database
* stored procedures.
*
* @param sql Statement to be processed
*
* @exception SQLException if a database access error occurs
*/
public CallableStatement prepareCall(String sql) throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.prepareCall(sql));
}
/**
* (JDBC 2.0) Create a CallableStatement object that will generate
* ResultSet objects with the given type and concurrency.
*
* @param sql Statement to be processed
* @param resultSetType A result set type
* @param resultSetConcurrency A result set concurrency
*
* @exception SQLException if a database access error occurs
*/
public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency)
throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.prepareCall(sql, resultSetType, resultSetConcurrency));
}
/**
* Create a <code>PreparedStatement</code> object for sending
* parameterized SQL statements to the database.
*
* @param sql Statement to be processed
*
* @exception SQLException if a database access error occurs
*/
public PreparedStatement prepareStatement(String sql) throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.prepareStatement(sql));
}
/**
* (JDBC 2.0) Create a PreparedStatement object that will generate
* ResultSet objects with the given type and concurrency.
*
* @param sql Statement to be processed
* @param resultSetType A result set type
* @param resultSetConcurrency A result set concurrency
*
* @exception SQLException if a database access error occurs
*/
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency)
throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
return (conn.prepareStatement(sql, resultSetType,
resultSetConcurrency));
}
/**
* Drop all changes made since the previous commit or rollback.
*
* @exception SQLException if a database access error occurs
*/
public void rollback() throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
conn.rollback();
}
/**
* Sets this connection's auto-commit mode.
*
* @param autoCommit The new auto-commit mode.
*
* @exception SQLException if a database access error occurs
*/
public void setAutoCommit(boolean autoCommit) throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
conn.setAutoCommit(autoCommit);
}
/**
* Set the catalog name for this Connection.
*
* @param catalog The new catalog name
*
* @exception SQLException if a database access error occurs
*/
public void setCatalog(String catalog) throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
conn.setCatalog(catalog);
}
/**
* Set the read-only mode of this connection.
*
* @param readOnly The new read-only mode
*
* @exception SQLException if a database access error occurs
*/
public void setReadOnly(boolean readOnly) throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
conn.setReadOnly(readOnly);
}
/**
* Set the transaction isolation level for this Connection.
*
* @param level The new transaction isolation level
*
* @exception SQLException if a database access error occurs
*/
public void setTransactionIsolation(int level) throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
conn.setTransactionIsolation(level);
}
/**
* (JDBC 2.0) Set the type map for this connection.
*
* @param map The new type map
*
* @exception SQLException if a database access error occurs
*/
public void setTypeMap(Map map) throws SQLException {
if (closed) throw new SQLException(SQLEXCEPTION_CLOSED);
conn.setTypeMap(map);
}
// -------------------------------------------------------- Package Methods
/**
* Return the actual connection that we are wrapping.
*/
Connection getConnection() {
return (this.conn); // FIXME - Good idea to return if closed?
}
/**
* Return the data source that owns this connection.
*/
DataSource getDataSource() {
// Do not check for closed exception, to allow for a fresh connection
return (this.source);
}
/**
* Set the closed status of this connection wrapper.
*
* Would usually only be called by the owning DataSource (source), with
* setClosed(false), when a pooled connection is being recycled.
*
*/
void setClosed(boolean closed) {
this.closed = closed;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org