From 7bf1c8b0ad5f2534362fb6938be28bb041d79c90 Mon Sep 17 00:00:00 2001
From: Barry Lind <barry@xythos.com>
Date: Wed, 25 Sep 2002 07:01:31 +0000
Subject: [PATCH] Applied patch from Aaron Mulder
 (ammulder@alumni.princeton.edu) that fixes jdbc datasource support for
 jdk1.4/jdbc3

 Modified Files:
 	jdbc/build.xml jdbc/org/postgresql/Driver.java.in
 	jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java
 	jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java
 	jdbc/org/postgresql/jdbc2/optional/PooledConnectionImpl.java
 	jdbc/org/postgresql/jdbc2/optional/PoolingDataSource.java
 	jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java
 	jdbc/org/postgresql/test/jdbc2/optional/OptionalTestSuite.java
 	jdbc/org/postgresql/test/jdbc3/Jdbc3TestSuite.java
 Added Files:
 	jdbc/org/postgresql/jdbc3/Jdbc3ConnectionPool.java
 	jdbc/org/postgresql/jdbc3/Jdbc3ObjectFactory.java
 	jdbc/org/postgresql/jdbc3/Jdbc3PooledConnection.java
 	jdbc/org/postgresql/jdbc3/Jdbc3PoolingDataSource.java
 	jdbc/org/postgresql/jdbc3/Jdbc3SimpleDataSource.java
 	jdbc/org/postgresql/test/jdbc2/optional/PoolingDataSourceTest.java
 	jdbc/org/postgresql/test/jdbc3/Jdbc3ConnectionPoolTest.java
 	jdbc/org/postgresql/test/jdbc3/Jdbc3PoolingDataSourceTest.java
 	jdbc/org/postgresql/test/jdbc3/Jdbc3SimpleDataSourceTest.java
 	jdbc/org/postgresql/test/util/MiniJndiContext.java
 	jdbc/org/postgresql/test/util/MiniJndiContextFactory.java
---
 src/interfaces/jdbc/build.xml                 |   4 +-
 .../jdbc/org/postgresql/Driver.java.in        |   2 +-
 .../jdbc2/optional/BaseDataSource.java        |  13 +-
 .../jdbc2/optional/PGObjectFactory.java       |   6 +-
 .../jdbc2/optional/PooledConnectionImpl.java  |   4 +-
 .../jdbc2/optional/PoolingDataSource.java     |  35 ++-
 .../postgresql/jdbc3/Jdbc3ConnectionPool.java |  61 +++++
 .../postgresql/jdbc3/Jdbc3ObjectFactory.java  |  80 ++++++
 .../jdbc3/Jdbc3PooledConnection.java          |  20 ++
 .../jdbc3/Jdbc3PoolingDataSource.java         |  96 ++++++++
 .../jdbc3/Jdbc3SimpleDataSource.java          |  30 +++
 .../jdbc2/optional/BaseDataSourceTest.java    |  50 +++-
 .../jdbc2/optional/OptionalTestSuite.java     |   3 +-
 .../jdbc2/optional/PoolingDataSourceTest.java | 106 ++++++++
 .../test/jdbc3/Jdbc3ConnectionPoolTest.java   |  67 +++++
 .../jdbc3/Jdbc3PoolingDataSourceTest.java     | 155 ++++++++++++
 .../test/jdbc3/Jdbc3SimpleDataSourceTest.java |  60 +++++
 .../postgresql/test/jdbc3/Jdbc3TestSuite.java |  12 +-
 .../postgresql/test/util/MiniJndiContext.java | 228 ++++++++++++++++++
 .../test/util/MiniJndiContextFactory.java     |  22 ++
 20 files changed, 1023 insertions(+), 31 deletions(-)
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ConnectionPool.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ObjectFactory.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PooledConnection.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PoolingDataSource.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3SimpleDataSource.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/PoolingDataSourceTest.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3ConnectionPoolTest.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3PoolingDataSourceTest.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3SimpleDataSourceTest.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContext.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContextFactory.java

diff --git a/src/interfaces/jdbc/build.xml b/src/interfaces/jdbc/build.xml
index 80f9ca9b637..96c3dbb3138 100644
--- a/src/interfaces/jdbc/build.xml
+++ b/src/interfaces/jdbc/build.xml
@@ -6,7 +6,7 @@
 
   This file now requires Ant 1.4.1.  2002-04-18
 
-  $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/build.xml,v 1.28 2002/08/14 20:35:39 barry Exp $
+  $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/build.xml,v 1.29 2002/09/25 07:01:30 barry Exp $
 
 -->
 
@@ -262,6 +262,7 @@
   <target name="testjdbc2optional" depends="jar" if="jdbc2optionaltests">
     <javac srcdir="${srcdir}" destdir="${builddir}" debug="${debug}">
       <include name="${package}/test/jdbc2/optional/**" />
+      <include name="${package}/test/util/**" />
     </javac>
     <java fork="yes" classname="junit.${junit.ui}.TestRunner" taskname="junit" failonerror="true">
       <arg value="org.postgresql.test.jdbc2.optional.OptionalTestSuite" />
@@ -278,6 +279,7 @@
   <target name="testjdbc3" depends="jar" if="jdbc3tests">
     <javac srcdir="${srcdir}" destdir="${builddir}" debug="${debug}">
       <include name="${package}/test/jdbc3/*" />
+      <include name="${package}/test/util/*" />
     </javac>
     <java fork="yes" classname="junit.${junit.ui}.TestRunner" taskname="junit" failonerror="true">
       <arg value="org.postgresql.test.jdbc3.Jdbc3TestSuite" />
