1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Run pgjindent for Java folks.

This commit is contained in:
Bruce Momjian
2002-09-06 21:23:06 +00:00
parent b4295d052e
commit f37c1c486a
71 changed files with 8582 additions and 7709 deletions

View File

@ -6,194 +6,206 @@ import java.net.ConnectException;
import java.sql.*;
import org.postgresql.util.PSQLException;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Connection.java,v 1.1 2002/07/23 03:59:55 barry Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Connection.java,v 1.2 2002/09/06 21:23:06 momjian Exp $
* This class defines methods of the jdbc2 specification. This class extends
* org.postgresql.jdbc1.AbstractJdbc1Connection which provides the jdbc1
* methods. The real Connection class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Connection
*/
public abstract class AbstractJdbc2Connection extends org.postgresql.jdbc1.AbstractJdbc1Connection
{
/*
* The current type mappings
*/
protected java.util.Map typemap;
/*
* The current type mappings
*/
protected java.util.Map typemap;
public java.sql.Statement createStatement() throws SQLException
{
// The spec says default of TYPE_FORWARD_ONLY but everyone is used to
// using TYPE_SCROLL_INSENSITIVE
return createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
}
public java.sql.Statement createStatement() throws SQLException
{
// The spec says default of TYPE_FORWARD_ONLY but everyone is used to
// using TYPE_SCROLL_INSENSITIVE
return createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
}
public abstract java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException;
public abstract java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException;
public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
{
return prepareStatement(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
}
public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
{
return prepareStatement(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
}
public abstract java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException;
public abstract java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException;
public java.sql.CallableStatement prepareCall(String sql) throws SQLException
{
return prepareCall(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
}
public java.sql.CallableStatement prepareCall(String sql) throws SQLException
{
return prepareCall(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
}
public abstract java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException;
public abstract java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException;
public java.util.Map getTypeMap() throws SQLException
{
return typemap;
}
public void setTypeMap(java.util.Map map) throws SQLException
{
typemap = map;
}
public void cancelQuery() throws SQLException
{
org.postgresql.PG_Stream cancelStream = null;
try {
cancelStream = new org.postgresql.PG_Stream(PG_HOST, PG_PORT);
} catch (ConnectException cex) {
// Added by Peter Mount <peter@retep.org.uk>
// ConnectException is thrown when the connection cannot be made.
// we trap this an return a more meaningful message for the end user
throw new PSQLException ("postgresql.con.refused");
} catch (IOException e) {
throw new PSQLException ("postgresql.con.failed",e);
}
// Now we need to construct and send a cancel packet
try {
cancelStream.SendInteger(16, 4);
cancelStream.SendInteger(80877102, 4);
cancelStream.SendInteger(pid, 4);
cancelStream.SendInteger(ckey, 4);
cancelStream.flush();
}
catch(IOException e) {
throw new PSQLException("postgresql.con.failed",e);
}
finally {
try {
if(cancelStream != null)
cancelStream.close();
}
catch(IOException e) {} // Ignore
}
}
/*
* This overides the standard internal getObject method so that we can
* check the jdbc2 type map first
*/
public Object getObject(String type, String value) throws SQLException
{
if (typemap != null)
{
SQLData d = (SQLData) typemap.get(type);
if (d != null)
{
// Handle the type (requires SQLInput & SQLOutput classes to be implemented)
throw org.postgresql.Driver.notImplemented();
}
}
// Default to the original method
return super.getObject(type, value);
}
//Because the get/setLogStream methods are deprecated in JDBC2
//we use the get/setLogWriter methods here for JDBC2 by overriding
//the base version of this method
protected void enableDriverManagerLogging() {
if (DriverManager.getLogWriter() == null) {
DriverManager.setLogWriter(new PrintWriter(System.out));
}
public java.util.Map getTypeMap() throws SQLException
{
return typemap;
}
/*
* This implemetation uses the jdbc2Types array to support the jdbc2
* datatypes. Basically jdbc1 and jdbc2 are the same, except that
* jdbc2 adds the Array types.
*/
public int getSQLType(String pgTypeName)
{
int sqlType = Types.OTHER; // default value
for (int i = 0;i < jdbc2Types.length;i++)
{
if (pgTypeName.equals(jdbc2Types[i]))
{
sqlType = jdbc2Typei[i];
break;
}
}
return sqlType;
}
public void setTypeMap(java.util.Map map) throws SQLException
{
typemap = map;
}
/*
* This table holds the org.postgresql names for the types supported.
* Any types that map to Types.OTHER (eg POINT) don't go into this table.
* They default automatically to Types.OTHER
*
* Note: This must be in the same order as below.
*
* Tip: keep these grouped together by the Types. value
*/
private static final String jdbc2Types[] = {
"int2",
"int4", "oid",
"int8",
"cash", "money",
"numeric",
"float4",
"float8",
"bpchar", "char", "char2", "char4", "char8", "char16",
"varchar", "text", "name", "filename",
"bytea",
"bool",
"date",
"time",
"abstime", "timestamp", "timestamptz",
"_bool", "_char", "_int2", "_int4", "_text",
"_oid", "_varchar", "_int8", "_float4", "_float8",
"_abstime", "_date", "_time", "_timestamp", "_numeric",
"_bytea"
};
public void cancelQuery() throws SQLException
{
org.postgresql.PG_Stream cancelStream = null;
try
{
cancelStream = new org.postgresql.PG_Stream(PG_HOST, PG_PORT);
}
catch (ConnectException cex)
{
// Added by Peter Mount <peter@retep.org.uk>
// ConnectException is thrown when the connection cannot be made.
// we trap this an return a more meaningful message for the end user
throw new PSQLException ("postgresql.con.refused");
}
catch (IOException e)
{
throw new PSQLException ("postgresql.con.failed", e);
}
/*
* This table holds the JDBC type for each entry above.
*
* Note: This must be in the same order as above
*
* Tip: keep these grouped together by the Types. value
*/
private static final int jdbc2Typei[] = {
Types.SMALLINT,
Types.INTEGER, Types.INTEGER,
Types.BIGINT,
Types.DOUBLE, Types.DOUBLE,
Types.NUMERIC,
Types.REAL,
Types.DOUBLE,
Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR,
Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
Types.BINARY,
Types.BIT,
Types.DATE,
Types.TIME,
Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP,
Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
Types.ARRAY
};
// Now we need to construct and send a cancel packet
try
{
cancelStream.SendInteger(16, 4);
cancelStream.SendInteger(80877102, 4);
cancelStream.SendInteger(pid, 4);
cancelStream.SendInteger(ckey, 4);
cancelStream.flush();
}
catch (IOException e)
{
throw new PSQLException("postgresql.con.failed", e);
}
finally
{
try
{
if (cancelStream != null)
cancelStream.close();
}
catch (IOException e)
{} // Ignore
}
}
/*
* This overides the standard internal getObject method so that we can
* check the jdbc2 type map first
*/
public Object getObject(String type, String value) throws SQLException
{
if (typemap != null)
{
SQLData d = (SQLData) typemap.get(type);
if (d != null)
{
// Handle the type (requires SQLInput & SQLOutput classes to be implemented)
throw org.postgresql.Driver.notImplemented();
}
}
// Default to the original method
return super.getObject(type, value);
}
//Because the get/setLogStream methods are deprecated in JDBC2
//we use the get/setLogWriter methods here for JDBC2 by overriding
//the base version of this method
protected void enableDriverManagerLogging()
{
if (DriverManager.getLogWriter() == null)
{
DriverManager.setLogWriter(new PrintWriter(System.out));
}
}
/*
* This implemetation uses the jdbc2Types array to support the jdbc2
* datatypes. Basically jdbc1 and jdbc2 are the same, except that
* jdbc2 adds the Array types.
*/
public int getSQLType(String pgTypeName)
{
int sqlType = Types.OTHER; // default value
for (int i = 0;i < jdbc2Types.length;i++)
{
if (pgTypeName.equals(jdbc2Types[i]))
{
sqlType = jdbc2Typei[i];
break;
}
}
return sqlType;
}
/*
* This table holds the org.postgresql names for the types supported.
* Any types that map to Types.OTHER (eg POINT) don't go into this table.
* They default automatically to Types.OTHER
*
* Note: This must be in the same order as below.
*
* Tip: keep these grouped together by the Types. value
*/
private static final String jdbc2Types[] = {
"int2",
"int4", "oid",
"int8",
"cash", "money",
"numeric",
"float4",
"float8",
"bpchar", "char", "char2", "char4", "char8", "char16",
"varchar", "text", "name", "filename",
"bytea",
"bool",
"date",
"time",
"abstime", "timestamp", "timestamptz",
"_bool", "_char", "_int2", "_int4", "_text",
"_oid", "_varchar", "_int8", "_float4", "_float8",
"_abstime", "_date", "_time", "_timestamp", "_numeric",
"_bytea"
};
/*
* This table holds the JDBC type for each entry above.
*
* Note: This must be in the same order as above
*
* Tip: keep these grouped together by the Types. value
*/
private static final int jdbc2Typei[] = {
Types.SMALLINT,
Types.INTEGER, Types.INTEGER,
Types.BIGINT,
Types.DOUBLE, Types.DOUBLE,
Types.NUMERIC,
Types.REAL,
Types.DOUBLE,
Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR,
Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
Types.BINARY,
Types.BIT,
Types.DATE,
Types.TIME,
Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP,
Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
Types.ARRAY
};

View File

@ -13,7 +13,7 @@ public abstract class AbstractJdbc2DatabaseMetaData extends org.postgresql.jdbc1
public AbstractJdbc2DatabaseMetaData(AbstractJdbc2Connection conn)
{
super(conn);
super(conn);
}
@ -61,18 +61,18 @@ public abstract class AbstractJdbc2DatabaseMetaData extends org.postgresql.jdbc1
/* lots of unsupported stuff... */
public boolean ownUpdatesAreVisible(int type) throws SQLException
{
return true;
return true;
}
public boolean ownDeletesAreVisible(int type) throws SQLException
{
return true;
return true;
}
public boolean ownInsertsAreVisible(int type) throws SQLException
{
// indicates that
return true;
// indicates that
return true;
}
public boolean othersUpdatesAreVisible(int type) throws SQLException
@ -117,10 +117,10 @@ public abstract class AbstractJdbc2DatabaseMetaData extends org.postgresql.jdbc1
* Return user defined types in a schema
*/
public java.sql.ResultSet getUDTs(String catalog,
String schemaPattern,
String typeNamePattern,
int[] types
) throws SQLException
String schemaPattern,
String typeNamePattern,
int[] types
) throws SQLException
{
throw org.postgresql.Driver.notImplemented();
}

View File

@ -19,7 +19,7 @@ public abstract class AbstractJdbc2ResultSetMetaData extends org.postgresql.jdbc
*/
public AbstractJdbc2ResultSetMetaData(Vector rows, Field[] fields)
{
super(rows, fields);
super(rows, fields);
}
/*
@ -459,53 +459,53 @@ public abstract class AbstractJdbc2ResultSetMetaData extends org.postgresql.jdbc
// This can hook into our PG_Object mechanism
/**
* Returns the fully-qualified name of the Java class whose instances
* Returns the fully-qualified name of the Java class whose instances
* are manufactured if the method <code>ResultSet.getObject</code>
* is called to retrieve a value from the column.
*
*
* <code>ResultSet.getObject</code> may return a subclass of the class
* returned by this method.
*
* @param column the first column is 1, the second is 2, ...
* @return the fully-qualified name of the class in the Java programming
* language that would be used by the method
* <code>ResultSet.getObject</code> to retrieve the value in the specified
* column. This is the class name used for custom mapping.
* language that would be used by the method
* <code>ResultSet.getObject</code> to retrieve the value in the specified
* column. This is the class name used for custom mapping.
* @exception SQLException if a database access error occurs
*/
public String getColumnClassName(int column) throws SQLException
{
/*
The following data type mapping came from ../Field.java.
/*
The following data type mapping came from ../Field.java.
"int2",
"int4","oid",
"int8",
"cash","money",
"numeric",
"float4",
"float8",
"bpchar","char","char2","char4","char8","char16",
"varchar","text","name","filename",
"bool",
"date",
"time",
"abstime","timestamp"
"int2",
"int4","oid",
"int8",
"cash","money",
"numeric",
"float4",
"float8",
"bpchar","char","char2","char4","char8","char16",
"varchar","text","name","filename",
"bool",
"date",
"time",
"abstime","timestamp"
Types.SMALLINT,
Types.INTEGER,Types.INTEGER,
Types.BIGINT,
Types.DOUBLE,Types.DOUBLE,
Types.NUMERIC,
Types.REAL,
Types.DOUBLE,
Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,
Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,
Types.BIT,
Types.DATE,
Types.TIME,
Types.TIMESTAMP,Types.TIMESTAMP
*/
Types.SMALLINT,
Types.INTEGER,Types.INTEGER,
Types.BIGINT,
Types.DOUBLE,Types.DOUBLE,
Types.NUMERIC,
Types.REAL,
Types.DOUBLE,
Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,
Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,
Types.BIT,
Types.DATE,
Types.TIME,
Types.TIMESTAMP,Types.TIMESTAMP
*/
Field field = getField(column);
int sql_type = field.getSQLType();
@ -513,40 +513,40 @@ public abstract class AbstractJdbc2ResultSetMetaData extends org.postgresql.jdbc
switch (sql_type)
{
case Types.BIT:
return("java.lang.Boolean");
return ("java.lang.Boolean");
case Types.SMALLINT:
return("java.lang.Short");
return ("java.lang.Short");
case Types.INTEGER:
return("java.lang.Integer");
return ("java.lang.Integer");
case Types.BIGINT:
return("java.lang.Long");
return ("java.lang.Long");
case Types.NUMERIC:
return("java.math.BigDecimal");
return ("java.math.BigDecimal");
case Types.REAL:
return("java.lang.Float");
return ("java.lang.Float");
case Types.DOUBLE:
return("java.lang.Double");
return ("java.lang.Double");
case Types.CHAR:
case Types.VARCHAR:
return("java.lang.String");
return ("java.lang.String");
case Types.DATE:
return("java.sql.Date");
return ("java.sql.Date");
case Types.TIME:
return("java.sql.Time");
return ("java.sql.Time");
case Types.TIMESTAMP:
return("java.sql.Timestamp");
return ("java.sql.Timestamp");
case Types.BINARY:
case Types.VARBINARY:
return("[B");
return ("[B");
case Types.ARRAY:
return("java.sql.Array");
return ("java.sql.Array");
default:
String type = field.getPGType();
if ("unknown".equals(type))
{
return("java.lang.String");
return ("java.lang.String");
}
return("java.lang.Object");
return ("java.lang.Object");
}
}
}

View File

@ -8,7 +8,7 @@ import java.util.Vector;
import org.postgresql.largeobject.*;
import org.postgresql.util.PSQLException;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.5 2002/09/02 03:07:36 barry Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.6 2002/09/06 21:23:06 momjian Exp $
* This class defines methods of the jdbc2 specification. This class extends
* org.postgresql.jdbc1.AbstractJdbc1Statement which provides the jdbc1
* methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Statement
@ -45,8 +45,8 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
*/
public boolean execute() throws SQLException
{
boolean l_return = super.execute();
//Now do the jdbc2 specific stuff
boolean l_return = super.execute();
//Now do the jdbc2 specific stuff
//required for ResultSet.getStatement() to work and updateable resultsets
((AbstractJdbc2ResultSet)result).setStatement((Statement)this);
@ -64,7 +64,7 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
public void clearBatch() throws SQLException
{
batch = null;
batch = null;
}
public int[] executeBatch() throws SQLException
@ -86,7 +86,7 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
PBatchUpdateException updex =
new PBatchUpdateException("postgresql.stat.batch.error",
new Integer(i), batch.elementAt(i), resultSucceeded);
new Integer(i), batch.elementAt(i), resultSucceeded);
updex.setNextException(e);
throw updex;
@ -183,12 +183,12 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
// is buffered internally anyhow, so there would be no performance
// boost gained, if anything it would be worse!
int bytesRemaining = (int)x.length();
int numRead = l_inStream.read(buf,0,Math.min(buf.length,bytesRemaining));
int numRead = l_inStream.read(buf, 0, Math.min(buf.length, bytesRemaining));
while (numRead != -1 && bytesRemaining > 0)
{
bytesRemaining -= numRead;
los.write(buf,0,numRead);
numRead = l_inStream.read(buf,0,Math.min(buf.length,bytesRemaining));
bytesRemaining -= numRead;
los.write(buf, 0, numRead);
numRead = l_inStream.read(buf, 0, Math.min(buf.length, bytesRemaining));
}
los.close();
}
@ -384,9 +384,10 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
}
//This is needed by AbstractJdbc2ResultSet to determine if the query is updateable or not
protected String[] getSqlFragments() {
return m_sqlFragments;
}
//This is needed by AbstractJdbc2ResultSet to determine if the query is updateable or not
protected String[] getSqlFragments()
{
return m_sqlFragments;
}
}

View File

@ -27,7 +27,7 @@ public class Array implements java.sql.Array
{
private org.postgresql.PGConnection conn = null;
private org.postgresql.Field field = null;
private ResultSet rs;
private ResultSet rs;
private int idx = 0;
private String rawString = null;
@ -44,7 +44,7 @@ public class Array implements java.sql.Array
{
this.conn = conn;
this.field = field;
this.rs = rs;
this.rs = rs;
this.idx = idx;
this.rawString = ((AbstractJdbc2ResultSet)rs).getFixedString(idx);
}
@ -76,9 +76,9 @@ public class Array implements java.sql.Array
ArrayList array = new ArrayList();
/* Check if the String is also not an empty array
* otherwise there will be an exception thrown below
* in the ResultSet.toX with an empty string.
* -- Doug Fields <dfields-pg-jdbc@pexicom.com> Feb 20, 2002 */
* otherwise there will be an exception thrown below
* in the ResultSet.toX with an empty string.
* -- Doug Fields <dfields-pg-jdbc@pexicom.com> Feb 20, 2002 */
if ( rawString != null && !rawString.equals("{}") )
{
@ -88,9 +88,9 @@ public class Array implements java.sql.Array
boolean insideString = false;
for ( int i = 0; i < chars.length; i++ )
{
if ( chars[i] == '\\' )
//escape character that we need to skip
i++;
if ( chars[i] == '\\' )
//escape character that we need to skip
i++;
if ( chars[i] == '{' )
{
if ( foundOpen ) // Only supports 1-D arrays for now

View File

@ -6,55 +6,55 @@ import java.util.Vector;
import java.util.Hashtable;
import org.postgresql.Field;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Connection.java,v 1.4 2002/07/26 05:29:35 barry Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Connection.java,v 1.5 2002/09/06 21:23:06 momjian Exp $
* This class implements the java.sql.Connection interface for JDBC2.
* However most of the implementation is really done in
* However most of the implementation is really done in
* org.postgresql.jdbc2.AbstractJdbc2Connection or one of it's parents
*/
public class Jdbc2Connection extends org.postgresql.jdbc2.AbstractJdbc2Connection implements java.sql.Connection
{
public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
{
Jdbc2Statement s = new Jdbc2Statement(this);
s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{
Jdbc2PreparedStatement s = new Jdbc2PreparedStatement(this, sql);
s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{
Jdbc2CallableStatement s = new org.postgresql.jdbc2.Jdbc2CallableStatement(this,sql);
public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
{
Jdbc2Statement s = new Jdbc2Statement(this);
s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
public java.sql.DatabaseMetaData getMetaData() throws SQLException
{
if (metadata == null)
metadata = new org.postgresql.jdbc2.Jdbc2DatabaseMetaData(this);
return metadata;
}
public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException
{
return new Jdbc2ResultSet(this, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
}
public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{
Jdbc2PreparedStatement s = new Jdbc2PreparedStatement(this, sql);
s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount) throws SQLException
{
return new Jdbc2ResultSet(this, statement, fields, tuples, status, updateCount, 0, false);
}
public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{
Jdbc2CallableStatement s = new org.postgresql.jdbc2.Jdbc2CallableStatement(this, sql);
s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
public java.sql.DatabaseMetaData getMetaData() throws SQLException
{
if (metadata == null)
metadata = new org.postgresql.jdbc2.Jdbc2DatabaseMetaData(this);
return metadata;
}
public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException
{
return new Jdbc2ResultSet(this, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
}
public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount) throws SQLException
{
return new Jdbc2ResultSet(this, statement, fields, tuples, status, updateCount, 0, false);
}
}

View File

@ -5,9 +5,9 @@ import java.sql.*;
import java.util.Vector;
import org.postgresql.Field;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2ResultSet.java,v 1.4 2002/08/14 20:35:39 barry Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2ResultSet.java,v 1.5 2002/09/06 21:23:06 momjian Exp $
* This class implements the java.sql.ResultSet interface for JDBC2.
* However most of the implementation is really done in
* However most of the implementation is really done in
* org.postgresql.jdbc2.AbstractJdbc2ResultSet or one of it's parents
*/
public class Jdbc2ResultSet extends org.postgresql.jdbc2.AbstractJdbc2ResultSet implements java.sql.ResultSet
@ -23,13 +23,15 @@ public class Jdbc2ResultSet extends org.postgresql.jdbc2.AbstractJdbc2ResultSet
return new Jdbc2ResultSetMetaData(rows, fields);
}
public java.sql.Clob getClob(int i) throws SQLException {
return new org.postgresql.jdbc2.Jdbc2Clob(connection, getInt(i));
}
public java.sql.Clob getClob(int i) throws SQLException
{
return new org.postgresql.jdbc2.Jdbc2Clob(connection, getInt(i));
}
public java.sql.Blob getBlob(int i) throws SQLException {
return new org.postgresql.jdbc2.Jdbc2Blob(connection, getInt(i));
}
public java.sql.Blob getBlob(int i) throws SQLException
{
return new org.postgresql.jdbc2.Jdbc2Blob(connection, getInt(i));
}
}

View File

@ -4,7 +4,7 @@ public class Jdbc2ResultSetMetaData extends AbstractJdbc2ResultSetMetaData imple
{
public Jdbc2ResultSetMetaData(java.util.Vector rows, org.postgresql.Field[] fields)
{
super(rows, fields);
super(rows, fields);
}
}

View File

@ -3,9 +3,9 @@ package org.postgresql.jdbc2;
import java.sql.*;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Statement.java,v 1.2 2002/07/24 22:08:43 barry Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Statement.java,v 1.3 2002/09/06 21:23:06 momjian Exp $
* This class implements the java.sql.Statement interface for JDBC2.
* However most of the implementation is really done in
* However most of the implementation is really done in
* org.postgresql.jdbc2.AbstractJdbc2Statement or one of it's parents
*/
public class Jdbc2Statement extends org.postgresql.jdbc2.AbstractJdbc2Statement implements java.sql.Statement

View File

@ -8,217 +8,249 @@ import java.sql.*;
* Base class for data sources and related classes.
*
* @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $
* @version $Revision: 1.2 $
*/
public abstract class BaseDataSource implements Referenceable {
// Load the normal driver, since we'll use it to actually connect to the
// database. That way we don't have to maintain the connecting code in
// multiple places.
static {
try {
Class.forName("org.postgresql.Driver");
} catch (ClassNotFoundException e) {
System.err.println("PostgreSQL DataSource unable to load PostgreSQL JDBC Driver");
}
}
public abstract class BaseDataSource implements Referenceable
{
// Load the normal driver, since we'll use it to actually connect to the
// database. That way we don't have to maintain the connecting code in
// multiple places.
static {
try
{
Class.forName("org.postgresql.Driver");
}
catch (ClassNotFoundException e)
{
System.err.println("PostgreSQL DataSource unable to load PostgreSQL JDBC Driver");
}
}
// Needed to implement the DataSource/ConnectionPoolDataSource interfaces
private transient PrintWriter logger;
// Don't track loginTimeout, since we'd just ignore it anyway
// Needed to implement the DataSource/ConnectionPoolDataSource interfaces
private transient PrintWriter logger;
// Don't track loginTimeout, since we'd just ignore it anyway
// Standard properties, defined in the JDBC 2.0 Optional Package spec
private String serverName = "localhost";
private String databaseName;
private String user;
private String password;
private int portNumber;
// Standard properties, defined in the JDBC 2.0 Optional Package spec
private String serverName = "localhost";
private String databaseName;
private String user;
private String password;
private int portNumber;
/**
* Gets a connection to the PostgreSQL database. The database is identified by the
* DataSource properties serverName, databaseName, and portNumber. The user to
* connect as is identified by the DataSource properties user and password.
*
* @return A valid database connection.
* @throws SQLException
* Occurs when the database connection cannot be established.
*/
public Connection getConnection() throws SQLException {
return getConnection(user, password);
}
/**
* Gets a connection to the PostgreSQL database. The database is identified by the
* DataSource properties serverName, databaseName, and portNumber. The user to
* connect as is identified by the DataSource properties user and password.
*
* @return A valid database connection.
* @throws SQLException
* Occurs when the database connection cannot be established.
*/
public Connection getConnection() throws SQLException
{
return getConnection(user, password);
}
/**
* Gets a connection to the PostgreSQL database. The database is identified by the
* DataAource properties serverName, databaseName, and portNumber. The user to
* connect as is identified by the arguments user and password, which override
* the DataSource properties by the same name.
*
* @return A valid database connection.
* @throws SQLException
* Occurs when the database connection cannot be established.
*/
public Connection getConnection(String user, String password) throws SQLException {
try {
Connection con = DriverManager.getConnection(getUrl(), user, password);
if (logger != null) {
logger.println("Created a non-pooled connection for " + user + " at " + getUrl());
}
return con;
} catch (SQLException e) {
if (logger != null) {
logger.println("Failed to create a non-pooled connection for " + user + " at " + getUrl() + ": " + e);
}
throw e;
}
}
/**
* Gets a connection to the PostgreSQL database. The database is identified by the
* DataAource properties serverName, databaseName, and portNumber. The user to
* connect as is identified by the arguments user and password, which override
* the DataSource properties by the same name.
*
* @return A valid database connection.
* @throws SQLException
* Occurs when the database connection cannot be established.
*/
public Connection getConnection(String user, String password) throws SQLException
{
try
{
Connection con = DriverManager.getConnection(getUrl(), user, password);
if (logger != null)
{
logger.println("Created a non-pooled connection for " + user + " at " + getUrl());
}
return con;
}
catch (SQLException e)
{
if (logger != null)
{
logger.println("Failed to create a non-pooled connection for " + user + " at " + getUrl() + ": " + e);
}
throw e;
}
}
/**
* This DataSource does not support a configurable login timeout.
* @return 0
*/
public int getLoginTimeout() throws SQLException {
return 0;
}
/**
* This DataSource does not support a configurable login timeout.
* @return 0
*/
public int getLoginTimeout() throws SQLException
{
return 0;
}
/**
* This DataSource does not support a configurable login timeout. Any value
* provided here will be ignored.
*/
public void setLoginTimeout(int i) throws SQLException {
}
/**
* This DataSource does not support a configurable login timeout. Any value
* provided here will be ignored.
*/
public void setLoginTimeout(int i) throws SQLException
{}
/**
* Gets the log writer used to log connections opened.
*/
public PrintWriter getLogWriter() throws SQLException {
return logger;
}
/**
* Gets the log writer used to log connections opened.
*/
public PrintWriter getLogWriter() throws SQLException
{
return logger;
}
/**
* The DataSource will note every connection opened to the provided log writer.
*/
public void setLogWriter(PrintWriter printWriter) throws SQLException {
logger = printWriter;
}
/**
* The DataSource will note every connection opened to the provided log writer.
*/
public void setLogWriter(PrintWriter printWriter) throws SQLException
{
logger = printWriter;
}
/**
* Gets the name of the host the PostgreSQL database is running on.
*/
public String getServerName() {
return serverName;
}
/**
* Gets the name of the host the PostgreSQL database is running on.
*/
public String getServerName()
{
return serverName;
}
/**
* Sets the name of the host the PostgreSQL database is running on. If this
* is changed, it will only affect future calls to getConnection. The default
* value is <tt>localhost</tt>.
*/
public void setServerName(String serverName) {
if(serverName == null || serverName.equals("")) {
this.serverName = "localhost";
} else {
this.serverName = serverName;
}
}
/**
* Sets the name of the host the PostgreSQL database is running on. If this
* is changed, it will only affect future calls to getConnection. The default
* value is <tt>localhost</tt>.
*/
public void setServerName(String serverName)
{
if (serverName == null || serverName.equals(""))
{
this.serverName = "localhost";
}
else
{
this.serverName = serverName;
}
}
/**
* Gets the name of the PostgreSQL database, running on the server identified
* by the serverName property.
*/
public String getDatabaseName() {
return databaseName;
}
/**
* Gets the name of the PostgreSQL database, running on the server identified
* by the serverName property.
*/
public String getDatabaseName()
{
return databaseName;
}
/**
* Sets the name of the PostgreSQL database, running on the server identified
* by the serverName property. If this is changed, it will only affect
* future calls to getConnection.
*/
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
}
/**
* Sets the name of the PostgreSQL database, running on the server identified
* by the serverName property. If this is changed, it will only affect
* future calls to getConnection.
*/
public void setDatabaseName(String databaseName)
{
this.databaseName = databaseName;
}
/**
* Gets a description of this DataSource-ish thing. Must be customized by
* subclasses.
*/
public abstract String getDescription();
/**
* Gets a description of this DataSource-ish thing. Must be customized by
* subclasses.
*/
public abstract String getDescription();
/**
* Gets the user to connect as by default. If this is not specified, you must
* use the getConnection method which takes a user and password as parameters.
*/
public String getUser() {
return user;
}
/**
* Gets the user to connect as by default. If this is not specified, you must
* use the getConnection method which takes a user and password as parameters.
*/
public String getUser()
{
return user;
}
/**
* Sets the user to connect as by default. If this is not specified, you must
* use the getConnection method which takes a user and password as parameters.
* If this is changed, it will only affect future calls to getConnection.
*/
public void setUser(String user) {
this.user = user;
}
/**
* Sets the user to connect as by default. If this is not specified, you must
* use the getConnection method which takes a user and password as parameters.
* If this is changed, it will only affect future calls to getConnection.
*/
public void setUser(String user)
{
this.user = user;
}
/**
* Gets the password to connect with by default. If this is not specified but a
* password is needed to log in, you must use the getConnection method which takes
* a user and password as parameters.
*/
public String getPassword() {
return password;
}
/**
* Gets the password to connect with by default. If this is not specified but a
* password is needed to log in, you must use the getConnection method which takes
* a user and password as parameters.
*/
public String getPassword()
{
return password;
}
/**
* Sets the password to connect with by default. If this is not specified but a
* password is needed to log in, you must use the getConnection method which takes
* a user and password as parameters. If this is changed, it will only affect
* future calls to getConnection.
*/
public void setPassword(String password) {
this.password = password;
}
/**
* Sets the password to connect with by default. If this is not specified but a
* password is needed to log in, you must use the getConnection method which takes
* a user and password as parameters. If this is changed, it will only affect
* future calls to getConnection.
*/
public void setPassword(String password)
{
this.password = password;
}
/**
* Gets the port which the PostgreSQL server is listening on for TCP/IP
* connections.
*
* @return The port, or 0 if the default port will be used.
*/
public int getPortNumber() {
return portNumber;
}
/**
* Gets the port which the PostgreSQL server is listening on for TCP/IP
* connections.
*
* @return The port, or 0 if the default port will be used.
*/
public int getPortNumber()
{
return portNumber;
}
/**
* Gets the port which the PostgreSQL server is listening on for TCP/IP
* connections. Be sure the -i flag is passed to postmaster when PostgreSQL
* is started. If this is not set, or set to 0, the default port will be used.
*/
public void setPortNumber(int portNumber) {
this.portNumber = portNumber;
}
/**
* Gets the port which the PostgreSQL server is listening on for TCP/IP
* connections. Be sure the -i flag is passed to postmaster when PostgreSQL
* is started. If this is not set, or set to 0, the default port will be used.
*/
public void setPortNumber(int portNumber)
{
this.portNumber = portNumber;
}
/**
* Generates a DriverManager URL from the other properties supplied.
*/
private String getUrl() {
return "jdbc:postgresql://"+serverName+(portNumber == 0 ? "" : ":"+portNumber)+"/"+databaseName;
}
/**
* Generates a DriverManager URL from the other properties supplied.
*/
private String getUrl()
{
return "jdbc:postgresql://" + serverName + (portNumber == 0 ? "" : ":" + portNumber) + "/" + databaseName;
}
public Reference getReference() throws NamingException {
Reference ref = new Reference(getClass().getName(), PGObjectFactory.class.getName(), null);
ref.add(new StringRefAddr("serverName", serverName));
if (portNumber != 0) {
ref.add(new StringRefAddr("portNumber", Integer.toString(portNumber)));
}
ref.add(new StringRefAddr("databaseName", databaseName));
if (user != null) {
ref.add(new StringRefAddr("user", user));
}
if (password != null) {
ref.add(new StringRefAddr("password", password));
}
return ref;
}
public Reference getReference() throws NamingException
{
Reference ref = new Reference(getClass().getName(), PGObjectFactory.class.getName(), null);
ref.add(new StringRefAddr("serverName", serverName));
if (portNumber != 0)
{
ref.add(new StringRefAddr("portNumber", Integer.toString(portNumber)));
}
ref.add(new StringRefAddr("databaseName", databaseName));
if (user != null)
{
ref.add(new StringRefAddr("user", user));
}
if (password != null)
{
ref.add(new StringRefAddr("password", password));
}
return ref;
}
}

View File

@ -21,56 +21,62 @@ import java.io.Serializable;
* <p>This implementation supports JDK 1.3 and higher.</p>
*
* @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $
* @version $Revision: 1.2 $
*/
public class ConnectionPool extends BaseDataSource implements Serializable, ConnectionPoolDataSource {
private boolean defaultAutoCommit = false;
public class ConnectionPool extends BaseDataSource implements Serializable, ConnectionPoolDataSource
{
private boolean defaultAutoCommit = false;
/**
* Gets a description of this DataSource.
*/
public String getDescription() {
return "ConnectionPoolDataSource from "+org.postgresql.Driver.getVersion();
}
/**
* Gets a description of this DataSource.
*/
public String getDescription()
{
return "ConnectionPoolDataSource from " + org.postgresql.Driver.getVersion();
}
/**
* Gets a connection which may be pooled by the app server or middleware
* implementation of DataSource.
*
* @throws java.sql.SQLException
* Occurs when the physical database connection cannot be established.
*/
public PooledConnection getPooledConnection() throws SQLException {
return new PooledConnectionImpl(getConnection(), defaultAutoCommit);
}
/**
* Gets a connection which may be pooled by the app server or middleware
* implementation of DataSource.
*
* @throws java.sql.SQLException
* Occurs when the physical database connection cannot be established.
*/
public PooledConnection getPooledConnection() throws SQLException
{
return new PooledConnectionImpl(getConnection(), defaultAutoCommit);
}
/**
* Gets a connection which may be pooled by the app server or middleware
* implementation of DataSource.
*
* @throws java.sql.SQLException
* Occurs when the physical database connection cannot be established.
*/
public PooledConnection getPooledConnection(String user, String password) throws SQLException {
return new PooledConnectionImpl(getConnection(user, password), defaultAutoCommit);
}
/**
* Gets a connection which may be pooled by the app server or middleware
* implementation of DataSource.
*
* @throws java.sql.SQLException
* Occurs when the physical database connection cannot be established.
*/
public PooledConnection getPooledConnection(String user, String password) throws SQLException
{
return new PooledConnectionImpl(getConnection(user, password), defaultAutoCommit);
}
/**
* Gets whether connections supplied by this pool will have autoCommit
* turned on by default. The default value is <tt>false</tt>, so that
* autoCommit will be turned off by default.
*/
public boolean isDefaultAutoCommit() {
return defaultAutoCommit;
}
/**
* Gets whether connections supplied by this pool will have autoCommit
* turned on by default. The default value is <tt>false</tt>, so that
* autoCommit will be turned off by default.
*/
public boolean isDefaultAutoCommit()
{
return defaultAutoCommit;
}
/**
* Sets whether connections supplied by this pool will have autoCommit
* turned on by default. The default value is <tt>false</tt>, so that
* autoCommit will be turned off by default.
*/
public void setDefaultAutoCommit(boolean defaultAutoCommit) {
this.defaultAutoCommit = defaultAutoCommit;
}
/**
* Sets whether connections supplied by this pool will have autoCommit
* turned on by default. The default value is <tt>false</tt>, so that
* autoCommit will be turned off by default.
*/
public void setDefaultAutoCommit(boolean defaultAutoCommit)
{
this.defaultAutoCommit = defaultAutoCommit;
}
}

View File

@ -13,77 +13,96 @@ import java.util.Hashtable;
* consistent.
*
* @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $
* @version $Revision: 1.2 $
*/
public class PGObjectFactory implements ObjectFactory {
/**
* Dereferences a PostgreSQL DataSource. Other types of references are
* ignored.
*/
public Object getObjectInstance(Object obj, Name name, Context nameCtx,
Hashtable environment) throws Exception {
Reference ref = (Reference)obj;
if(ref.getClassName().equals(SimpleDataSource.class.getName())) {
return loadSimpleDataSource(ref);
} else if (ref.getClassName().equals(ConnectionPool.class.getName())) {
return loadConnectionPool(ref);
} else if (ref.getClassName().equals(PoolingDataSource.class.getName())) {
return loadPoolingDataSource(ref);
} else {
return null;
}
}
public class PGObjectFactory implements ObjectFactory
{
/**
* Dereferences a PostgreSQL DataSource. Other types of references are
* ignored.
*/
public Object getObjectInstance(Object obj, Name name, Context nameCtx,
Hashtable environment) throws Exception
{
Reference ref = (Reference)obj;
if (ref.getClassName().equals(SimpleDataSource.class.getName()))
{
return loadSimpleDataSource(ref);
}
else if (ref.getClassName().equals(ConnectionPool.class.getName()))
{
return loadConnectionPool(ref);
}
else if (ref.getClassName().equals(PoolingDataSource.class.getName()))
{
return loadPoolingDataSource(ref);
}
else
{
return null;
}
}
private Object loadPoolingDataSource(Reference ref) {
// If DataSource exists, return it
String name = getProperty(ref, "dataSourceName");
PoolingDataSource pds = PoolingDataSource.getDataSource(name);
if(pds != null) {
return pds;
}
// Otherwise, create a new one
pds = new PoolingDataSource();
pds.setDataSourceName(name);
loadBaseDataSource(pds, ref);
String min = getProperty(ref, "initialConnections");
if (min != null) {
pds.setInitialConnections(Integer.parseInt(min));
}
String max = getProperty(ref, "maxConnections");
if (max != null) {
pds.setMaxConnections(Integer.parseInt(max));
}
return pds;
}
private Object loadPoolingDataSource(Reference ref)
{
// If DataSource exists, return it
String name = getProperty(ref, "dataSourceName");
PoolingDataSource pds = PoolingDataSource.getDataSource(name);
if (pds != null)
{
return pds;
}
// Otherwise, create a new one
pds = new PoolingDataSource();
pds.setDataSourceName(name);
loadBaseDataSource(pds, ref);
String min = getProperty(ref, "initialConnections");
if (min != null)
{
pds.setInitialConnections(Integer.parseInt(min));
}
String max = getProperty(ref, "maxConnections");
if (max != null)
{
pds.setMaxConnections(Integer.parseInt(max));
}
return pds;
}
private Object loadSimpleDataSource(Reference ref) {
SimpleDataSource ds = new SimpleDataSource();
return loadBaseDataSource(ds, ref);
}
private Object loadSimpleDataSource(Reference ref)
{
SimpleDataSource ds = new SimpleDataSource();
return loadBaseDataSource(ds, ref);
}
private Object loadConnectionPool(Reference ref) {
ConnectionPool cp = new ConnectionPool();
return loadBaseDataSource(cp, ref);
}
private Object loadConnectionPool(Reference ref)
{
ConnectionPool cp = new ConnectionPool();
return loadBaseDataSource(cp, ref);
}
private Object loadBaseDataSource(BaseDataSource ds, Reference ref) {
ds.setDatabaseName(getProperty(ref, "databaseName"));
ds.setPassword(getProperty(ref, "password"));
String port = getProperty(ref, "portNumber");
if(port != null) {
ds.setPortNumber(Integer.parseInt(port));
}
ds.setServerName(getProperty(ref, "serverName"));
ds.setUser(getProperty(ref, "user"));
return ds;
}
private Object loadBaseDataSource(BaseDataSource ds, Reference ref)
{
ds.setDatabaseName(getProperty(ref, "databaseName"));
ds.setPassword(getProperty(ref, "password"));
String port = getProperty(ref, "portNumber");
if (port != null)
{
ds.setPortNumber(Integer.parseInt(port));
}
ds.setServerName(getProperty(ref, "serverName"));
ds.setUser(getProperty(ref, "user"));
return ds;
}
private String getProperty(Reference ref, String s) {
RefAddr addr = ref.get(s);
if(addr == null) {
return null;
}
return (String)addr.getContent();
}
private String getProperty(Reference ref, String s)
{
RefAddr addr = ref.get(s);
if (addr == null)
{
return null;
}
return (String)addr.getContent();
}
}

View File

@ -13,187 +13,244 @@ import java.lang.reflect.*;
* @see ConnectionPool
*
* @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $
* @version $Revision: 1.2 $
*/
public class PooledConnectionImpl implements PooledConnection {
private List listeners = new LinkedList();
private Connection con;
private ConnectionHandler last;
private boolean autoCommit;
public class PooledConnectionImpl implements PooledConnection
{
private List listeners = new LinkedList();
private Connection con;
private ConnectionHandler last;
private boolean autoCommit;
/**
* Creates a new PooledConnection representing the specified physical
* connection.
*/
PooledConnectionImpl(Connection con, boolean autoCommit) {
this.con = con;
this.autoCommit = autoCommit;
}
/**
* Creates a new PooledConnection representing the specified physical
* connection.
*/
PooledConnectionImpl(Connection con, boolean autoCommit)
{
this.con = con;
this.autoCommit = autoCommit;
}
/**
* Adds a listener for close or fatal error events on the connection
* handed out to a client.
*/
public void addConnectionEventListener(ConnectionEventListener connectionEventListener) {
listeners.add(connectionEventListener);
}
/**
* Adds a listener for close or fatal error events on the connection
* handed out to a client.
*/
public void addConnectionEventListener(ConnectionEventListener connectionEventListener)
{
listeners.add(connectionEventListener);
}
/**
* Removes a listener for close or fatal error events on the connection
* handed out to a client.
*/
public void removeConnectionEventListener(ConnectionEventListener connectionEventListener) {
listeners.remove(connectionEventListener);
}
/**
* Removes a listener for close or fatal error events on the connection
* handed out to a client.
*/
public void removeConnectionEventListener(ConnectionEventListener connectionEventListener)
{
listeners.remove(connectionEventListener);
}
/**
* Closes the physical database connection represented by this
* PooledConnection. If any client has a connection based on
* this PooledConnection, it is forcibly closed as well.
*/
public void close() throws SQLException {
if(last != null) {
last.close();
if(!con.getAutoCommit()) {
try {con.rollback();} catch (SQLException e) {}
}
}
try {
con.close();
} finally {
con = null;
}
}
/**
* Closes the physical database connection represented by this
* PooledConnection. If any client has a connection based on
* this PooledConnection, it is forcibly closed as well.
*/
public void close() throws SQLException
{
if (last != null)
{
last.close();
if (!con.getAutoCommit())
{
try
{
con.rollback();
}
catch (SQLException e)
{}
}
}
try
{
con.close();
}
finally
{
con = null;
}
}
/**
* Gets a handle for a client to use. This is a wrapper around the
* physical connection, so the client can call close and it will just
* return the connection to the pool without really closing the
* pgysical connection.
*
* <p>According to the JDBC 2.0 Optional Package spec (6.2.3), only one
* client may have an active handle to the connection at a time, so if
* there is a previous handle active when this is called, the previous
* one is forcibly closed and its work rolled back.</p>
*/
public Connection getConnection() throws SQLException {
if(con == null) {
throw new SQLException("This PooledConnection has already been closed!");
}
// Only one connection can be open at a time from this PooledConnection. See JDBC 2.0 Optional Package spec section 6.2.3
if(last != null) {
last.close();
if(!con.getAutoCommit()) {
try {con.rollback();} catch(SQLException e) {}
}
con.clearWarnings();
}
con.setAutoCommit(autoCommit);
ConnectionHandler handler = new ConnectionHandler(con);
last = handler;
return (Connection)Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Connection.class}, handler);
}
/**
* Gets a handle for a client to use. This is a wrapper around the
* physical connection, so the client can call close and it will just
* return the connection to the pool without really closing the
* pgysical connection.
*
* <p>According to the JDBC 2.0 Optional Package spec (6.2.3), only one
* client may have an active handle to the connection at a time, so if
* there is a previous handle active when this is called, the previous
* one is forcibly closed and its work rolled back.</p>
*/
public Connection getConnection() throws SQLException
{
if (con == null)
{
throw new SQLException("This PooledConnection has already been closed!");
}
// Only one connection can be open at a time from this PooledConnection. See JDBC 2.0 Optional Package spec section 6.2.3
if (last != null)
{
last.close();
if (!con.getAutoCommit())
{
try
{
con.rollback();
}
catch (SQLException e)
{}
}
con.clearWarnings();
}
con.setAutoCommit(autoCommit);
ConnectionHandler handler = new ConnectionHandler(con);
last = handler;
return (Connection)Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Connection.class}, handler);
}
/**
* Used to fire a connection event to all listeners.
*/
void fireConnectionClosed() {
ConnectionEvent evt = null;
// Copy the listener list so the listener can remove itself during this method call
ConnectionEventListener[] local = (ConnectionEventListener[]) listeners.toArray(new ConnectionEventListener[listeners.size()]);
for (int i = 0; i < local.length; i++) {
ConnectionEventListener listener = local[i];
if (evt == null) {
evt = new ConnectionEvent(this);
}
listener.connectionClosed(evt);
}
}
/**
* Used to fire a connection event to all listeners.
*/
void fireConnectionClosed()
{
ConnectionEvent evt = null;
// Copy the listener list so the listener can remove itself during this method call
ConnectionEventListener[] local = (ConnectionEventListener[]) listeners.toArray(new ConnectionEventListener[listeners.size()]);
for (int i = 0; i < local.length; i++)
{
ConnectionEventListener listener = local[i];
if (evt == null)
{
evt = new ConnectionEvent(this);
}
listener.connectionClosed(evt);
}
}
/**
* Used to fire a connection event to all listeners.
*/
void fireConnectionFatalError(SQLException e) {
ConnectionEvent evt = null;
// Copy the listener list so the listener can remove itself during this method call
ConnectionEventListener[] local = (ConnectionEventListener[])listeners.toArray(new ConnectionEventListener[listeners.size()]);
for (int i=0; i<local.length; i++) {
ConnectionEventListener listener = local[i];
if (evt == null) {
evt = new ConnectionEvent(this, e);
}
listener.connectionErrorOccurred(evt);
}
}
/**
* Used to fire a connection event to all listeners.
*/
void fireConnectionFatalError(SQLException e)
{
ConnectionEvent evt = null;
// Copy the listener list so the listener can remove itself during this method call
ConnectionEventListener[] local = (ConnectionEventListener[])listeners.toArray(new ConnectionEventListener[listeners.size()]);
for (int i = 0; i < local.length; i++)
{
ConnectionEventListener listener = local[i];
if (evt == null)
{
evt = new ConnectionEvent(this, e);
}
listener.connectionErrorOccurred(evt);
}
}
/**
* Instead of declaring a class implementing Connection, which would have
* to be updated for every JDK rev, use a dynamic proxy to handle all
* calls through the Connection interface. This is the part that
* requires JDK 1.3 or higher, though JDK 1.2 could be supported with a
* 3rd-party proxy package.
*/
private class ConnectionHandler implements InvocationHandler {
private Connection con;
private boolean automatic = false;
/**
* Instead of declaring a class implementing Connection, which would have
* to be updated for every JDK rev, use a dynamic proxy to handle all
* calls through the Connection interface. This is the part that
* requires JDK 1.3 or higher, though JDK 1.2 could be supported with a
* 3rd-party proxy package.
*/
private class ConnectionHandler implements InvocationHandler
{
private Connection con;
private boolean automatic = false;
public ConnectionHandler(Connection con) {
this.con = con;
}
public ConnectionHandler(Connection con)
{
this.con = con;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// From Object
if(method.getDeclaringClass().getName().equals("java.lang.Object")) {
if(method.getName().equals("toString")) {
return "Pooled connection wrapping physical connection "+con;
}
if(method.getName().equals("hashCode")) {
return new Integer(con.hashCode());
}
if(method.getName().equals("equals")) {
if(args[0] == null) {
return Boolean.FALSE;
}
try {
return Proxy.isProxyClass(args[0].getClass()) && ((ConnectionHandler) Proxy.getInvocationHandler(args[0])).con == con ? Boolean.TRUE : Boolean.FALSE;
} catch(ClassCastException e) {
return Boolean.FALSE;
}
}
return method.invoke(con, args);
}
// All the rest is from the Connection interface
if(method.getName().equals("isClosed")) {
return con == null ? Boolean.TRUE : Boolean.FALSE;
}
if(con == null) {
throw new SQLException(automatic ? "Connection has been closed automatically because a new connection was opened for the same PooledConnection or the PooledConnection has been closed" : "Connection has been closed");
}
if(method.getName().equals("close")) {
SQLException ex = null;
if(!con.getAutoCommit()) {
try {con.rollback();} catch(SQLException e) {ex = e;}
}
con.clearWarnings();
con = null;
last = null;
fireConnectionClosed();
if(ex != null) {
throw ex;
}
return null;
} else {
return method.invoke(con, args);
}
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
// From Object
if (method.getDeclaringClass().getName().equals("java.lang.Object"))
{
if (method.getName().equals("toString"))
{
return "Pooled connection wrapping physical connection " + con;
}
if (method.getName().equals("hashCode"))
{
return new Integer(con.hashCode());
}
if (method.getName().equals("equals"))
{
if (args[0] == null)
{
return Boolean.FALSE;
}
try
{
return Proxy.isProxyClass(args[0].getClass()) && ((ConnectionHandler) Proxy.getInvocationHandler(args[0])).con == con ? Boolean.TRUE : Boolean.FALSE;
}
catch (ClassCastException e)
{
return Boolean.FALSE;
}
}
return method.invoke(con, args);
}
// All the rest is from the Connection interface
if (method.getName().equals("isClosed"))
{
return con == null ? Boolean.TRUE : Boolean.FALSE;
}
if (con == null)
{
throw new SQLException(automatic ? "Connection has been closed automatically because a new connection was opened for the same PooledConnection or the PooledConnection has been closed" : "Connection has been closed");
}
if (method.getName().equals("close"))
{
SQLException ex = null;
if (!con.getAutoCommit())
{
try
{
con.rollback();
}
catch (SQLException e)
{
ex = e;
}
}
con.clearWarnings();
con = null;
last = null;
fireConnectionClosed();
if (ex != null)
{
throw ex;
}
return null;
}
else
{
return method.invoke(con, args);
}
}
public void close() {
if(con != null) {
automatic = true;
}
con = null;
// No close event fired here: see JDBC 2.0 Optional Package spec section 6.3
}
}
public void close()
{
if (con != null)
{
automatic = true;
}
con = null;
// No close event fired here: see JDBC 2.0 Optional Package spec section 6.3
}
}
}

View File

@ -26,388 +26,454 @@ import java.sql.SQLException;
*
* <p>If you put this DataSource in JNDI, and access it from different JVMs (or
* otherwise load this class from different ClassLoaders), you'll end up with one
* pool per ClassLoader or VM. This is another area where a server-specific
* pool per ClassLoader or VM. This is another area where a server-specific
* implementation may provide advanced features, such as using a single pool
* across all VMs in a cluster.</p>
*
* <p>This implementation supports JDK 1.3 and higher.</p>
*
* @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $
* @version $Revision: 1.2 $
*/
public class PoolingDataSource extends BaseDataSource implements DataSource {
private static Map dataSources = new HashMap();
public class PoolingDataSource extends BaseDataSource implements DataSource
{
private static Map dataSources = new HashMap();
static PoolingDataSource getDataSource(String name) {
return (PoolingDataSource)dataSources.get(name);
}
static PoolingDataSource getDataSource(String name)
{
return (PoolingDataSource)dataSources.get(name);
}
// Additional Data Source properties
private String dataSourceName;
private int initialConnections = 0;
private int maxConnections = 0;
// State variables
private boolean initialized = false;
private Stack available = new Stack();
private Stack used = new Stack();
private Object lock = new Object();
private ConnectionPool source;
// Additional Data Source properties
private String dataSourceName;
private int initialConnections = 0;
private int maxConnections = 0;
// State variables
private boolean initialized = false;
private Stack available = new Stack();
private Stack used = new Stack();
private Object lock = new Object();
private ConnectionPool source;
/**
* Gets a description of this DataSource.
*/
public String getDescription() {
return "Pooling DataSource '"+dataSourceName+" from "+org.postgresql.Driver.getVersion();
}
/**
* Gets a description of this DataSource.
*/
public String getDescription()
{
return "Pooling DataSource '" + dataSourceName + " from " + org.postgresql.Driver.getVersion();
}
/**
* Ensures the DataSource properties are not changed after the DataSource has
* been used.
*
* @throws java.lang.IllegalStateException
* The Server Name cannot be changed after the DataSource has been
* used.
*/
public void setServerName(String serverName) {
if (initialized) {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
super.setServerName(serverName);
}
/**
* Ensures the DataSource properties are not changed after the DataSource has
* been used.
*
* @throws java.lang.IllegalStateException
* The Server Name cannot be changed after the DataSource has been
* used.
*/
public void setServerName(String serverName)
{
if (initialized)
{
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
super.setServerName(serverName);
}
/**
* Ensures the DataSource properties are not changed after the DataSource has
* been used.
*
* @throws java.lang.IllegalStateException
* The Database Name cannot be changed after the DataSource has been
* used.
*/
public void setDatabaseName(String databaseName) {
if (initialized) {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
super.setDatabaseName(databaseName);
}
/**
* Ensures the DataSource properties are not changed after the DataSource has
* been used.
*
* @throws java.lang.IllegalStateException
* The Database Name cannot be changed after the DataSource has been
* used.
*/
public void setDatabaseName(String databaseName)
{
if (initialized)
{
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
super.setDatabaseName(databaseName);
}
/**
* Ensures the DataSource properties are not changed after the DataSource has
* been used.
*
* @throws java.lang.IllegalStateException
* The User cannot be changed after the DataSource has been
* used.
*/
public void setUser(String user) {
if (initialized) {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
super.setUser(user);
}
/**
* Ensures the DataSource properties are not changed after the DataSource has
* been used.
*
* @throws java.lang.IllegalStateException
* The User cannot be changed after the DataSource has been
* used.
*/
public void setUser(String user)
{
if (initialized)
{
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
super.setUser(user);
}
/**
* Ensures the DataSource properties are not changed after the DataSource has
* been used.
*
* @throws java.lang.IllegalStateException
* The Password cannot be changed after the DataSource has been
* used.
*/
public void setPassword(String password) {
if (initialized) {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
super.setPassword(password);
}
/**
* Ensures the DataSource properties are not changed after the DataSource has
* been used.
*
* @throws java.lang.IllegalStateException
* The Password cannot be changed after the DataSource has been
* used.
*/
public void setPassword(String password)
{
if (initialized)
{
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
super.setPassword(password);
}
/**
* Ensures the DataSource properties are not changed after the DataSource has
* been used.
*
* @throws java.lang.IllegalStateException
* The Port Number cannot be changed after the DataSource has been
* used.
*/
public void setPortNumber(int portNumber) {
if (initialized) {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
super.setPortNumber(portNumber);
}
/**
* Ensures the DataSource properties are not changed after the DataSource has
* been used.
*
* @throws java.lang.IllegalStateException
* The Port Number cannot be changed after the DataSource has been
* used.
*/
public void setPortNumber(int portNumber)
{
if (initialized)
{
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
super.setPortNumber(portNumber);
}
/**
* Gets the number of connections that will be created when this DataSource
* is initialized. If you do not call initialize explicitly, it will be
* initialized the first time a connection is drawn from it.
*/
public int getInitialConnections() {
return initialConnections;
}
/**
* Gets the number of connections that will be created when this DataSource
* is initialized. If you do not call initialize explicitly, it will be
* initialized the first time a connection is drawn from it.
*/
public int getInitialConnections()
{
return initialConnections;
}
/**
* Sets the number of connections that will be created when this DataSource
* is initialized. If you do not call initialize explicitly, it will be
* initialized the first time a connection is drawn from it.
*
* @throws java.lang.IllegalStateException
* The Initial Connections cannot be changed after the DataSource has been
* used.
*/
public void setInitialConnections(int initialConnections) {
if (initialized) {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
this.initialConnections = initialConnections;
}
/**
* Sets the number of connections that will be created when this DataSource
* is initialized. If you do not call initialize explicitly, it will be
* initialized the first time a connection is drawn from it.
*
* @throws java.lang.IllegalStateException
* The Initial Connections cannot be changed after the DataSource has been
* used.
*/
public void setInitialConnections(int initialConnections)
{
if (initialized)
{
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
this.initialConnections = initialConnections;
}
/**
* Gets the maximum number of connections that the pool will allow. If a request
* comes in and this many connections are in use, the request will block until a
* connection is available. Note that connections for a user other than the
* default user will not be pooled and don't count against this limit.
*
* @return The maximum number of pooled connection allowed, or 0 for no maximum.
*/
public int getMaxConnections() {
return maxConnections;
}
/**
* Gets the maximum number of connections that the pool will allow. If a request
* comes in and this many connections are in use, the request will block until a
* connection is available. Note that connections for a user other than the
* default user will not be pooled and don't count against this limit.
*
* @return The maximum number of pooled connection allowed, or 0 for no maximum.
*/
public int getMaxConnections()
{
return maxConnections;
}
/**
* Sets the maximum number of connections that the pool will allow. If a request
* comes in and this many connections are in use, the request will block until a
* connection is available. Note that connections for a user other than the
* default user will not be pooled and don't count against this limit.
*
* @param maxConnections The maximum number of pooled connection to allow, or
* 0 for no maximum.
*
* @throws java.lang.IllegalStateException
* The Maximum Connections cannot be changed after the DataSource has been
* used.
*/
public void setMaxConnections(int maxConnections) {
if (initialized) {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
this.maxConnections = maxConnections;
}
/**
* Sets the maximum number of connections that the pool will allow. If a request
* comes in and this many connections are in use, the request will block until a
* connection is available. Note that connections for a user other than the
* default user will not be pooled and don't count against this limit.
*
* @param maxConnections The maximum number of pooled connection to allow, or
* 0 for no maximum.
*
* @throws java.lang.IllegalStateException
* The Maximum Connections cannot be changed after the DataSource has been
* used.
*/
public void setMaxConnections(int maxConnections)
{
if (initialized)
{
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
this.maxConnections = maxConnections;
}
/**
* Gets the name of this DataSource. This uniquely identifies the DataSource.
* You cannot use more than one DataSource in the same VM with the same name.
*/
public String getDataSourceName() {
return dataSourceName;
}
/**
* Gets the name of this DataSource. This uniquely identifies the DataSource.
* You cannot use more than one DataSource in the same VM with the same name.
*/
public String getDataSourceName()
{
return dataSourceName;
}
/**
* Sets the name of this DataSource. This is required, and uniquely identifies
* the DataSource. You cannot create or use more than one DataSource in the
* same VM with the same name.
*
* @throws java.lang.IllegalStateException
* The Data Source Name cannot be changed after the DataSource has been
* used.
* @throws java.lang.IllegalArgumentException
* Another PoolingDataSource with the same dataSourceName already
* exists.
*/
public void setDataSourceName(String dataSourceName) {
if(initialized) {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
if(this.dataSourceName != null && dataSourceName != null && dataSourceName.equals(this.dataSourceName)) {
return;
}
synchronized(dataSources) {
if(getDataSource(dataSourceName) != null) {
throw new IllegalArgumentException("DataSource with name '"+dataSourceName+"' already exists!");
}
if (this.dataSourceName != null) {
dataSources.remove(this.dataSourceName);
}
this.dataSourceName = dataSourceName;
dataSources.put(dataSourceName, this);
}
}
/**
* Sets the name of this DataSource. This is required, and uniquely identifies
* the DataSource. You cannot create or use more than one DataSource in the
* same VM with the same name.
*
* @throws java.lang.IllegalStateException
* The Data Source Name cannot be changed after the DataSource has been
* used.
* @throws java.lang.IllegalArgumentException
* Another PoolingDataSource with the same dataSourceName already
* exists.
*/
public void setDataSourceName(String dataSourceName)
{
if (initialized)
{
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
}
if (this.dataSourceName != null && dataSourceName != null && dataSourceName.equals(this.dataSourceName))
{
return ;
}
synchronized (dataSources)
{
if (getDataSource(dataSourceName) != null)
{
throw new IllegalArgumentException("DataSource with name '" + dataSourceName + "' already exists!");
}
if (this.dataSourceName != null)
{
dataSources.remove(this.dataSourceName);
}
this.dataSourceName = dataSourceName;
dataSources.put(dataSourceName, this);
}
}
/**
* Initializes this DataSource. If the initialConnections is greater than zero,
* that number of connections will be created. After this method is called,
* the DataSource properties cannot be changed. If you do not call this
* explicitly, it will be called the first time you get a connection from the
* Datasource.
* @throws java.sql.SQLException
* Occurs when the initialConnections is greater than zero, but the
* DataSource is not able to create enough physical connections.
*/
public void initialize() throws SQLException {
synchronized (lock) {
source = new ConnectionPool();
source.setDatabaseName(getDatabaseName());
source.setPassword(getPassword());
source.setPortNumber(getPortNumber());
source.setServerName(getServerName());
source.setUser(getUser());
while (available.size() < initialConnections) {
available.push(source.getPooledConnection());
}
initialized = true;
}
}
/**
* Initializes this DataSource. If the initialConnections is greater than zero,
* that number of connections will be created. After this method is called,
* the DataSource properties cannot be changed. If you do not call this
* explicitly, it will be called the first time you get a connection from the
* Datasource.
* @throws java.sql.SQLException
* Occurs when the initialConnections is greater than zero, but the
* DataSource is not able to create enough physical connections.
*/
public void initialize() throws SQLException
{
synchronized (lock)
{
source = new ConnectionPool();
source.setDatabaseName(getDatabaseName());
source.setPassword(getPassword());
source.setPortNumber(getPortNumber());
source.setServerName(getServerName());
source.setUser(getUser());
while (available.size() < initialConnections)
{
available.push(source.getPooledConnection());
}
initialized = true;
}
}
/**
* Gets a <b>non-pooled</b> connection, unless the user and password are the
* same as the default values for this connection pool.
*
* @return A pooled connection.
* @throws SQLException
* Occurs when no pooled connection is available, and a new physical
* connection cannot be created.
*/
public Connection getConnection(String user, String password) throws SQLException {
// If this is for the default user/password, use a pooled connection
if(user == null ||
(user.equals(getUser()) && ((password == null && getPassword() == null) || (password != null && password.equals(getPassword()))))) {
return getConnection();
}
// Otherwise, use a non-pooled connection
if (!initialized) {
initialize();
}
return super.getConnection(user, password);
}
/**
* Gets a <b>non-pooled</b> connection, unless the user and password are the
* same as the default values for this connection pool.
*
* @return A pooled connection.
* @throws SQLException
* Occurs when no pooled connection is available, and a new physical
* connection cannot be created.
*/
public Connection getConnection(String user, String password) throws SQLException
{
// If this is for the default user/password, use a pooled connection
if (user == null ||
(user.equals(getUser()) && ((password == null && getPassword() == null) || (password != null && password.equals(getPassword())))))
{
return getConnection();
}
// Otherwise, use a non-pooled connection
if (!initialized)
{
initialize();
}
return super.getConnection(user, password);
}
/**
* Gets a connection from the connection pool.
*
* @return A pooled connection.
* @throws SQLException
* Occurs when no pooled connection is available, and a new physical
* connection cannot be created.
*/
public Connection getConnection() throws SQLException {
if(!initialized) {
initialize();
}
return getPooledConnection();
}
/**
* Gets a connection from the connection pool.
*
* @return A pooled connection.
* @throws SQLException
* Occurs when no pooled connection is available, and a new physical
* connection cannot be created.
*/
public Connection getConnection() throws SQLException
{
if (!initialized)
{
initialize();
}
return getPooledConnection();
}
/**
* Closes this DataSource, and all the pooled connections, whether in use or not.
*/
public void close() {
synchronized(lock) {
while(available.size() > 0) {
PooledConnectionImpl pci = (PooledConnectionImpl)available.pop();
try {
pci.close();
} catch (SQLException e) {
}
}
available = null;
while (used.size() > 0) {
PooledConnectionImpl pci = (PooledConnectionImpl)used.pop();
pci.removeConnectionEventListener(connectionEventListener);
try {
pci.close();
} catch (SQLException e) {
}
}
used = null;
}
synchronized (dataSources) {
dataSources.remove(dataSourceName);
}
}
/**
* Closes this DataSource, and all the pooled connections, whether in use or not.
*/
public void close()
{
synchronized (lock)
{
while (available.size() > 0)
{
PooledConnectionImpl pci = (PooledConnectionImpl)available.pop();
try
{
pci.close();
}
catch (SQLException e)
{}
}
available = null;
while (used.size() > 0)
{
PooledConnectionImpl pci = (PooledConnectionImpl)used.pop();
pci.removeConnectionEventListener(connectionEventListener);
try
{
pci.close();
}
catch (SQLException e)
{}
}
used = null;
}
synchronized (dataSources)
{
dataSources.remove(dataSourceName);
}
}
/**
* Gets a connection from the pool. Will get an available one if
* present, or create a new one if under the max limit. Will
* block if all used and a new one would exceed the max.
*/
private Connection getPooledConnection() throws SQLException {
PooledConnection pc = null;
synchronized(lock) {
if (available == null) {
throw new SQLException("DataSource has been closed.");
}
while(true) {
if(available.size() > 0) {
pc = (PooledConnection)available.pop();
used.push(pc);
break;
}
if(maxConnections == 0 || used.size() < maxConnections) {
pc = source.getPooledConnection();
used.push(pc);
break;
} else {
try {
// Wake up every second at a minimum
lock.wait(1000L);
} catch(InterruptedException e) {
}
}
}
}
pc.addConnectionEventListener(connectionEventListener);
return pc.getConnection();
}
/**
* Gets a connection from the pool. Will get an available one if
* present, or create a new one if under the max limit. Will
* block if all used and a new one would exceed the max.
*/
private Connection getPooledConnection() throws SQLException
{
PooledConnection pc = null;
synchronized (lock)
{
if (available == null)
{
throw new SQLException("DataSource has been closed.");
}
while (true)
{
if (available.size() > 0)
{
pc = (PooledConnection)available.pop();
used.push(pc);
break;
}
if (maxConnections == 0 || used.size() < maxConnections)
{
pc = source.getPooledConnection();
used.push(pc);
break;
}
else
{
try
{
// Wake up every second at a minimum
lock.wait(1000L);
}
catch (InterruptedException e)
{}
}
}
}
pc.addConnectionEventListener(connectionEventListener);
return pc.getConnection();
}
/**
* Notified when a pooled connection is closed, or a fatal error occurs
* on a pooled connection. This is the only way connections are marked
* as unused.
*/
private ConnectionEventListener connectionEventListener = new ConnectionEventListener() {
public void connectionClosed(ConnectionEvent event) {
((PooledConnection)event.getSource()).removeConnectionEventListener(this);
synchronized(lock) {
if(available == null) {
return; // DataSource has been closed
}
boolean removed = used.remove(event.getSource());
if(removed) {
available.push(event.getSource());
// There's now a new connection available
lock.notify();
} else {
// a connection error occured
}
}
}
/**
* Notified when a pooled connection is closed, or a fatal error occurs
* on a pooled connection. This is the only way connections are marked
* as unused.
*/
private ConnectionEventListener connectionEventListener = new ConnectionEventListener()
{
public void connectionClosed(ConnectionEvent event)
{
((PooledConnection)event.getSource()).removeConnectionEventListener(this);
synchronized (lock)
{
if (available == null)
{
return ; // DataSource has been closed
}
boolean removed = used.remove(event.getSource());
if (removed)
{
available.push(event.getSource());
// There's now a new connection available
lock.notify();
}
else
{
// a connection error occured
}
}
}
/**
* This is only called for fatal errors, where the physical connection is
* useless afterward and should be removed from the pool.
*/
public void connectionErrorOccurred(ConnectionEvent event) {
((PooledConnection) event.getSource()).removeConnectionEventListener(this);
synchronized(lock) {
if (available == null) {
return; // DataSource has been closed
}
used.remove(event.getSource());
// We're now at least 1 connection under the max
lock.notify();
}
}
};
/**
* This is only called for fatal errors, where the physical connection is
* useless afterward and should be removed from the pool.
*/
public void connectionErrorOccurred(ConnectionEvent event)
{
((PooledConnection) event.getSource()).removeConnectionEventListener(this);
synchronized (lock)
{
if (available == null)
{
return ; // DataSource has been closed
}
used.remove(event.getSource());
// We're now at least 1 connection under the max
lock.notify();
}
}
};
/**
* Adds custom properties for this DataSource to the properties defined in
* the superclass.
*/
public Reference getReference() throws NamingException {
Reference ref = super.getReference();
ref.add(new StringRefAddr("dataSourceName", dataSourceName));
if (initialConnections > 0) {
ref.add(new StringRefAddr("initialConnections", Integer.toString(initialConnections)));
}
if (maxConnections > 0) {
ref.add(new StringRefAddr("maxConnections", Integer.toString(maxConnections)));
}
return ref;
}
/**
* Adds custom properties for this DataSource to the properties defined in
* the superclass.
*/
public Reference getReference() throws NamingException
{
Reference ref = super.getReference();
ref.add(new StringRefAddr("dataSourceName", dataSourceName));
if (initialConnections > 0)
{
ref.add(new StringRefAddr("initialConnections", Integer.toString(initialConnections)));
}
if (maxConnections > 0)
{
ref.add(new StringRefAddr("maxConnections", Integer.toString(maxConnections)));
}
return ref;
}
}

View File

@ -5,18 +5,20 @@ import java.io.Serializable;
/**
* Simple DataSource which does not perform connection pooling. In order to use
* the DataSource, you must set the property databaseName. The settings for
* the DataSource, you must set the property databaseName. The settings for
* serverName, portNumber, user, and password are optional. Note: these properties
* are declared in the superclass.
*
* @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $
* @version $Revision: 1.2 $
*/
public class SimpleDataSource extends BaseDataSource implements Serializable, DataSource {
/**
* Gets a description of this DataSource.
*/
public String getDescription() {
return "Non-Pooling DataSource from "+org.postgresql.Driver.getVersion();
}
public class SimpleDataSource extends BaseDataSource implements Serializable, DataSource
{
/**
* Gets a description of this DataSource.
*/
public String getDescription()
{
return "Non-Pooling DataSource from " + org.postgresql.Driver.getVersion();
}
}