postgresql-jdbc.git / summary / log / commit / refs
commit 3f3bb0f7d7c17d6ce88d7b028f7ea7ec0dc97d5c
Author: Kris Jurka <books@ejurka.com>
Date: Wed Nov 29 04:00:27 2006 +0000
Allow datasource code to build with JDK1.6 by splitting off jdbcN
directories in the fashion of the core driver. To maintain the
generic interfaces like PGPoolingDataSource I had to use ant's
conditional compilation to determine which implementation class to
extend from. It's ugly, but contained and works.
build.xml | 73 ++-
org/postgresql/ds/PGConnectionPoolDataSource.java | 6 +-
org/postgresql/ds/PGPooledConnection.java.in | 46 ++
org/postgresql/ds/PGPoolingDataSource.java | 512 ---------------------
org/postgresql/ds/PGPoolingDataSource.java.in | 52 +++
org/postgresql/ds/PGSimpleDataSource.java | 47 --
org/postgresql/ds/PGSimpleDataSource.java.in | 26 ++
org/postgresql/ds/common/PooledConnectionImpl.java | 483 -------------------
.../ds/jdbc4/AbstractJdbc4PooledConnection.java | 32 ++
.../ds/jdbc4/AbstractJdbc4PoolingDataSource.java | 29 ++
.../ds/jdbc4/AbstractJdbc4SimpleDataSource.java | 28 ++
org/postgresql/xa/PGXAConnection.java | 4 +-
12 files changed, 281 insertions(+), 1057 deletions(-)
diff --git a/build.xml b/build.xml
index 40aefc60..27c906a9 100644
--- a/build.xml
+++ b/build.xml
@@ -8,7 +8,7 @@
This file now requires Ant 1.4.1. 2002-04-18
- $PostgreSQL: pgjdbc/build.xml,v 1.69 2006/06/08 10:34:50 jurka Exp $
+ $PostgreSQL: pgjdbc/build.xml,v 1.70 2006/07/03 15:11:58 jurka Exp $
-->
@@ -67,12 +67,7 @@
<available property="junit.task" classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask"/>
<condition property="datasource">
- <and>
- <isset property="datasourceclass" />
- <not>
- <isset property="jdbc4" />
- </not>
- </and>
+ <isset property="datasourceclass" />
</condition>
<condition property="jdbc2optionaltests">
@@ -173,10 +168,13 @@
<include name="${package}/jdbc3/Jdbc3PoolingDataSource.java" if="jdbc3any" />
<include name="${package}/jdbc3/Jdbc3SimpleDataSource.java" if="jdbc3any" />
- <include name="${package}/ds/**/*.java" if="datasource" />
+ <include name="${package}/ds/*.java" if="datasource" />
+ <include name="${package}/ds/common/*.java" if="datasource" />
+ <include name="${package}/ds/jdbc23/*.java" if="datasource" />
+ <include name="${package}/ds/jdbc4/*.java" if="jdbc4" />
<!-- XA stuff -->
- <include name="${package}/xa/*.java" if="jdbc3any" />
+ <include name="${package}/xa/*.java" if="jdbc3plus" />
</javac>
</target>
@@ -186,6 +184,9 @@
<srcfiles dir=".">
<include name="${package}/util/PSQLException.java.in"/>
<include name="${package}/Driver.java.in"/>
+ <include name="${package}/ds/PGSimpleDataSource.java.in"/>
+ <include name="${package}/ds/PGPoolingDataSource.java.in"/>
+ <include name="${package}/ds/PGPooledConnection.java.in"/>
<include name="build.properties"/>
<include name="build.local.properties" />
</srcfiles>
@@ -232,6 +233,39 @@
<equals arg1="${jdbc4}" arg2="true" />
</condition>
+ <condition property="simpledsclass" value="org.postgresql.ds.jdbc23.AbstractJdbc23SimpleDataSource">
+ <or>
+ <equals arg1="${jdbc2}" arg2="true" />
+ <equals arg1="${jdbc3}" arg2="true" />
+ <equals arg1="${jdbc3g}" arg2="true" />
+ </or>
+ </condition>
+ <condition property="simpledsclass" value="org.postgresql.ds.jdbc4.AbstractJdbc4SimpleDataSource">
+ <equals arg1="${jdbc4}" arg2="true" />
+ </condition>
+
+ <condition property="poolingdsclass" value="org.postgresql.ds.jdbc23.AbstractJdbc23PoolingDataSource">
+ <or>
+ <equals arg1="${jdbc2}" arg2="true" />
+ <equals arg1="${jdbc3}" arg2="true" />
+ <equals arg1="${jdbc3g}" arg2="true" />
+ </or>
+ </condition>
+ <condition property="poolingdsclass" value="org.postgresql.ds.jdbc4.AbstractJdbc4PoolingDataSource">
+ <equals arg1="${jdbc4}" arg2="true" />
+</condition>
+
+ <condition property="pooledconnclass" value="org.postgresql.ds.jdbc23.AbstractJdbc23PooledConnection">
+ <or>
+ <equals arg1="${jdbc2}" arg2="true" />
+ <equals arg1="${jdbc3}" arg2="true" />
+ <equals arg1="${jdbc3g}" arg2="true" />
+ </or>
+ </condition>
+ <condition property="pooledconnclass" value="org.postgresql.ds.jdbc4.AbstractJdbc4PooledConnection">
+ <equals arg1="${jdbc4}" arg2="true" />
+ </condition>
+
<!-- Determine if we have Throwable.initCause()
if so we use it in org.postgresql.util.PSQLException
instead of appending any nested exception to the message. -->
@@ -266,6 +300,9 @@
<filter token="MINORVERSION" value="${minor}" />
<filter token="VERSION" value="PostgreSQL ${fullversion} ${edition} with ${ssl_edition}" />
<filter token="JDBCCONNECTCLASS" value="${connectclass}" />
+ <filter token="POOLING_DS_CLASS" value="${poolingdsclass}" />
+ <filter token="SIMPLE_DS_CLASS" value="${simpledsclass}" />
+ <filter token="POOLED_CONN_CLASS" value="${pooledconnclass}" />
<filter token="DEF_PGPORT" value="${def_pgport}" />
<filter token="SSL" value="${ssl_config}" />
<filter token="NOINITCAUSE" value="${noInitCause}" />
@@ -287,6 +324,18 @@
overwrite="true"
tofile="${package}/util/PSQLException.java"
filtering="yes" />
+ <copy file="${package}/ds/PGPoolingDataSource.java.in"
+ overwrite="true"
+ tofile="${package}/ds/PGPoolingDataSource.java"
+ filtering="yes" />
+ <copy file="${package}/ds/PGSimpleDataSource.java.in"
+ overwrite="true"
+ tofile="${package}/ds/PGSimpleDataSource.java"
+ filtering="yes" />
+ <copy file="${package}/ds/PGPooledConnection.java.in"
+ overwrite="true"
+ tofile="${package}/ds/PGPooledConnection.java"
+ filtering="yes" />
<echo message="Configured build for the ${edition} edition driver with ${ssl_edition}" />
</target>
@@ -311,6 +360,9 @@
<delete quiet="true" dir="${jardir}" />
<delete quiet="true" file="${package}/Driver.java" />
<delete quiet="true" file="${package}/util/PSQLException.java" />
+ <delete quiet="true" file="${package}/ds/PGPoolingDataSource.java" />
+ <delete quiet="true" file="${package}/ds/PGSimpleDataSource.java" />
+ <delete quiet="true" file="${package}/ds/PGPooledConnection.java" />
</target>
<!-- This compiles and executes the JUnit tests -->
@@ -340,7 +392,7 @@
<exclude name="${package}/test/jdbc2/optional/**" unless="jdbc2optionaltests" />
<exclude name="${package}/test/jdbc3/**" unless="jdbc3tests" />
<exclude name="${package}/test/util/**" unless="jdbc2optionaltests" />
- <exclude name="${package}/test/xa/**" unless="jdbc3any" />
+ <exclude name="${package}/test/xa/**" unless="jdbc3plus" />
<classpath>
<pathelement location="${jardir}/postgresql.jar"/>
@@ -417,6 +469,7 @@
<exclude name="jdbc3/Jdbc3*.java" unless="jdbc3" />
<exclude name="jdbc3g/Jdbc3g*.java" unless="jdbc3g" />
<exclude name="jdbc4/*.java" unless="jdbc4" />
+ <exclude name="ds/jdbc4/*.java" unless="jdbc4" />
<exclude name="test/**/*.java"/>
</fileset>
</javadoc>
diff --git a/org/postgresql/ds/PGConnectionPoolDataSource.java b/org/postgresql/ds/PGConnectionPoolDataSource.java
index 90a3dbb4..5bedf846 100644
--- a/org/postgresql/ds/PGConnectionPoolDataSource.java
+++ b/org/postgresql/ds/PGConnectionPoolDataSource.java
@@ -3,7 +3,7 @@
* Copyright (c) 2004-2005, PostgreSQL Global Development Group
*
* IDENTIFICATION
-* $PostgreSQL: pgjdbc/org/postgresql/ds/PGConnectionPoolDataSource.java,v 1.2 2005/01/11 08:25:44 jurka Exp $
+* $PostgreSQL: pgjdbc/org/postgresql/ds/PGConnectionPoolDataSource.java,v 1.3 2005/01/14 01:20:17 oliver Exp $
*
*-------------------------------------------------------------------------
*/
@@ -57,7 +57,7 @@ public class PGConnectionPoolDataSource extends BaseDataSource implements Serial
*/
public PooledConnection getPooledConnection() throws SQLException
{
- return new PooledConnectionImpl(getConnection(), defaultAutoCommit);
+ return new PGPooledConnection(getConnection(), defaultAutoCommit);
}
/**
@@ -69,7 +69,7 @@ public class PGConnectionPoolDataSource extends BaseDataSource implements Serial
*/
public PooledConnection getPooledConnection(String user, String password) throws SQLException
{
- return new PooledConnectionImpl(getConnection(user, password), defaultAutoCommit);
+ return new PGPooledConnection(getConnection(user, password), defaultAutoCommit);
}
/**
diff --git a/org/postgresql/ds/PGPooledConnection.java.in b/org/postgresql/ds/PGPooledConnection.java.in
new file mode 100644
index 00000000..ceecb0aa
--- /dev/null
+++ b/org/postgresql/ds/PGPooledConnection.java.in
@@ -0,0 +1,46 @@
+/*-------------------------------------------------------------------------
+*
+* Copyright (c) 2004-2005, PostgreSQL Global Development Group
+*
+* IDENTIFICATION
+* $PostgreSQL$
+*
+*-------------------------------------------------------------------------
+*/
+package org.postgresql.ds;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import javax.sql.PooledConnection;
+import javax.sql.ConnectionEvent;
+
+/**
+ * PostgreSQL implementation of the PooledConnection interface. This shouldn't
+ * be used directly, as the pooling client should just interact with the
+ * ConnectionPool instead.
+ * @see org.postgresql.ds.PGConnectionPoolDataSource
+ *
+ * @author Aaron Mulder (ammulder@chariotsolutions.com)
+ * @author Csaba Nagy (ncsaba@yahoo.com)
+ */
+public class PGPooledConnection
+ extends @POOLED_CONN_CLASS@
+ implements PooledConnection
+{
+
+ public PGPooledConnection(Connection con, boolean autoCommit, boolean isXA)
+ {
+ super(con, autoCommit, isXA);
+ }
+
+ public PGPooledConnection(Connection con, boolean autoCommit)
+ {
+ this(con, autoCommit, false);
+ }
+
+ protected ConnectionEvent createConnectionEvent(SQLException sqle)
+ {
+ return new ConnectionEvent(this, sqle);
+ }
+
+}
diff --git a/org/postgresql/ds/PGPoolingDataSource.java b/org/postgresql/ds/PGPoolingDataSource.java
deleted file mode 100644
index ade7d44f..00000000
--- a/org/postgresql/ds/PGPoolingDataSource.java
+++ /dev/null
@@ -1,512 +0,0 @@
-/*-------------------------------------------------------------------------
-*
-* Copyright (c) 2004-2005, PostgreSQL Global Development Group
-*
-* IDENTIFICATION
-* $PostgreSQL: pgjdbc/org/postgresql/ds/PGPoolingDataSource.java,v 1.6 2005/01/11 08:25:44 jurka Exp $
-*
-*-------------------------------------------------------------------------
-*/
-package org.postgresql.ds;
-
-import javax.sql.*;
-import javax.naming.*;
-import java.util.*;
-import java.sql.Connection;
-import java.sql.SQLException;
-
-import org.postgresql.util.GT;
-import org.postgresql.util.PSQLState;
-import org.postgresql.util.PSQLException;
-import org.postgresql.ds.common.*;
-
-/**
- * DataSource which uses connection pooling. <font color="red">Don't use this if
- * your server/middleware vendor provides a connection pooling implementation
- * which interfaces with the PostgreSQL ConnectionPoolDataSource implementation!</font>
- * This class is provided as a convenience, but the JDBC Driver is really not
- * supposed to handle the connection pooling algorithm. Instead, the server or
- * middleware product is supposed to handle the mechanics of connection pooling,
- * and use the PostgreSQL implementation of ConnectionPoolDataSource to provide
- * the connections to pool.
- *
- * <p>If you're sure you want to use this, then you must set the properties
- * dataSourceName, databaseName, user, and password (if required for the user).
- * The settings for serverName, portNumber, initialConnections, and
- * maxConnections are optional. Note that <i>only connections
- * for the default user will be pooled!</i> Connections for other users will
- * be normal non-pooled connections, and will not count against the maximum pool
- * size limit.</p>
- *
- * <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
- * 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)
- */
-public class PGPoolingDataSource extends BaseDataSource implements DataSource
-{
- private static Map dataSources = new HashMap();
-
- public static PGPoolingDataSource getDataSource(String name)
- {
- return (PGPoolingDataSource)dataSources.get(name);
- }
-
- // Additional Data Source properties
- protected String dataSourceName; // Must be protected for subclasses to sync updates to it
- 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 PGConnectionPoolDataSource source;
-
- /**
- * 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 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 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);
- }
-
- /**
- * 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;
- }
-
- /**
- * 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;
- }
-
- /**
- * 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);
- }
- }
-
- /**
- * 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 = createConnectionPool();
- 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;
- }
- }
-
- protected boolean isInitialized() {
- return initialized;
- }
-
- /**
- * Creates the appropriate ConnectionPool to use for this DataSource.
- */
- protected PGConnectionPoolDataSource createConnectionPool() {
- return new PGConnectionPoolDataSource();
- }
-
- /**
- * 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();
- }
-
- /**
- * 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;
- }
- removeStoredDataSource();
- }
-
- protected void removeStoredDataSource() {
- 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 PSQLException(GT.tr("DataSource has been closed."),
- PSQLState.CONNECTION_DOES_NOT_EXIST);
- }
- 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
- }
- }
- }
-
- /**
- * 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;
- }
-}
diff --git a/org/postgresql/ds/PGPoolingDataSource.java.in b/org/postgresql/ds/PGPoolingDataSource.java.in
new file mode 100644
index 00000000..0fc5dd84
--- /dev/null
+++ b/org/postgresql/ds/PGPoolingDataSource.java.in
@@ -0,0 +1,52 @@
+/*-------------------------------------------------------------------------
+*
+* Copyright (c) 2004-2005, PostgreSQL Global Development Group
+*
+* IDENTIFICATION
+* $PostgreSQL$
+*
+*-------------------------------------------------------------------------
+*/
+package org.postgresql.ds;
+
+import javax.sql.DataSource;
+
+/**
+ * DataSource which uses connection pooling. <font color="red">Don't use this if
+ * your server/middleware vendor provides a connection pooling implementation
+ * which interfaces with the PostgreSQL ConnectionPoolDataSource implementation!</font>
+ * This class is provided as a convenience, but the JDBC Driver is really not
+ * supposed to handle the connection pooling algorithm. Instead, the server or
+ * middleware product is supposed to handle the mechanics of connection pooling,
+ * and use the PostgreSQL implementation of ConnectionPoolDataSource to provide
+ * the connections to pool.
+ *
+ * <p>If you're sure you want to use this, then you must set the properties
+ * dataSourceName, databaseName, user, and password (if required for the user).
+ * The settings for serverName, portNumber, initialConnections, and
+ * maxConnections are optional. Note that <i>only connections
+ * for the default user will be pooled!</i> Connections for other users will
+ * be normal non-pooled connections, and will not count against the maximum pool
+ * size limit.</p>
+ *
+ * <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
+ * 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)
+ */
+public class PGPoolingDataSource
+ extends @POOLING_DS_CLASS@
+ implements DataSource
+{
+
+ protected void addDataSource(String dataSourceName)
+ {
+ dataSources.put(dataSourceName, this);
+ }
+
+}
diff --git a/org/postgresql/ds/PGSimpleDataSource.java b/org/postgresql/ds/PGSimpleDataSource.java
deleted file mode 100644
index 6c9cc9f9..00000000
--- a/org/postgresql/ds/PGSimpleDataSource.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*-------------------------------------------------------------------------
-*
-* Copyright (c) 2004-2005, PostgreSQL Global Development Group
-*
-* IDENTIFICATION
-* $PostgreSQL: pgjdbc/org/postgresql/ds/PGSimpleDataSource.java,v 1.3 2004/11/09 08:46:49 jurka Exp $
-*
-*-------------------------------------------------------------------------
-*/
-package org.postgresql.ds;
-
-import javax.sql.DataSource;
-import java.io.Serializable;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
-import java.io.IOException;
-
-import org.postgresql.ds.common.*;
-
-/**
- * Simple DataSource which does not perform connection pooling. In order to use
- * 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)
- */
-public class PGSimpleDataSource extends BaseDataSource implements Serializable, DataSource
-{
- /**
- * Gets a description of this DataSource.
- */
- public String getDescription()
- {
- return "Non-Pooling DataSource from " + org.postgresql.Driver.getVersion();
- }
-
- private void writeObject(ObjectOutputStream out) throws IOException
- {
- writeBaseObject(out);
- }
-
- private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
- {
- readBaseObject(in);
- }
-}
diff --git a/org/postgresql/ds/PGSimpleDataSource.java.in b/org/postgresql/ds/PGSimpleDataSource.java.in
new file mode 100644
index 00000000..8c74eab3
--- /dev/null
+++ b/org/postgresql/ds/PGSimpleDataSource.java.in
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+*
+* Copyright (c) 2004-2005, PostgreSQL Global Development Group
+*
+* IDENTIFICATION
+* $PostgreSQL$
+*
+*-------------------------------------------------------------------------
+*/
+package org.postgresql.ds;
+
+import javax.sql.DataSource;
+
+/**
+ * Simple DataSource which does not perform connection pooling. In order to use
+ * 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)
+ */
+public class PGSimpleDataSource
+ extends @SIMPLE_DS_CLASS@
+ implements DataSource
+{
+}
diff --git a/org/postgresql/ds/common/PooledConnectionImpl.java b/org/postgresql/ds/common/PooledConnectionImpl.java
deleted file mode 100644
index d8a61159..00000000
--- a/org/postgresql/ds/common/PooledConnectionImpl.java
+++ /dev/null
@@ -1,483 +0,0 @@
-/*-------------------------------------------------------------------------
-*
-* Copyright (c) 2004-2005, PostgreSQL Global Development Group
-*
-* IDENTIFICATION
-* $PostgreSQL: pgjdbc/org/postgresql/ds/common/PooledConnectionImpl.java,v 1.10 2005/01/17 10:59:04 jurka Exp $
-*
-*-------------------------------------------------------------------------
-*/
-package org.postgresql.ds.common;
-
-import javax.sql.*;
-import java.sql.*;
-import java.util.*;
-import java.lang.reflect.*;
-import org.postgresql.PGConnection;
-import org.postgresql.util.GT;
-import org.postgresql.util.PSQLException;
-import org.postgresql.util.PSQLState;
-
-/**
- * PostgreSQL implementation of the PooledConnection interface. This shouldn't
- * be used directly, as the pooling client should just interact with the
- * ConnectionPool instead.
- * @see org.postgresql.ds.PGConnectionPoolDataSource
- *
- * @author Aaron Mulder (ammulder@chariotsolutions.com)
- * @author Csaba Nagy (ncsaba@yahoo.com)
- */
-public class PooledConnectionImpl implements PooledConnection
-{
- private List listeners = new LinkedList();
- private Connection con;
- private ConnectionHandler last;
- private final boolean autoCommit;
- private final boolean isXA;
-
- /**
- * Creates a new PooledConnection representing the specified physical
- * connection.
- */
- public PooledConnectionImpl(Connection con, boolean autoCommit, boolean isXA)
- {
- this.con = con;
- this.autoCommit = autoCommit;
- this.isXA = isXA;
- }
-
- public PooledConnectionImpl(Connection con, boolean autoCommit)
- {
- this(con, autoCommit, false);
- }
-
- /**
- * 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);
- }
-
- /**
- * 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)
- {
- // Before throwing the exception, let's notify the registered listeners about the error
- PSQLException sqlException = new PSQLException(GT.tr("This PooledConnection has already been closed."),
- PSQLState.CONNECTION_DOES_NOT_EXIST);
- fireConnectionFatalError(sqlException);
- throw sqlException;
- }
- // If any error occures while opening a new connection, the listeners
- // have to be notified. This gives a chance to connection pools to
- // elliminate bad pooled connections.
- try
- {
- // 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);
- }
- catch (SQLException sqlException)
- {
- fireConnectionFatalError(sqlException);
- throw (SQLException)sqlException.fillInStackTrace();
- }
- ConnectionHandler handler = new ConnectionHandler(con);
- last = handler;
-
- Connection proxyCon = (Connection)Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Connection.class, PGConnection.class}, handler);
- last.setProxy(proxyCon);
- return proxyCon;
- }
-
- /**
- * Used to fire a connection closed 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 error 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);
- }
- }
-
- // Classes we consider fatal.
- private static String[] fatalClasses = {
- "08", // connection error
- "53", // insufficient resources
-
- // nb: not just "57" as that includes query cancel which is nonfatal
- "57P01", // admin shutdown
- "57P02", // crash shutdown
- "57P03", // cannot connect now
-
- "58", // system error (backend)
- "60", // system error (driver)
- "99", // unexpected error
- "F0", // configuration file error (backend)
- "XX", // internal error (backend)
- };
-
- private static boolean isFatalState(String state) {
- if (state == null) // no info, assume fatal
- return true;
- if (state.length() < 2) // no class info, assume fatal
- return true;
-
- for (int i = 0; i < fatalClasses.length; ++i)
- if (state.startsWith(fatalClasses[i]))
- return true; // fatal
-
- return false;
- }
-
- /**
- * Fires a connection error event, but only if we
- * think the exception is fatal.
- *
- * @param e the SQLException to consider
- */
- private void fireConnectionError(SQLException e)
- {
- if (!isFatalState(e.getSQLState()))
- return;
-
- fireConnectionFatalError(e);
- }
-
- /**
- * 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 Connection proxy; // the Connection the client is currently using, which is a proxy
- private boolean automatic = false;
-
- 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;
- }
- }
- try
- {
- return method.invoke(con, args);
- }
- catch (InvocationTargetException e)
- {
- throw e.getTargetException();
- }
- }
- // All the rest is from the Connection or PGConnection interface
- if (method.getName().equals("isClosed"))
- {
- return con == null ? Boolean.TRUE : Boolean.FALSE;
- }
- if (con == null && !method.getName().equals("close"))
- {
- throw new PSQLException(automatic ? GT.tr("Connection has been closed automatically because a new connection was opened for the same PooledConnection or the PooledConnection has been closed.") : GT.tr("Connection has been closed."),
- PSQLState.CONNECTION_DOES_NOT_EXIST);
- }
- if (method.getName().equals("close"))
- {
- // we are already closed and a double close
- // is not an error.
- if (con == null)
- return null;
-
- SQLException ex = null;
- if (!isXA && !con.getAutoCommit())
- {
- try
- {
- con.rollback();
- }
- catch (SQLException e)
- {
- ex = e;
- }
- }
- con.clearWarnings();
- con = null;
- proxy = null;
- last = null;
- fireConnectionClosed();
- if (ex != null)
- {
- throw ex;
- }
- return null;
- }
-
- // From here on in, we invoke via reflection, catch exceptions,
- // and check if they're fatal before rethrowing.
-
- try {
- if (method.getName().equals("createStatement"))
- {
- Statement st = (Statement)method.invoke(con, args);
- return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Statement.class, org.postgresql.PGStatement.class}, new StatementHandler(this, st));
- }
- else if (method.getName().equals("prepareCall"))
- {
- Statement st = (Statement)method.invoke(con, args);
- return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{CallableStatement.class, org.postgresql.PGStatement.class}, new StatementHandler(this, st));
- }
- else if (method.getName().equals("prepareStatement"))
- {
- Statement st = (Statement)method.invoke(con, args);
- return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{PreparedStatement.class, org.postgresql.PGStatement.class}, new StatementHandler(this, st));
- }
- else
- {
- return method.invoke(con, args);
- }
- } catch (InvocationTargetException e) {
- Throwable te = e.getTargetException();
- if (te instanceof SQLException)
- fireConnectionError((SQLException)te); // Tell listeners about exception if it's fatal
- throw te;
- }
- }
-
- Connection getProxy() {
- return proxy;
- }
-
- void setProxy(Connection proxy) {
- this.proxy = proxy;
- }
-
- public void close()
- {
- if (con != null)
- {
- automatic = true;
- }
- con = null;
- proxy = null;
- // No close event fired here: see JDBC 2.0 Optional Package spec section 6.3
- }
-
- public boolean isClosed() {
- return con == null;
- }
- }
-
- /**
- * Instead of declaring classes implementing Statement, PreparedStatement,
- * and CallableStatement, which would have to be updated for every JDK rev,
- * use a dynamic proxy to handle all calls through the Statement
- * interfaces. This is the part that requires JDK 1.3 or higher, though
- * JDK 1.2 could be supported with a 3rd-party proxy package.
- *
- * The StatementHandler is required in order to return the proper
- * Connection proxy for the getConnection method.
- */
- private class StatementHandler implements InvocationHandler {
- private PooledConnectionImpl.ConnectionHandler con;
- private Statement st;
-
- public StatementHandler(PooledConnectionImpl.ConnectionHandler con, Statement st) {
- this.con = con;
- this.st = st;
- }
- 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 statement wrapping physical statement " + st;
- }
- if (method.getName().equals("hashCode"))
- {
- return new Integer(st.hashCode());
- }
- if (method.getName().equals("equals"))
- {
- if (args[0] == null)
- {
- return Boolean.FALSE;
- }
- try
- {
- return Proxy.isProxyClass(args[0].getClass()) && ((StatementHandler) Proxy.getInvocationHandler(args[0])).st == st ? Boolean.TRUE : Boolean.FALSE;
- }
- catch (ClassCastException e)
- {
- return Boolean.FALSE;
- }
- }
- return method.invoke(st, args);
- }
- // All the rest is from the Statement interface
- if (method.getName().equals("close"))
- {
- // closing an already closed object is a no-op
- if (st == null || con.isClosed())
- return null;
-
- try
- {
- st.close();
- }
- finally
- {
- con = null;
- st = null;
- }
- return null;
- }
- if (st == null || con.isClosed())
- {
- throw new PSQLException(GT.tr("Statement has been closed."),
- PSQLState.OBJECT_NOT_IN_STATE);
- }
-
- if (method.getName().equals("getConnection"))
- {
- return con.getProxy(); // the proxied connection, not a physical connection
- }
-
- try
- {
- return method.invoke(st, args);
- } catch (InvocationTargetException e) {
- Throwable te = e.getTargetException();
- if (te instanceof SQLException)
- fireConnectionError((SQLException)te); // Tell listeners about exception if it's fatal
- throw te;
- }
- }
- }
-}
diff --git a/org/postgresql/ds/jdbc4/AbstractJdbc4PooledConnection.java b/org/postgresql/ds/jdbc4/AbstractJdbc4PooledConnection.java
new file mode 100644
index 00000000..4b2aa739
--- /dev/null
+++ b/org/postgresql/ds/jdbc4/AbstractJdbc4PooledConnection.java
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+*
+* Copyright (c) 2004-2005, PostgreSQL Global Development Group
+*
+* IDENTIFICATION
+* $PostgreSQL$
+*
+*-------------------------------------------------------------------------
+*/
+package org.postgresql.ds.jdbc4;
+
+import java.sql.Connection;
+import javax.sql.StatementEventListener;
+import org.postgresql.ds.jdbc23.AbstractJdbc23PooledConnection;
+
+public abstract class AbstractJdbc4PooledConnection extends AbstractJdbc23PooledConnection
+{
+
+ public AbstractJdbc4PooledConnection(Connection con, boolean autoCommit, boolean isXA)
+ {
+ super(con, autoCommit, isXA);
+ }
+
+ public void removeStatementEventListener(StatementEventListener listener)
+ {
+ }
+
+ public void addStatementEventListener(StatementEventListener listener)
+ {
+ }
+
+}
diff --git a/org/postgresql/ds/jdbc4/AbstractJdbc4PoolingDataSource.java b/org/postgresql/ds/jdbc4/AbstractJdbc4PoolingDataSource.java
new file mode 100644
index 00000000..2a839203
--- /dev/null
+++ b/org/postgresql/ds/jdbc4/AbstractJdbc4PoolingDataSource.java
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+*
+* Copyright (c) 2004-2005, PostgreSQL Global Development Group
+*
+* IDENTIFICATION
+* $PostgreSQL$
+*
+*-------------------------------------------------------------------------
+*/
+package org.postgresql.ds.jdbc4;
+
+import java.sql.SQLException;
+
+import org.postgresql.ds.jdbc23.AbstractJdbc23PoolingDataSource;
+
+public abstract class AbstractJdbc4PoolingDataSource extends AbstractJdbc23PoolingDataSource
+{
+
+ public boolean isWrapperFor(Class<?> iface) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented(this.getClass(), "isWrapperFor(Class<?>)");
+ }
+
+ public <T> T unwrap(Class<T> iface) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented(this.getClass(), "unwrap(Class<T>)");
+ }
+
+}
diff --git a/org/postgresql/ds/jdbc4/AbstractJdbc4SimpleDataSource.java b/org/postgresql/ds/jdbc4/AbstractJdbc4SimpleDataSource.java
new file mode 100644
index 00000000..18135f8d
--- /dev/null
+++ b/org/postgresql/ds/jdbc4/AbstractJdbc4SimpleDataSource.java
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+*
+* Copyright (c) 2004-2005, PostgreSQL Global Development Group
+*
+* IDENTIFICATION
+* $PostgreSQL$
+*
+*-------------------------------------------------------------------------
+*/
+package org.postgresql.ds.jdbc4;
+
+import java.sql.SQLException;
+
+import org.postgresql.ds.jdbc23.AbstractJdbc23SimpleDataSource;
+
+public class AbstractJdbc4SimpleDataSource extends AbstractJdbc23SimpleDataSource
+{
+ public boolean isWrapperFor(Class<?> iface) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented(this.getClass(), "isWrapperFor(Class<?>)");
+ }
+
+ public <T> T unwrap(Class<T> iface) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented(this.getClass(), "unwrap(Class<T>)");
+ }
+
+}
diff --git a/org/postgresql/xa/PGXAConnection.java b/org/postgresql/xa/PGXAConnection.java
index 773fa016..bb20a0e2 100644
--- a/org/postgresql/xa/PGXAConnection.java
+++ b/org/postgresql/xa/PGXAConnection.java
@@ -1,7 +1,7 @@
package org.postgresql.xa;
import org.postgresql.Driver;
-import org.postgresql.ds.common.PooledConnectionImpl;
+import org.postgresql.ds.PGPooledConnection;
import org.postgresql.core.BaseConnection;
import org.postgresql.core.Logger;
@@ -27,7 +27,7 @@ import javax.transaction.xa.XAException;
*
* @author Heikki Linnakangas (heikki.linnakangas@iki.fi)
*/
-public class PGXAConnection extends PooledConnectionImpl implements XAConnection, XAResource
+public class PGXAConnection extends PGPooledConnection implements XAConnection, XAResource
{
/**
* Underlying physical database connection. It's used for issuing PREPARE TRANSACTION/
[parent: 743041f45d5b]