diff --git a/src/interfaces/jdbc/org/postgresql/Driver.java.in b/src/interfaces/jdbc/org/postgresql/Driver.java.in
index 328c06ce6b9..0dbb0f04c0f 100644
--- a/src/interfaces/jdbc/org/postgresql/Driver.java.in
+++ b/src/interfaces/jdbc/org/postgresql/Driver.java.in
@@ -446,6 +446,6 @@ public class Driver implements java.sql.Driver
 	}
 
 	//The build number should be incremented for every new build
-	private static int m_buildNumber = 105;
+	private static int m_buildNumber = 106;
 
 }
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java
index c5fbde848ed..417cf87c10c 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/BaseDataSource.java
@@ -8,7 +8,7 @@ import java.sql.*;
  * Base class for data sources and related classes.
  *
  * @author Aaron Mulder (ammulder@chariotsolutions.com)
- * @version $Revision: 1.2 $
+ * @version $Revision: 1.3 $
  */
 public abstract class BaseDataSource implements Referenceable
 {
@@ -233,9 +233,18 @@ public abstract class BaseDataSource implements Referenceable
 		return "jdbc:postgresql://" + serverName + (portNumber == 0 ? "" : ":" + portNumber) + "/" + databaseName;
 	}
 
+    /**
+     * Generates a reference using the appropriate object factory.  This
+     * implementation uses the JDBC 2 optional package object factory.
+     */
+    protected Reference createReference()
+    {
+        return new Reference(getClass().getName(), PGObjectFactory.class.getName(), null);
+    }
+
 	public Reference getReference() throws NamingException
 	{
-		Reference ref = new Reference(getClass().getName(), PGObjectFactory.class.getName(), null);
+		Reference ref = createReference();
 		ref.add(new StringRefAddr("serverName", serverName));
 		if (portNumber != 0)
 		{
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java
index 2ee3c10130b..48778e0e550 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PGObjectFactory.java
@@ -13,7 +13,7 @@ import java.util.Hashtable;
  * consistent.
  *
  * @author Aaron Mulder (ammulder@chariotsolutions.com)
- * @version $Revision: 1.2 $
+ * @version $Revision: 1.3 $
  */
 public class PGObjectFactory implements ObjectFactory
 {
@@ -81,7 +81,7 @@ public class PGObjectFactory implements ObjectFactory
 		return loadBaseDataSource(cp, ref);
 	}
 
-	private Object loadBaseDataSource(BaseDataSource ds, Reference ref)
+	protected Object loadBaseDataSource(BaseDataSource ds, Reference ref)
 	{
 		ds.setDatabaseName(getProperty(ref, "databaseName"));
 		ds.setPassword(getProperty(ref, "password"));
@@ -95,7 +95,7 @@ public class PGObjectFactory implements ObjectFactory
 		return ds;
 	}
 
-	private String getProperty(Reference ref, String s)
+    protected String getProperty(Reference ref, String s)
 	{
 		RefAddr addr = ref.get(s);
 		if (addr == null)
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PooledConnectionImpl.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PooledConnectionImpl.java
index 4eb7d41b654..1d1d8f67df2 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PooledConnectionImpl.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PooledConnectionImpl.java
@@ -13,7 +13,7 @@ import java.lang.reflect.*;
  * @see ConnectionPool
  *
  * @author Aaron Mulder (ammulder@chariotsolutions.com)
- * @version $Revision: 1.2 $
+ * @version $Revision: 1.3 $
  */
 public class PooledConnectionImpl implements PooledConnection
 {
@@ -26,7 +26,7 @@ public class PooledConnectionImpl implements PooledConnection
 	 * Creates a new PooledConnection representing the specified physical
 	 * connection.
 	 */
-	PooledConnectionImpl(Connection con, boolean autoCommit)
+	protected PooledConnectionImpl(Connection con, boolean autoCommit)
 	{
 		this.con = con;
 		this.autoCommit = autoCommit;
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PoolingDataSource.java b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PoolingDataSource.java
index 95ed5d8fef0..1d6c7daeac4 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PoolingDataSource.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/optional/PoolingDataSource.java
@@ -33,7 +33,7 @@ import java.sql.SQLException;
  * <p>This implementation supports JDK 1.3 and higher.</p>
  *
  * @author Aaron Mulder (ammulder@chariotsolutions.com)
- * @version $Revision: 1.2 $
+ * @version $Revision: 1.3 $
  */
 public class PoolingDataSource extends BaseDataSource implements DataSource
 {
@@ -45,7 +45,7 @@ public class PoolingDataSource extends BaseDataSource implements DataSource
 	}
 
 	// Additional Data Source properties
-	private String dataSourceName;
+	protected String dataSourceName;  // Must be protected for subclasses to sync updates to it
 	private int initialConnections = 0;
 	private int maxConnections = 0;
 	// State variables
@@ -262,7 +262,7 @@ public class PoolingDataSource extends BaseDataSource implements DataSource
 	 * 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.
+	 * DataSource.
 	 * @throws java.sql.SQLException
 	 *		   Occurs when the initialConnections is greater than zero, but the
 	 *		   DataSource is not able to create enough physical connections.
@@ -271,7 +271,7 @@ public class PoolingDataSource extends BaseDataSource implements DataSource
 	{
 		synchronized (lock)
 		{
-			source = new ConnectionPool();
+			source = createConnectionPool();
 			source.setDatabaseName(getDatabaseName());
 			source.setPassword(getPassword());
 			source.setPortNumber(getPortNumber());
@@ -285,6 +285,17 @@ public class PoolingDataSource extends BaseDataSource implements DataSource
 		}
 	}
 
+    protected boolean isInitialized() {
+        return initialized;
+    }
+
+    /**
+     * Creates the appropriate ConnectionPool to use for this DataSource.
+     */
+    protected ConnectionPool createConnectionPool() {
+        return new ConnectionPool();
+    }
+
 	/**
 	 * Gets a <b>non-pooled</b> connection, unless the user and password are the
 	 * same as the default values for this connection pool.
@@ -358,13 +369,17 @@ public class PoolingDataSource extends BaseDataSource implements DataSource
 			}
 			used = null;
 		}
-		synchronized (dataSources)
-		{
-			dataSources.remove(dataSourceName);
-		}
-	}
+        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.
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ConnectionPool.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ConnectionPool.java
new file mode 100644
index 00000000000..1f739d5eb9d
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ConnectionPool.java
@@ -0,0 +1,61 @@
+package org.postgresql.jdbc3;
+
+import org.postgresql.jdbc2.optional.ConnectionPool;
+
+import javax.sql.PooledConnection;
+import javax.naming.Reference;
+import java.sql.SQLException;
+
+/**
+ * Jdbc3 implementation of ConnectionPoolDataSource.  This is
+ * typically the interface used by an app server to interact
+ * with connection pools provided by a JDBC driver.  PostgreSQL
+ * does not support XADataSource, the other common connection
+ * pooling interface (for connections supporting the two-phase
+ * commit protocol).
+ *
+ * @author Aaron Mulder (ammulder@alumni.princeton.edu)
+ * @version $Revision: 1.1 $
+ */
+public class Jdbc3ConnectionPool extends ConnectionPool
+{
+    /**
+     * Gets a description of this DataSource.
+     */
+    public String getDescription()
+    {
+        return "Jdbc3ConnectionPool 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 Jdbc3PooledConnection(getConnection(), isDefaultAutoCommit());
+    }
+
+    /**
+     * 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 Jdbc3PooledConnection(getConnection(user, password), isDefaultAutoCommit());
+    }
+
+    /**
+     * Generates a JDBC object factory reference.
+     */
+    protected Reference createReference()
+    {
+        return new Reference(getClass().getName(), Jdbc3ObjectFactory.class.getName(), null);
+    }
+}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ObjectFactory.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ObjectFactory.java
new file mode 100644
index 00000000000..53151b80a24
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ObjectFactory.java
@@ -0,0 +1,80 @@
+package org.postgresql.jdbc3;
+
+import java.util.*;
+import javax.naming.*;
+import org.postgresql.jdbc2.optional.PGObjectFactory;
+
+/**
+ * JDBC3 version of the Object Factory used to recreate objects
+ * from their JNDI references.
+ *
+ * @author Aaron Mulder (ammulder@alumni.princeton.edu)
+ * @version $Revision: 1.1 $
+ */
+public class Jdbc3ObjectFactory extends PGObjectFactory
+{
+    /**
+     * 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(Jdbc3SimpleDataSource.class.getName()))
+        {
+            return loadSimpleDataSource(ref);
+        }
+        else if (ref.getClassName().equals(Jdbc3ConnectionPool.class.getName()))
+        {
+            return loadConnectionPool(ref);
+        }
+        else if (ref.getClassName().equals(Jdbc3PoolingDataSource.class.getName()))
+        {
+            return loadPoolingDataSource(ref);
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    private Object loadPoolingDataSource(Reference ref)
+    {
+        // If DataSource exists, return it
+        String name = getProperty(ref, "dataSourceName");
+        Jdbc3PoolingDataSource pds = Jdbc3PoolingDataSource.getDataSource(name);
+        if (pds != null)
+        {
+            return pds;
+        }
+        // Otherwise, create a new one
+        pds = new Jdbc3PoolingDataSource();
+        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)
+    {
+        Jdbc3SimpleDataSource ds = new Jdbc3SimpleDataSource();
+        return loadBaseDataSource(ds, ref);
+    }
+
+    private Object loadConnectionPool(Reference ref)
+    {
+        Jdbc3ConnectionPool cp = new Jdbc3ConnectionPool();
+        return loadBaseDataSource(cp, ref);
+    }
+
+}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PooledConnection.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PooledConnection.java
new file mode 100644
index 00000000000..cac966ddc81
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PooledConnection.java
@@ -0,0 +1,20 @@
+package org.postgresql.jdbc3;
+
+import org.postgresql.jdbc2.optional.PooledConnectionImpl;
+
+import java.sql.Connection;
+
+/**
+ * JDBC3 implementation of PooledConnection, which manages
+ * a connection in a connection pool.
+ *
+ * @author Aaron Mulder (ammulder@alumni.princeton.edu)
+ * @version $Revision: 1.1 $
+ */
+public class Jdbc3PooledConnection extends PooledConnectionImpl
+{
+    Jdbc3PooledConnection(Connection con, boolean autoCommit)
+    {
+        super(con, autoCommit);
+    }
+}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PoolingDataSource.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PoolingDataSource.java
new file mode 100644
index 00000000000..df3e50ad074
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PoolingDataSource.java
@@ -0,0 +1,96 @@
+package org.postgresql.jdbc3;
+
+import java.util.*;
+import org.postgresql.jdbc2.optional.PoolingDataSource;
+import org.postgresql.jdbc2.optional.ConnectionPool;
+
+import javax.naming.Reference;
+
+/**
+ * JDBC 3 implementation of a pooling DataSource.  This is best
+ * used outside of an application server environment.  Application
+ * servers generally prefer to deal with instances of
+ * ConnectionPoolDataSource (see ConnectionPool) or XADataSource
+ * (not available for PostgreSQL).
+ *
+ * @author Aaron Mulder (ammulder@alumni.princeton.edu)
+ * @version $Revision: 1.1 $
+ */
+public class Jdbc3PoolingDataSource extends PoolingDataSource
+{
+    /**
+     * Store JDBC3 DataSources in different bucket than JDBC2 DataSources
+     */
+    private static Map dataSources = new HashMap();
+
+    /**
+     * Store JDBC3 DataSources in different bucket than JDBC2 DataSources
+     */
+    static Jdbc3PoolingDataSource getDataSource(String name)
+    {
+        return (Jdbc3PoolingDataSource) dataSources.get(name);
+    }
+
+    /**
+     * Store JDBC3 DataSources in different bucket than JDBC2 DataSources
+     */
+    protected void removeStoredDataSource()
+    {
+        synchronized (dataSources)
+        {
+            dataSources.remove(dataSourceName);
+        }
+    }
+
+    /**
+     * Store JDBC3 DataSources in different bucket than JDBC2 DataSources
+     */
+    public void setDataSourceName(String dataSourceName)
+    {
+        if (isInitialized())
+        {
+            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);
+        }
+    }
+
+    /**
+     * Generates a JDBC3 object factory reference.
+     */
+    protected Reference createReference()
+    {
+        return new Reference(getClass().getName(), Jdbc3ObjectFactory.class.getName(), null);
+    }
+
+    /**
+     * Creates a JDBC3 ConnectionPool to use with this DataSource.
+     */
+    protected ConnectionPool createConnectionPool()
+    {
+        return new Jdbc3ConnectionPool();
+    }
+
+    /**
+     * Gets a description of this DataSource.
+     */
+    public String getDescription()
+    {
+        return "JDBC3 Pooling DataSource from " + org.postgresql.Driver.getVersion();
+    }
+}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3SimpleDataSource.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3SimpleDataSource.java
new file mode 100644
index 00000000000..d8dff03221b
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3SimpleDataSource.java
@@ -0,0 +1,30 @@
+package org.postgresql.jdbc3;
+
+import org.postgresql.jdbc2.optional.SimpleDataSource;
+
+import javax.naming.Reference;
+
+/**
+ * JDBC3 implementation of a non-pooling DataSource.
+ *
+ * @author Aaron Mulder (ammulder@alumni.princeton.edu)
+ * @version $Revision: 1.1 $
+ */
+public class Jdbc3SimpleDataSource extends SimpleDataSource
+{
+    /**
+     * Generates a JDBC3 object factory reference.
+     */
+    protected Reference createReference()
+    {
+        return new Reference(getClass().getName(), Jdbc3ObjectFactory.class.getName(), null);
+    }
+
+    /**
+     * Gets a description of this DataSource.
+     */
+    public String getDescription()
+    {
+        return "JDBC3 Non-Pooling DataSource from " + org.postgresql.Driver.getVersion();
+    }
+}
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java
index 7d041496c80..8add0b19d80 100644
--- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java
@@ -2,10 +2,11 @@ package org.postgresql.test.jdbc2.optional;
 
 import junit.framework.TestCase;
 import org.postgresql.test.TestUtil;
-import org.postgresql.jdbc2.optional.SimpleDataSource;
 import org.postgresql.jdbc2.optional.BaseDataSource;
 
 import java.sql.*;
+import java.util.*;
+import javax.naming.*;
 
 /**
  * Common tests for all the BaseDataSource implementations.  This is
@@ -15,10 +16,11 @@ import java.sql.*;
  * tests.
  *
  * @author Aaron Mulder (ammulder@chariotsolutions.com)
- * @version $Revision: 1.3 $
+ * @version $Revision: 1.4 $
  */
 public abstract class BaseDataSourceTest extends TestCase
 {
+    public static String DATA_SOURCE_JNDI = "BaseDataSource";
 	protected Connection con;
 	protected BaseDataSource bds;
 
@@ -60,7 +62,10 @@ public abstract class BaseDataSourceTest extends TestCase
 	 */
 	protected Connection getDataSourceConnection() throws SQLException
 	{
-		initializeDataSource();
+		if(bds == null)
+        {
+            initializeDataSource();
+        }
 		return bds.getConnection();
 	}
 
@@ -174,6 +179,21 @@ public abstract class BaseDataSourceTest extends TestCase
 		}
 	}
 
+    /**
+     * Uses the mini-JNDI implementation for testing purposes
+     */
+    protected InitialContext getInitialContext()
+    {
+        Hashtable env = new Hashtable();
+        env.put(Context.INITIAL_CONTEXT_FACTORY, "org.postgresql.test.util.MiniJndiContextFactory");
+        try {
+            return new InitialContext(env);
+        } catch(NamingException e) {
+            fail("Unable to create InitialContext: "+e.getMessage());
+            return null;
+        }
+    }
+
 	/**
 	 * Eventually, we must test stuffing the DataSource in JNDI and
 	 * then getting it back out and make sure it's still usable.  This
@@ -182,6 +202,26 @@ public abstract class BaseDataSourceTest extends TestCase
 	 */
 	public void testJndi()
 	{
-		// TODO: Put the DS in JNDI, retrieve it, and try some of this stuff again
-	}
+        initializeDataSource();
+        BaseDataSource oldbds = bds;
+        InitialContext ic = getInitialContext();
+        try {
+            ic.rebind(DATA_SOURCE_JNDI, bds);
+            bds = (BaseDataSource)ic.lookup(DATA_SOURCE_JNDI);
+            assertTrue("Got null looking up DataSource from JNDI!", bds != null);
+            compareJndiDataSource(oldbds, bds);
+        } catch (NamingException e) {
+            fail(e.getMessage());
+        }
+        oldbds = bds;
+        testUseConnection();
+        assertTrue("Test should not have changed DataSource ("+bds+" != "+oldbds+")!", bds == oldbds);
+    }
+
+    /**
+     * Check whether a DS was dereferenced from JNDI or recreated.
+     */
+    protected void compareJndiDataSource(BaseDataSource oldbds, BaseDataSource bds) {
+        assertTrue("DataSource was dereferenced, should have been serialized or recreated", bds != oldbds);
+    }
 }
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/OptionalTestSuite.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/OptionalTestSuite.java
index 49108910f90..6acb381da90 100644
--- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/OptionalTestSuite.java
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/OptionalTestSuite.java
@@ -8,7 +8,7 @@ import junit.framework.TestSuite;
  * PooledConnection implementations.
  *
  * @author Aaron Mulder (ammulder@chariotsolutions.com)
- * @version $Revision: 1.2 $
+ * @version $Revision: 1.3 $
  */
 public class OptionalTestSuite extends TestSuite
 {
@@ -21,6 +21,7 @@ public class OptionalTestSuite extends TestSuite
 		TestSuite suite = new TestSuite();
 		suite.addTestSuite(SimpleDataSourceTest.class);
 		suite.addTestSuite(ConnectionPoolTest.class);
+        suite.addTestSuite(ConnectionPoolTest.class);
 		return suite;
 	}
 }
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/PoolingDataSourceTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/PoolingDataSourceTest.java
new file mode 100644
index 00000000000..9b08eca7d0c
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/PoolingDataSourceTest.java
@@ -0,0 +1,106 @@
+package org.postgresql.test.jdbc2.optional;
+
+import java.sql.SQLException;
+import org.postgresql.test.TestUtil;
+import org.postgresql.jdbc2.optional.PoolingDataSource;
+import org.postgresql.jdbc2.optional.BaseDataSource;
+
+/**
+ * Minimal tests for pooling DataSource.  Needs many more.
+ *
+ * @author Aaron Mulder (ammulder@chariotsolutions.com)
+ * @version $Revision: 1.1 $
+ */
+public class PoolingDataSourceTest extends BaseDataSourceTest
+{
+    private final static String DS_NAME = "JDBC 2 SE Test DataSource";
+
+    /**
+     * Constructor required by JUnit
+     */
+    public PoolingDataSourceTest(String name)
+    {
+        super(name);
+    }
+
+    protected void tearDown() throws Exception
+    {
+        super.tearDown();
+        if (bds instanceof PoolingDataSource)
+        {
+            ((PoolingDataSource) bds).close();
+        }
+    }
+
+    /**
+     * Creates and configures a new SimpleDataSource.
+     */
+    protected void initializeDataSource()
+    {
+        if (bds == null)
+        {
+            bds = new PoolingDataSource();
+            String db = TestUtil.getURL();
+            if (db.indexOf('/') > -1)
+            {
+                db = db.substring(db.lastIndexOf('/') + 1);
+            }
+            else if (db.indexOf(':') > -1)
+            {
+                db = db.substring(db.lastIndexOf(':') + 1);
+            }
+            bds.setDatabaseName(db);
+            bds.setUser(TestUtil.getUser());
+            bds.setPassword(TestUtil.getPassword());
+            ((PoolingDataSource) bds).setDataSourceName(DS_NAME);
+            ((PoolingDataSource) bds).setInitialConnections(2);
+            ((PoolingDataSource) bds).setMaxConnections(10);
+        }
+    }
+
+    /**
+     * In this case, we *do* want it to be pooled.
+     */
+    public void testNotPooledConnection()
+    {
+        try
+        {
+            con = getDataSourceConnection();
+            String name = con.toString();
+            con.close();
+            con = getDataSourceConnection();
+            String name2 = con.toString();
+            con.close();
+            assertTrue("Pooled DS doesn't appear to be pooling connections!", name.equals(name2));
+        }
+        catch (SQLException e)
+        {
+            fail(e.getMessage());
+        }
+    }
+
+    /**
+     * In this case, the desired behavior is dereferencing.
+     */
+    protected void compareJndiDataSource(BaseDataSource oldbds, BaseDataSource bds)
+    {
+        assertTrue("DataSource was serialized or recreated, should have been dereferenced", bds == oldbds);
+    }
+
+    /**
+     * Check that 2 DS instances can't use the same name.
+     */
+    public void testCantReuseName()
+    {
+        initializeDataSource();
+        PoolingDataSource pds = new PoolingDataSource();
+        try
+        {
+            pds.setDataSourceName(DS_NAME);
+            fail("Should have denied 2nd DataSource with same name");
+        }
+        catch (IllegalArgumentException e)
+        {
+        }
+    }
+}
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3ConnectionPoolTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3ConnectionPoolTest.java
new file mode 100644
index 00000000000..a171e8ff025
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3ConnectionPoolTest.java
@@ -0,0 +1,67 @@
+package org.postgresql.test.jdbc3;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import javax.sql.PooledConnection;
+import org.postgresql.test.jdbc2.optional.ConnectionPoolTest;
+import org.postgresql.test.TestUtil;
+import org.postgresql.jdbc3.*;
+
+/**
+ * Tests JDBC3 implementation of ConnectionPoolDataSource.
+ *
+ * @author Aaron Mulder (ammulder@chariotsolutions.com)
+ * @version $Revision: 1.1 $
+ */
+public class Jdbc3ConnectionPoolTest extends ConnectionPoolTest
+{
+    public Jdbc3ConnectionPoolTest(String name)
+    {
+        super(name);
+    }
+
+    /**
+     * Creates and configures a Jdbc3ConnectionPool
+     */
+    protected void initializeDataSource()
+    {
+        if (bds == null)
+        {
+            bds = new Jdbc3ConnectionPool();
+            String db = TestUtil.getURL();
+            if (db.indexOf('/') > -1)
+            {
+                db = db.substring(db.lastIndexOf('/') + 1);
+            }
+            else if (db.indexOf(':') > -1)
+            {
+                db = db.substring(db.lastIndexOf(':') + 1);
+            }
+            bds.setDatabaseName(db);
+            bds.setUser(TestUtil.getUser());
+            bds.setPassword(TestUtil.getPassword());
+        }
+    }
+
+    /**
+     * Makes sure this is a JDBC 3 implementation producing JDBC3
+     * connections.  Depends on toString implementation of
+     * connection wrappers.
+     */
+    public void testConfirmJdbc3Impl()
+    {
+        try
+        {
+            initializeDataSource();
+            assertTrue("Wrong ConnectionPool impl used by test: " + bds.getClass().getName(), bds instanceof Jdbc3ConnectionPool);
+            PooledConnection pc = ((Jdbc3ConnectionPool) bds).getPooledConnection();
+            assertTrue("Wrong PooledConnection impl generated by JDBC3 ConnectionPoolDataSource: " + pc.getClass().getName(), pc instanceof Jdbc3PooledConnection);
+            assertTrue("Wrong Connnection class used in JDBC3 ConnectionPoolDataSource's PooledConnection impl: " + pc.getConnection().toString(), pc.getConnection().toString().indexOf("Jdbc3") > -1);
+            pc.close();
+        }
+        catch (SQLException e)
+        {
+            fail(e.getMessage());
+        }
+    }
+}
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3PoolingDataSourceTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3PoolingDataSourceTest.java
new file mode 100644
index 00000000000..55374cb1b81
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3PoolingDataSourceTest.java
@@ -0,0 +1,155 @@
+package org.postgresql.test.jdbc3;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import org.postgresql.test.jdbc2.optional.PoolingDataSourceTest;
+import org.postgresql.test.TestUtil;
+import org.postgresql.jdbc3.Jdbc3PoolingDataSource;
+import org.postgresql.jdbc2.optional.PoolingDataSource;
+
+/**
+ * Minimal tests for JDBC3 pooling DataSource.  Needs many more.
+ *
+ * @author Aaron Mulder (ammulder@chariotsolutions.com)
+ * @version $Revision: 1.1 $
+ */
+public class Jdbc3PoolingDataSourceTest extends PoolingDataSourceTest
+{
+    private final static String DS_NAME = "JDBC 3 Test DataSource";
+
+    /**
+     * Constructor required by JUnit
+     */
+    public Jdbc3PoolingDataSourceTest(String name)
+    {
+        super(name);
+    }
+
+    /**
+     * Creates and configures a new SimpleDataSource.
+     */
+    protected void initializeDataSource()
+    {
+        if (bds == null)
+        {
+            bds = new Jdbc3PoolingDataSource();
+            configureDataSource((Jdbc3PoolingDataSource) bds);
+        }
+    }
+
+    private void configureDataSource(PoolingDataSource source)
+    {
+        String db = TestUtil.getURL();
+        if (db.indexOf('/') > -1)
+        {
+            db = db.substring(db.lastIndexOf('/') + 1);
+        }
+        else if (db.indexOf(':') > -1)
+        {
+            db = db.substring(db.lastIndexOf(':') + 1);
+        }
+        source.setDatabaseName(db);
+        source.setUser(TestUtil.getUser());
+        source.setPassword(TestUtil.getPassword());
+        source.setDataSourceName(DS_NAME);
+        source.setInitialConnections(2);
+        source.setMaxConnections(10);
+    }
+
+    /**
+     * Check that 2 DS instances can't use the same name.
+     */
+    public void testCantReuseName()
+    {
+        initializeDataSource();
+        Jdbc3PoolingDataSource pds = new Jdbc3PoolingDataSource();
+        try
+        {
+            pds.setDataSourceName(DS_NAME);
+            fail("Should have denied 2nd DataSource with same name");
+        }
+        catch (IllegalArgumentException e)
+        {
+        }
+    }
+
+    /**
+     * Test that JDBC 2 and JDBC 3 DSs come from different buckets
+     * as far as creating with the same name
+     */
+    public void testDifferentImplPools()
+    {
+        initializeDataSource();
+        PoolingDataSource pds = new PoolingDataSource();
+        try
+        {
+            configureDataSource(pds);
+            PoolingDataSource p2 = new PoolingDataSource();
+            try
+            {
+                configureDataSource(p2);
+                fail("Shouldn't be able to create 2 JDBC 2 DSs with same name");
+            }
+            catch (IllegalArgumentException e)
+            {
+            }
+            Jdbc3PoolingDataSource p3 = new Jdbc3PoolingDataSource();
+            try
+            {
+                configureDataSource(p3);
+                fail("Shouldn't be able to create 2 JDBC 3 DSs with same name");
+            }
+            catch (IllegalArgumentException e)
+            {
+            }
+        }
+        finally
+        {
+            pds.close();
+        }
+    }
+
+    /**
+     * Test that JDBC 2 and JDBC 3 DSs come from different buckets
+     * as far as fetching from JNDI
+     */
+    public void testDifferentImplJndi()
+    {
+        initializeDataSource();
+        PoolingDataSource pds = new PoolingDataSource();
+        try
+        {
+            configureDataSource(pds);
+            try
+            {
+                Connection j3c = getDataSourceConnection();
+                Connection j2c = pds.getConnection();
+                j2c.close();
+                j3c.close();
+                InitialContext ctx = getInitialContext();
+                ctx.bind("JDBC2", pds);
+                ctx.bind("JDBC3", bds);
+                pds = (PoolingDataSource) ctx.lookup("JDBC2");
+                bds = (Jdbc3PoolingDataSource) ctx.lookup("JDBC3");
+                j2c = pds.getConnection();
+                j3c = bds.getConnection();
+                j2c.close();
+                j3c.close();
+            }
+            catch (SQLException e)
+            {
+                fail(e.getMessage());
+            }
+            catch (NamingException e)
+            {
+                fail(e.getMessage());
+            }
+        }
+        finally
+        {
+            pds.close();
+        }
+    }
+}
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3SimpleDataSourceTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3SimpleDataSourceTest.java
new file mode 100644
index 00000000000..cef4c83f651
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3SimpleDataSourceTest.java
@@ -0,0 +1,60 @@
+package org.postgresql.test.jdbc3;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.postgresql.test.jdbc2.optional.SimpleDataSourceTest;
+import org.postgresql.test.TestUtil;
+import org.postgresql.jdbc3.*;
+
+/**
+ * Tests JDBC3 non-pooling DataSource.
+ *
+ * @author Aaron Mulder (ammulder@chariotsolutions.com)
+ * @version $Revision: 1.1 $
+ */
+public class Jdbc3SimpleDataSourceTest extends SimpleDataSourceTest {
+    /**
+     * Constructor required by JUnit
+     */
+    public Jdbc3SimpleDataSourceTest(String name)
+    {
+        super(name);
+    }
+
+    /**
+     * Creates and configures a new SimpleDataSource.
+     */
+    protected void initializeDataSource()
+    {
+        if (bds == null)
+        {
+            bds = new Jdbc3SimpleDataSource();
+            String db = TestUtil.getURL();
+            if (db.indexOf('/') > -1)
+            {
+                db = db.substring(db.lastIndexOf('/') + 1);
+            }
+            else if (db.indexOf(':') > -1)
+            {
+                db = db.substring(db.lastIndexOf(':') + 1);
+            }
+            bds.setDatabaseName(db);
+            bds.setUser(TestUtil.getUser());
+            bds.setPassword(TestUtil.getPassword());
+        }
+    }
+    /**
+     * Makes sure this is a JDBC 3 implementation producing JDBC3
+     * connections.
+     */
+    public void testConfirmJdbc3Impl()
+    {
+        try {
+            Connection con = getDataSourceConnection();
+            assertTrue("Wrong SimpleDataSource impl used by test: "+bds.getClass().getName(), bds instanceof Jdbc3SimpleDataSource);
+            assertTrue("Wrong Connnection class generated by JDBC3 DataSource: "+con.getClass().getName(), con instanceof Jdbc3Connection);
+        } catch (SQLException e) {
+            fail(e.getMessage());
+        }
+    }
+}
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3TestSuite.java b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3TestSuite.java
index 5278977de46..ec560213a9e 100644
--- a/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3TestSuite.java
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc3/Jdbc3TestSuite.java
@@ -1,10 +1,6 @@
 package org.postgresql.test.jdbc3;
 
 import junit.framework.TestSuite;
-import junit.framework.TestCase;
-import junit.framework.Test;
-
-import java.sql.*;
 
 /*
  * Executes all known tests for JDBC3
@@ -17,7 +13,11 @@ public class Jdbc3TestSuite extends TestSuite
 	 */
 	public static TestSuite suite()
 	{
-		//Currently there are no specific jdbc3 tests so just run the jdbc2 tests
-		return org.postgresql.test.jdbc2.Jdbc2TestSuite.suite();
+        TestSuite suite = new TestSuite();
+		suite.addTest(org.postgresql.test.jdbc2.Jdbc2TestSuite.suite());
+        suite.addTestSuite(Jdbc3SimpleDataSourceTest.class);
+        suite.addTestSuite(Jdbc3ConnectionPoolTest.class);
+        suite.addTestSuite(Jdbc3PoolingDataSourceTest.class);
+        return suite;
 	}
 }
