You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by cr...@locus.apache.org on 2000/11/26 06:11:31 UTC
cvs commit: jakarta-struts/src/share/org/apache/struts/util GenericConnection.java GenericDataSource.java
craigmcc 00/11/25 21:11:31
Modified: . README
src/conf struts-config_1_0.dtd
src/doc release.xml
src/share/org/apache/struts/action Action.java
ActionResources.properties ActionServlet.java
Added: src/share/org/apache/struts/util GenericConnection.java
GenericDataSource.java
Log:
Initial implementation of a simple JDBC data source for Struts based
applications. The data source implements the javax.sql.DataSource
interface, and may be configured by new extensions to the
struts-config.xml DTD. More sophisticated data source implementations may
also be used, as long as they implement javax.sql.DataSource.
Revision Changes Path
1.11 +5 -1 jakarta-struts/README
Index: README
===================================================================
RCS file: /home/cvs/jakarta-struts/README,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- README 2000/11/03 01:54:32 1.10
+++ README 2000/11/26 05:11:27 1.11
@@ -1,4 +1,4 @@
-$Id: README,v 1.10 2000/11/03 01:54:32 craigmcc Exp $
+$Id: README,v 1.11 2000/11/26 05:11:27 craigmcc Exp $
Struts
======
@@ -48,6 +48,10 @@
available at <http://xml.apache.org>. Be sure to add the "jaxp.jar" and
"parser.jar" (or whatever JAR file comes with your parser) files to
your CLASSPATH environment variable.
+
+- Download and install the JDBC 2.0 Standard Extensions package from the
+ Java Software web site <http://java.sun.com/products/jdbc>, and install
+ the "jdbc2_0-stdext.jar" file on your classpath (or as a system extension).
- (*) Download and install a servlet container that supports the Servlet
API Specification, version 2.2 or later, and the JavaServer Pages (JSP)
1.2 +62 -2 jakarta-struts/src/conf/struts-config_1_0.dtd
Index: struts-config_1_0.dtd
===================================================================
RCS file: /home/cvs/jakarta-struts/src/conf/struts-config_1_0.dtd,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- struts-config_1_0.dtd 2000/09/20 04:16:11 1.1
+++ struts-config_1_0.dtd 2000/11/26 05:11:28 1.2
@@ -11,7 +11,7 @@
"-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd">
- $Id: struts-config_1_0.dtd,v 1.1 2000/09/20 04:16:11 craigmcc Exp $
+ $Id: struts-config_1_0.dtd,v 1.2 2000/11/26 05:11:28 craigmcc Exp $
-->
@@ -38,6 +38,13 @@
<!ENTITY % ClassName "CDATA">
+<!-- An "Integer" is a character string consisting solely of numeric digits,
+ optionally preceeded by a minus sign, that can be converted to a
+ 32-bit integer.
+-->
+<!ENTITY % Integer "CDATA">
+
+
<!-- A "Location" is a relative path, delimited by "/" characters, that
defines the location of a resource relative to the location of the
Struts configuration file itself.
@@ -72,8 +79,61 @@
hierarchy, and contains nested elements for all of the other
configuration settings.
-->
-<!ELEMENT struts-config (form-beans?, global-forwards?, action-mappings?)>
+<!ELEMENT struts-config (data-source, form-beans?, global-forwards?, action-mappings?)>
<!ATTLIST struts-config id ID #IMPLIED>
+
+
+<!-- The "data-source" element describes a JDBC 2.0 Standard Extension data
+ source object (that implements javax.sql.DataSource) which will be
+ configured according to the properties and nested elements found here,
+ and made available as a servlet context attribute (i.e. application
+ scope bean). The following attributes are defined:
+
+ type Fully qualified Java class name of the implementation
+ class (must implement javax.sql.DataSource).
+
+ NOTE: The following attributes are defined by the default data source
+ implementation, and only take effect for that class or subclasses of
+ that class.
+
+ autoCommit The default auto-commit state for newly created
+ connections.
+
+ description The description of this data source.
+
+ driverClass The Java class name of the JDBC driver to be used.
+ [REQUIRED]
+
+ loginTimeout The maximum number of seconds to wait for a connection
+ to be created or returned.
+
+ maxCount The maximum number of connections to be created.
+
+ minCount The minimum number of connections to be created.
+
+ password The database password to use when connecting. [REQUIRED]
+
+ readOnly The default read-only state for newly created
+ connections.
+
+ url The JDBC URL to use when connecting. [REQUIRED]
+
+ user The database username to use when connecting. [REQUIRED]
+
+-->
+<!ELEMENT data-source (set-property*)>
+<!ATTLIST data-source id ID #IMPLIED>
+<!ATTLIST data-source type %ClassName; "org.apache.struts.util.GenericDataSource">
+<!ATTLIST data-source autoCommit %Boolean; "true">
+<!ATTLIST data-source description CDATA #IMPLIED>
+<!ATTLIST data-source driverClass %ClassName; #REQUIRED>
+<!ATTLIST data-source loginTimeout %Integer; #IMPLIED>
+<!ATTLIST data-source maxCount %Integer; "2">
+<!ATTLIST data-source minCount %Integer; "1">
+<!ATTLIST data-source password CDATA #REQUIRED>
+<!ATTLIST data-source readOnly %Boolean; "false">
+<!ATTLIST data-source url CDATA #REQUIRED>
+<!ATTLIST data-source user CDATA #REQUIRED>
<!-- The "form-beans" element is the root of the set of form bean descriptors
1.11 +11 -0 jakarta-struts/src/doc/release.xml
Index: release.xml
===================================================================
RCS file: /home/cvs/jakarta-struts/src/doc/release.xml,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- release.xml 2000/11/19 03:12:01 1.10
+++ release.xml 2000/11/26 05:11:29 1.11
@@ -70,6 +70,17 @@
properties) only if the checkbox was actually checked.</li>
</ul>
+ <p>The following major new features have been added to the utility classes
+ library (package <code>org.apache.struts.util</code>):</p>
+ <ul>
+ <li>Initial implementation of a JDBC data source that implements the
+ <code>javax.sql.DataSource</code> interface from the JDBC 2.0 Standard
+ Extensions API. This implementation may be configured based on new
+ extensions to the Struts configuration file DTD, and the configured
+ data source / connection pool is made available to application components
+ as a servlet context attribute (i.e. an application scope bean).</li>
+ </ul>
+
<p>The following major new features have been added to the
<em>struts-bean</em> custom tag library (package
<code>org.apache.struts.taglib.bean</code>):</p>
1.9 +13 -4 jakarta-struts/src/share/org/apache/struts/action/Action.java
Index: Action.java
===================================================================
RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/action/Action.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- Action.java 2000/11/18 22:10:55 1.8
+++ Action.java 2000/11/26 05:11:30 1.9
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/action/Action.java,v 1.8 2000/11/18 22:10:55 craigmcc Exp $
- * $Revision: 1.8 $
- * $Date: 2000/11/18 22:10:55 $
+ * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/action/Action.java,v 1.9 2000/11/26 05:11:30 craigmcc Exp $
+ * $Revision: 1.9 $
+ * $Date: 2000/11/26 05:11:30 $
*
* ====================================================================
*
@@ -105,13 +105,22 @@
* by this Action.
*
* @author Craig R. McClanahan
- * @version $Revision: 1.8 $ $Date: 2000/11/18 22:10:55 $
+ * @version $Revision: 1.9 $ $Date: 2000/11/26 05:11:30 $
*/
public class Action {
// ----------------------------------------------------- Manifest Constants
+
+
+ /**
+ * The context attribute key under which our configured data source
+ * (which must implement <code>javax.sql.DataSource</code>) is stored,
+ * if one is configured for this application.
+ */
+ public static final String DATA_SOURCE_KEY =
+ "org.apache.struts.action.DATA_SOURCE";
/**
1.5 +4 -0 jakarta-struts/src/share/org/apache/struts/action/ActionResources.properties
Index: ActionResources.properties
===================================================================
RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/action/ActionResources.properties,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- ActionResources.properties 2000/10/15 03:29:15 1.4
+++ ActionResources.properties 2000/11/26 05:11:30 1.5
@@ -6,7 +6,11 @@
configMapping=Configuring mapping for path {0}
configMissing=Missing configuration resource for path {0}
configParse=Parsing error processing resource path {0}
+dataSource.destroy=Finalizing application data source
+dataSource.init=Initializing application data source
+destroyDataSource=Exception destroying application data source
finalizing=Finalizing this controller servlet
+initDataSource=Exception initializing application data source
noInput=No input attribute for mapping path {0}
processInvalid=Invalid path {0} was requested
processPath=No process path included in this request
1.36 +97 -4 jakarta-struts/src/share/org/apache/struts/action/ActionServlet.java
Index: ActionServlet.java
===================================================================
RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/action/ActionServlet.java,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- ActionServlet.java 2000/11/19 02:11:15 1.35
+++ ActionServlet.java 2000/11/26 05:11:30 1.36
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/action/ActionServlet.java,v 1.35 2000/11/19 02:11:15 craigmcc Exp $
- * $Revision: 1.35 $
- * $Date: 2000/11/19 02:11:15 $
+ * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/action/ActionServlet.java,v 1.36 2000/11/26 05:11:30 craigmcc Exp $
+ * $Revision: 1.36 $
+ * $Date: 2000/11/26 05:11:30 $
*
* ====================================================================
*
@@ -66,6 +66,7 @@
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
+import java.sql.SQLException;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Locale;
@@ -78,9 +79,11 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import javax.sql.DataSource;
import org.apache.struts.digester.Digester;
import org.apache.struts.taglib.form.Constants;
import org.apache.struts.util.BeanUtils;
+import org.apache.struts.util.GenericDataSource;
import org.apache.struts.util.MessageResources;
import org.xml.sax.SAXException;
@@ -200,7 +203,7 @@
* </ul>
*
* @author Craig R. McClanahan
- * @version $Revision: 1.35 $ $Date: 2000/11/19 02:11:15 $
+ * @version $Revision: 1.36 $ $Date: 2000/11/26 05:11:30 $
*/
public class ActionServlet
@@ -237,6 +240,13 @@
/**
+ * The JDBC data source that has been configured for this application,
+ * if any.
+ */
+ protected DataSource dataSource = null;
+
+
+ /**
* The debugging detail level for this servlet.
*/
protected int debug = 0;
@@ -372,6 +382,7 @@
destroyActions();
destroyApplication();
+ destroyDataSource();
destroyInternal();
}
@@ -396,6 +407,7 @@
(internal.getMessage("configIO", config));
}
initUpload();
+ initDataSource();
initOther();
}
@@ -522,7 +534,9 @@
* @return The size in bytes of the buffer
*/
public int getBufferSize() {
+
return bufferSize;
+
}
@@ -538,6 +552,16 @@
/**
+ * Return the JDBC data source associated with this application, if any.
+ */
+ public DataSource getDataSource() {
+
+ return (this.dataSource);
+
+ }
+
+
+ /**
* Return the Java class name of the class used to instantiate
* <code>ActionFormBean</code> objects.
*/
@@ -697,7 +721,21 @@
* @param bufferSize The size in bytes of the buffer
*/
public void setBufferSize(int bufferSize) {
+
this.bufferSize = bufferSize;
+
+ }
+
+
+ /**
+ * Set the data source object to be used by this application.
+ *
+ * @param dataSource The data source to be used
+ */
+ public void setDataSource(DataSource dataSource) {
+
+ this.dataSource = dataSource;
+
}
@@ -807,6 +845,29 @@
/**
+ * Gracefully terminate use of the data source associated with this
+ * application (if any).
+ */
+ protected void destroyDataSource() {
+
+ if (dataSource == null)
+ return;
+ if (dataSource instanceof GenericDataSource) {
+ if (debug >= 1)
+ log(internal.getMessage("dataSource.destroy"));
+ try {
+ ((GenericDataSource) dataSource).close();
+ } catch (SQLException e) {
+ log(internal.getMessage("destroyDataSource"), e);
+ }
+ dataSource = null;
+ getServletContext().removeAttribute(Action.DATA_SOURCE_KEY);
+ }
+
+ }
+
+
+ /**
* Gracefully terminate use of the internal MessageResources.
*/
protected void destroyInternal() {
@@ -849,6 +910,29 @@
/**
+ * Initialize use of the data source associated with this
+ * application (if any).
+ */
+ protected void initDataSource() {
+
+ if (dataSource == null)
+ return;
+ if (dataSource instanceof GenericDataSource) {
+ if (debug >= 1)
+ log(internal.getMessage("dataSource.init"));
+ try {
+ ((GenericDataSource) dataSource).open();
+ } catch (SQLException e) {
+ log(internal.getMessage("initDataSource"), e);
+ }
+ getServletContext().setAttribute(Action.DATA_SOURCE_KEY,
+ dataSource);
+ }
+
+ }
+
+
+ /**
* Initialize the debugging detail level for this application.
*
* @exception ServletException if we cannot initialize these resources
@@ -886,6 +970,15 @@
// Configure the processing rules
// FIXME "struts-config/action-mappings" type attribute
+
+ digester.addObjectCreate("struts-config/data-source",
+ "org.apache.struts.util.GenericDataSource",
+ "type");
+ digester.addSetProperties("struts-config/data-source");
+ digester.addSetNext("struts-config/data-source",
+ "setDataSource", "javax.sql.DataSource");
+ digester.addSetProperty("struts-config/data-source/set-property",
+ "property", "value");
digester.addObjectCreate("struts-config/action-mappings/action",
mappingClass, "className");
1.1 jakarta-struts/src/share/org/apache/struts/util/GenericConnection.java
Index: GenericConnection.java
===================================================================
/*
* $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/GenericConnection.java,v 1.1 2000/11/26 05:11:31 craigmcc Exp $
* $Revision: 1.1 $
* $Date: 2000/11/26 05:11:31 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 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", "Tomcat", 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.util;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
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.
*
* @author Craig R. McClanahan
* @version $Revision: 1.1 $ $Date: 2000/11/26 05:11:31 $
*/
public class GenericConnection implements Connection {
// ----------------------------------------------------------- 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
}
this.readOnly = readOnly;
this.conn.setAutoCommit(this.autoCommit);
this.conn.setReadOnly(this.readOnly);
}
// ----------------------------------------------------- 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 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 {
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 {
// 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) {
;
}
try {
conn.setReadOnly(this.readOnly);
} catch (SQLException e) {
;
}
try {
conn.clearWarnings();
} catch (SQLException e) {
;
}
// 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 {
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 {
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 {
return (conn.createStatement(resultSetType, resultSetConcurrency));
}
/**
* Return the current auto-commit state.
*
* @exception SQLException if a database access error occurs
*/
public boolean getAutoCommit() throws SQLException {
return (conn.getAutoCommit());
}
/**
* Return the current catalog name for this Connection.
*
* @exception SQLException if a database access error occurs
*/
public String getCatalog() throws SQLException {
return (conn.getCatalog());
}
/**
* Get the metadata regarding this connection's database.
*
* @exception SQLException if a database access error occurs
*/
public DatabaseMetaData getMetaData() throws SQLException {
return (conn.getMetaData());
}
/**
* Return this Connection's current transaction isolation level.
*
* @exception SQLException if a database access error occurs
*/
public int getTransactionIsolation() throws SQLException {
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 {
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 {
return (conn.getWarnings());
}
/**
* Return <code>true</code> if this Connection is closed.
*
* @exception SQLException if a database access error occurs
*/
public boolean isClosed() throws SQLException {
return (false); // FIXME - isClosed()
}
/**
* 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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
conn.setTypeMap(map);
}
// -------------------------------------------------------- Package Methods
/**
* Return the actual connection that we are wrapping.
*/
Connection getConnection() {
return (this.conn);
}
/**
* Return the data source that owns this connection.
*/
DataSource getDataSource() {
return (this.source);
}
}
1.1 jakarta-struts/src/share/org/apache/struts/util/GenericDataSource.java
Index: GenericDataSource.java
===================================================================
/*
* $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/GenericDataSource.java,v 1.1 2000/11/26 05:11:31 craigmcc Exp $
* $Revision: 1.1 $
* $Date: 2000/11/26 05:11:31 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 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", "Tomcat", 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.util;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.Properties;
import javax.sql.DataSource;
/**
* 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. It
* always returns connections based on the username and password configured
* with <code>setUsername()</code> and <code>setPassword()</code>,
* respectively.
*
* @author Craig R. McClanahan
* @version $Revision: 1.1 $ $Date: 2000/11/26 05:11:31 $
*/
public class GenericDataSource implements DataSource {
// ----------------------------------------------------- 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;
/**
* The login timeout for this data source.
*/
protected int loginTimeout = 0;
/**
* The log writer for this data source.
*/
protected PrintWriter logWriter = null;
/**
* The connection properties for use in establishing connections.
*/
protected Properties properties = new Properties();
// ------------------------------------------------------------- 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 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 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;
// 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 ((loginTimeout > 0) && (seconds >= loginTimeout))
break;
// Return an existing connection from the pool if there is one
synchronized (connections) {
if (!connections.isEmpty()) {
useCount++;
return ((Connection) connections.removeFirst());
}
}
// Create a new connection if we are not yet at the maximum
if (activeCount < maxCount) {
Connection conn = createConnection();
useCount++;
return (conn);
}
// Wait for an existing connection to be returned
try {
Thread.sleep(1000);
seconds++;
} catch (InterruptedException e) {
;
}
}
// We have timed out awaiting an available connection
throw new SQLException
("getConnection: Timeout awaiting connection");
}
/**
* Attempt to establish a database connection. <b>WARNING</b> - The
* specified username and password are ignored 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 {
return (getConnection());
}
/**
* 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");
// 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;
// Instantiate our database driver
try {
Class clazz = Class.forName(driverClass);
driver = (Driver) clazz.newInstance();
} catch (Throwable t) {
throw new SQLException("createConnection: " + 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 {
Connection conn = driver.connect(url, properties);
activeCount++;
return (new GenericConnection(this, conn, autoCommit, readOnly));
}
// -------------------------------------------------------- Package Methods
/**
* Return this connection to the available connection pool.
*
* @param conn The connection being returned
*/
void returnConnection(GenericConnection conn) {
synchronized (connections) {
connections.addLast(conn);
useCount--;
}
}
}