diff --git a/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContext.java b/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContext.java
new file mode 100644
index 00000000000..4caf24120c5
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContext.java
@@ -0,0 +1,228 @@
+package org.postgresql.test.util;
+
+import java.util.*;
+import java.rmi.MarshalledObject;
+import java.io.Serializable;
+import javax.naming.*;
+import javax.naming.spi.ObjectFactory;
+
+/**
+ * The Context for a trivial JNDI implementation.  This is not meant to
+ * be very useful, beyond testing JNDI features of the connection
+ * pools.  It is not a complete JNDI implementations.
+ *
+ * @author Aaron Mulder (ammulder@chariotsolutions.com)
+ * @version $Revision: 1.1 $
+ */
+public class MiniJndiContext implements Context
+{
+    private Map map = new HashMap();
+
+    public MiniJndiContext()
+    {
+    }
+
+    public Object lookup(Name name) throws NamingException
+    {
+        return lookup(name.get(0));
+    }
+
+    public Object lookup(String name) throws NamingException
+    {
+        Object o = map.get(name);
+        if (o == null)
+        {
+            return null;
+        }
+        if (o instanceof Reference)
+        {
+            Reference ref = (Reference) o;
+            try
+            {
+                Class factoryClass = Class.forName(ref.getFactoryClassName());
+                ObjectFactory fac = (ObjectFactory) factoryClass.newInstance();
+                Object result = fac.getObjectInstance(ref, null, this, null);
+                return result;
+            }
+            catch (Exception e)
+            {
+                throw new NamingException("Unable to dereference to object: " + e);
+            }
+        }
+        else if (o instanceof MarshalledObject)
+        {
+            try
+            {
+                Object result = ((MarshalledObject) o).get();
+                return result;
+            }
+            catch (java.io.IOException e)
+            {
+                throw new NamingException("Unable to deserialize object: " + e);
+            }
+            catch (ClassNotFoundException e)
+            {
+                throw new NamingException("Unable to deserialize object: " + e);
+            }
+        }
+        else
+        {
+            throw new NamingException("JNDI Object is neither Referenceable nor Serializable");
+        }
+    }
+
+    public void bind(Name name, Object obj) throws NamingException
+    {
+        rebind(name.get(0), obj);
+    }
+
+    public void bind(String name, Object obj) throws NamingException
+    {
+        rebind(name, obj);
+    }
+
+    public void rebind(Name name, Object obj) throws NamingException
+    {
+        rebind(name.get(0), obj);
+    }
+
+    public void rebind(String name, Object obj) throws NamingException
+    {
+        if (obj instanceof Referenceable)
+        {
+            Reference ref = ((Referenceable) obj).getReference();
+            map.put(name, ref);
+        }
+        else if (obj instanceof Serializable)
+        {
+            try
+            {
+                MarshalledObject mo = new MarshalledObject(obj);
+                map.put(name, mo);
+            }
+            catch (java.io.IOException e)
+            {
+                throw new NamingException("Unable to serialize object to JNDI: " + e);
+            }
+        }
+        else
+        {
+            throw new NamingException("Object to store in JNDI is neither Referenceable nor Serializable");
+        }
+    }
+
+    public void unbind(Name name) throws NamingException
+    {
+        unbind(name.get(0));
+    }
+
+    public void unbind(String name) throws NamingException
+    {
+        map.remove(name);
+    }
+
+    public void rename(Name oldName, Name newName) throws NamingException
+    {
+        rename(oldName.get(0), newName.get(0));
+    }
+
+    public void rename(String oldName, String newName) throws NamingException
+    {
+        map.put(newName, map.remove(oldName));
+    }
+
+    public NamingEnumeration list(Name name) throws NamingException
+    {
+        return null;
+    }
+
+    public NamingEnumeration list(String name) throws NamingException
+    {
+        return null;
+    }
+
+    public NamingEnumeration listBindings(Name name) throws NamingException
+    {
+        return null;
+    }
+
+    public NamingEnumeration listBindings(String name) throws NamingException
+    {
+        return null;
+    }
+
+    public void destroySubcontext(Name name) throws NamingException
+    {
+    }
+
+    public void destroySubcontext(String name) throws NamingException
+    {
+    }
+
+    public Context createSubcontext(Name name) throws NamingException
+    {
+        return null;
+    }
+
+    public Context createSubcontext(String name) throws NamingException
+    {
+        return null;
+    }
+
+    public Object lookupLink(Name name) throws NamingException
+    {
+        return null;
+    }
+
+    public Object lookupLink(String name) throws NamingException
+    {
+        return null;
+    }
+
+    public NameParser getNameParser(Name name) throws NamingException
+    {
+        return null;
+    }
+
+    public NameParser getNameParser(String name) throws NamingException
+    {
+        return null;
+    }
+
+    public Name composeName(Name name, Name prefix) throws NamingException
+    {
+        return null;
+    }
+
+    public String composeName(String name, String prefix)
+            throws NamingException
+    {
+        return null;
+    }
+
+    public Object addToEnvironment(String propName, Object propVal)
+            throws NamingException
+    {
+        return null;
+    }
+
+    public Object removeFromEnvironment(String propName)
+            throws NamingException
+    {
+        return null;
+    }
+
+    public Hashtable getEnvironment() throws NamingException
+    {
+        return null;
+    }
+
+    public void close() throws NamingException
+    {
+    }
+
+    public String getNameInNamespace() throws NamingException
+    {
+        return null;
+    }
+}
diff --git a/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContextFactory.java b/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContextFactory.java
new file mode 100644
index 00000000000..58cc533ce0e
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/test/util/MiniJndiContextFactory.java
@@ -0,0 +1,22 @@
+package org.postgresql.test.util;
+
+import java.util.*;
+import javax.naming.*;
+import javax.naming.spi.InitialContextFactory;
+
+/**
+ * The ICF for a trivial JNDI implementation.  This is not meant to
+ * be very useful, beyond testing JNDI features of the connection
+ * pools.
+ *
+ * @author Aaron Mulder (ammulder@chariotsolutions.com)
+ * @version $Revision: 1.1 $
+ */
+public class MiniJndiContextFactory implements InitialContextFactory
+{
+    public Context getInitialContext(Hashtable environment)
+            throws NamingException
+    {
+        return new MiniJndiContext();
+    }
+}
-- 
GitLab