You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ode.apache.org by ms...@apache.org on 2007/02/26 18:24:41 UTC

svn commit: r511910 - in /incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva: ./ cache/ connector/ connector/jdbc/ jdbc/ jdbc/xa/wrapper/ pool/ xml/

Author: mszefler
Date: Mon Feb 26 09:24:33 2007
New Revision: 511910

URL: http://svn.apache.org/viewvc?view=rev&rev=511910
Log:
Major cleanup of Minerva DB pool. 
Fix (hopefully) random NPE's. 
Removed prepared statement pooling as it is redundant with modern JDBC drivers.
Fix NPE when pool runs out of connections in pool (throw resource exception instead). 
Added checks to prevent concurrent state modifications.

Removed:
    incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/cache/CachedObjectFactory.java
    incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/cache/LeastRecentlyUsedCache.java
    incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/cache/ObjectCache.java
    incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/xml/XMLUtils.java
Modified:
    incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/MinervaPool.java
    incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/connector/SharedLocalConnectionManager.java
    incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/connector/jdbc/JDBCManagedConnection.java
    incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/ConnectionInPool.java
    incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/ConnectionWrapper.java
    incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/JDBCConnectionFactory.java
    incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/xa/wrapper/XAClientConnection.java
    incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/xa/wrapper/XAConnectionImpl.java
    incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/pool/ObjectPool.java

Modified: incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/MinervaPool.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/MinervaPool.java?view=diff&rev=511910&r1=511909&r2=511910
==============================================================================
--- incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/MinervaPool.java (original)
+++ incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/MinervaPool.java Mon Feb 26 09:24:33 2007
@@ -35,106 +35,112 @@
 import org.opentools.minerva.connector.jdbc.JDBCManagedConnectionFactory;
 import org.opentools.minerva.pool.PoolParameters;
 
+/**
+ * Component for managing a Minerva JDBC pool.
+ * 
+ * @author mszefler
+ */
 public class MinervaPool {
-  
-  private static final Map<String,MinervaPool> __pools = Collections.synchronizedMap(new HashMap<String, MinervaPool>());
-  
-  private PoolParameters _params = new PoolParameters();
-  
-  JDBCManagedConnectionFactory _mcf = new JDBCManagedConnectionFactory();
-  BaseConnectionManager _connManager;
-
-  private String _id;
-
-  private TransactionManager _tm;
-
-  private PoolType _type = PoolType.MANAGED;
-  private static int __numpools = 0;
-  
-  public MinervaPool() {
-    synchronized(MinervaPool.class) {
-      _id = "Minerva# " + ++__numpools; 
-    }
-
-    _params.blocking = false;
-    _params.gcEnabled = true;
-    _params.idleTimeoutEnabled = true;
-    _params.invalidateOnError = true;
-    _params.minSize = 0;
-    _params.maxSize = 1;
-  }
-
-  public PoolParameters getPoolParams() {
-    return _params;
-  }
-
-  public JDBCManagedConnectionFactory getConnectionFactory() {
-    return _mcf;
-  }
-  
-  public void setTransactionManager(TransactionManager tm) {
-    _tm = tm;
-  }
-  
-  public synchronized void start() throws Exception {
-    if (_connManager != null)
-      return;
-    
-    // First, lets make sure the connection works:
-
-    // Try the managed connection factory to make sure it works.
-    _mcf.createManagedConnection(null,null).destroy();
-    
-    switch (_type) {
-    case UNMANAGED:
-      _connManager = new NoTransConnectionManager();
-      break;
-    case MANAGED:
-      _connManager = new SharedLocalConnectionManager();
-      break;
-    }
-    _connManager.setTransactionManager(_tm);
-    _connManager.createPerFactoryPool(_mcf, _params);
-    __pools.put(_id, this);
-  }
-  
-  public synchronized void stop() {
-    __pools.remove(_id);
-    _connManager.shutDown();
-    _connManager = null;
-  }
-  String getId() {
-    return _id;
-  }
-  
-  static MinervaPool get(String id) {
-    return __pools.get(id);
-  }
-
-  public PoolType getType() {
-    return _type ;
-  }
-  
-  public void setType(PoolType type) {
-    _type = type;
-  }
-  
-  public Reference createDataSourceReference() {
-    Reference ref = new Reference(javax.sql.DataSource.class.getName(),
-        MinervaJDBCDataSourceFactory.class.getName(), null);
-    ref.add(new StringRefAddr(MinervaJDBCDataSourceFactory.REF_ID, _id));    // TODO Auto-generated method stub
-    return ref;
-  }
-
-  public enum PoolType {
-    MANAGED,
-    UNMANAGED
-  }
-
-  public DataSource createDataSource() {
-    JDBCDataSource ds = new JDBCDataSource(_connManager,_mcf);
-    ds.setReference(createDataSourceReference());
-    return ds;
-  }
+
+    private static final Map<String, MinervaPool> __pools = Collections.synchronizedMap(new HashMap<String, MinervaPool>());
+
+    private PoolParameters _params = new PoolParameters();
+
+    JDBCManagedConnectionFactory _mcf = new JDBCManagedConnectionFactory();
+
+    BaseConnectionManager _connManager;
+
+    private String _id;
+
+    private TransactionManager _tm;
+
+    private PoolType _type = PoolType.MANAGED;
+
+    private static int __numpools = 0;
+
+    public MinervaPool() {
+        synchronized (MinervaPool.class) {
+            _id = "Minerva# " + ++__numpools;
+        }
+
+        _params.blocking = false;
+        _params.gcEnabled = true;
+        _params.idleTimeoutEnabled = true;
+        _params.invalidateOnError = true;
+        _params.minSize = 0;
+        _params.maxSize = 1;
+    }
+
+    public PoolParameters getPoolParams() {
+        return _params;
+    }
+
+    public JDBCManagedConnectionFactory getConnectionFactory() {
+        return _mcf;
+    }
+
+    public void setTransactionManager(TransactionManager tm) {
+        _tm = tm;
+    }
+
+    public synchronized void start() throws Exception {
+        if (_connManager != null)
+            return;
+
+        // First, lets make sure the connection works:
+
+        // Try the managed connection factory to make sure it works.
+        _mcf.createManagedConnection(null, null).destroy();
+
+        switch (_type) {
+        case UNMANAGED:
+            _connManager = new NoTransConnectionManager();
+            break;
+        case MANAGED:
+            _connManager = new SharedLocalConnectionManager();
+            break;
+        }
+        _connManager.setTransactionManager(_tm);
+        _connManager.createPerFactoryPool(_mcf, _params);
+        __pools.put(_id, this);
+    }
+
+    public synchronized void stop() {
+        __pools.remove(_id);
+        _connManager.shutDown();
+        _connManager = null;
+    }
+
+    String getId() {
+        return _id;
+    }
+
+    static MinervaPool get(String id) {
+        return __pools.get(id);
+    }
+
+    public PoolType getType() {
+        return _type;
+    }
+
+    public void setType(PoolType type) {
+        _type = type;
+    }
+
+    public Reference createDataSourceReference() {
+        Reference ref = new Reference(javax.sql.DataSource.class.getName(), MinervaJDBCDataSourceFactory.class.getName(), null);
+        ref.add(new StringRefAddr(MinervaJDBCDataSourceFactory.REF_ID, _id)); // TODO Auto-generated method stub
+        return ref;
+    }
+
+    public enum PoolType {
+        MANAGED, UNMANAGED
+    }
+
+    public DataSource createDataSource() {
+        JDBCDataSource ds = new JDBCDataSource(_connManager, _mcf);
+        ds.setReference(createDataSourceReference());
+        return ds;
+    }
 
 }

Modified: incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/connector/SharedLocalConnectionManager.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/connector/SharedLocalConnectionManager.java?view=diff&rev=511910&r1=511909&r2=511910
==============================================================================
--- incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/connector/SharedLocalConnectionManager.java (original)
+++ incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/connector/SharedLocalConnectionManager.java Mon Feb 26 09:24:33 2007
@@ -113,6 +113,9 @@
             // and create one if necessary
             con = (ManagedConnection)pool.getObject(new ConnectionParameters(subj, info));
         }
+        
+        if (con == null)
+            throw new ResourceException("Pool exhausted, not blocking!");
 
         // Register the connection with the Tx Cache & the Transaction
         ConnectionListener listener = null;

Modified: incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/connector/jdbc/JDBCManagedConnection.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/connector/jdbc/JDBCManagedConnection.java?view=diff&rev=511910&r1=511909&r2=511910
==============================================================================
--- incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/connector/jdbc/JDBCManagedConnection.java (original)
+++ incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/connector/jdbc/JDBCManagedConnection.java Mon Feb 26 09:24:33 2007
@@ -38,15 +38,14 @@
 import org.opentools.minerva.pool.PoolEventListener;
 
 /**
- * ManagedConnection implementation for JDBC connections.  Rolls back on
- * cleanup, closes on destroy.  This represents one physical connection to
- * the DB, and it can be shared, but uses LocalTransactions only (no
- * XAResource).
+ * ManagedConnection implementation for JDBC connections. Rolls back on cleanup, closes on destroy. This represents one physical
+ * connection to the DB, and it can be shared, but uses LocalTransactions only (no XAResource).
+ * 
  * @author Aaron Mulder <am...@alumni.princeton.edu>
- * @version $Revision: 245 $
  */
 public class JDBCManagedConnection extends BaseManagedConnection {
     private Connection con;
+
     private String url;
 
     public JDBCManagedConnection(Connection con, String user, String url) {
@@ -56,7 +55,7 @@
     }
 
     public Object getConnection(Subject sub, ConnectionRequestInfo info) throws ResourceException {
-        final ConnectionInPool wrapper = new ConnectionInPool(con, ConnectionInPool.PS_CACHE_UNLIMITED);
+        final ConnectionInPool wrapper = new ConnectionInPool(con);
         wrapper.addPoolEventListener(new PoolEventListener() {
             public void objectClosed(PoolEvent evt) {
                 ConnectionEvent ce = new ConnectionEvent(JDBCManagedConnection.this, ConnectionEvent.CONNECTION_CLOSED);
@@ -64,13 +63,16 @@
                 fireConnectionEvent(ce);
                 wrapper.removePoolEventListener(this);
             }
+
             public void objectError(PoolEvent evt) {
                 ConnectionEvent ce = new ConnectionEvent(JDBCManagedConnection.this, ConnectionEvent.CONNECTION_ERROR_OCCURRED);
                 ce.setConnectionHandle(wrapper);
                 fireConnectionEvent(ce);
                 wrapper.removePoolEventListener(this);
             }
-            public void objectUsed(PoolEvent evt) {}
+
+            public void objectUsed(PoolEvent evt) {
+            }
         });
         return wrapper;
     }
@@ -87,8 +89,8 @@
         super.destroy();
         try {
             con.close();
-        } catch(SQLException e) {
-            throw new ResourceException("Unable to close DB connection: "+e);
+        } catch (SQLException e) {
+            throw new ResourceException("Unable to close DB connection: " + e);
         }
         con = null;
     }
@@ -96,13 +98,13 @@
     public void cleanup() throws ResourceException {
         try {
             con.rollback();
-        } catch(SQLException e) {
-            throw new ResourceException("Unable to rollback DB connection: "+e);
+        } catch (SQLException e) {
+            throw new ResourceException("Unable to rollback DB connection: " + e);
         }
     }
 
     public ManagedConnectionMetaData getMetaData() throws ResourceException {
-        /**@todo: Implement this javax.resource.spi.ManagedConnection method*/
+        /** @todo: Implement this javax.resource.spi.ManagedConnection method */
         throw new java.lang.UnsupportedOperationException("Method getMetaData() not yet implemented.");
     }
 

Modified: incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/ConnectionInPool.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/ConnectionInPool.java?view=diff&rev=511910&r1=511909&r2=511910
==============================================================================
--- incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/ConnectionInPool.java (original)
+++ incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/ConnectionInPool.java Mon Feb 26 09:24:33 2007
@@ -22,25 +22,25 @@
  */
 package org.opentools.minerva.jdbc;
 
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.sql.CallableStatement;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.SQLWarning;
 import java.sql.Savepoint;
 import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.Vector;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
 
-import org.opentools.minerva.cache.LeastRecentlyUsedCache;
-import org.opentools.minerva.cache.ObjectCache;
 import org.opentools.minerva.pool.PoolEvent;
 import org.opentools.minerva.pool.PoolEventListener;
 import org.opentools.minerva.pool.PooledObject;
@@ -51,101 +51,51 @@
  * etc. to update the last used time for the connection.
  * 
  * @author Aaron Mulder (ammulder@alumni.princeton.edu)
+ * @author Maciej Szefler m s z e f l e r ( at ) g m a i l . c o m 
  */
 public class ConnectionInPool implements PooledObject, ConnectionWrapper {
     private final static String CLOSED = "Connection has been closed!";
 
-    public final static int PS_CACHE_UNLIMITED = 0;
+    private static final String CONCURRENT = "Concurrent access to connection not permitted!";
 
-    public final static int PS_CACHE_DISABLED = -1;
+    private static final Class[] RESULT_SET_CLASS = { ResultSet.class };
 
-    public final static Map<Connection, ObjectCache> psCaches = new HashMap<Connection, ObjectCache>();
+    /** The actual (underlying) connection. */
+    protected volatile Connection _con;
 
-    private Connection con;
+    /** Has the object been invalidated? */
+    private volatile boolean _invalid = false;
 
-    private Set<Statement> statements;
+    /** Listeners. */
+    private CopyOnWriteArrayList<PoolEventListener> _listeners = new CopyOnWriteArrayList<PoolEventListener>();
 
-    private Vector<PoolEventListener> listeners;
+    /** Statements/result sets created by this connection wrapper. */
+    private Set<ManagedObject> _managedObjects = new HashSet<ManagedObject>();
 
-    private int preparedStatementCacheSize = 0;
-
-    private ObjectCache preparedStatementCache;
+    /** Work lock: detect concurrent use of connection. */
+    private AtomicBoolean _spinlock = new AtomicBoolean(false);
 
     /**
      * Creates a new connection wrapper.
      * 
-     * @param con
-     *            The "real" database connection to wrap.
+     * @param con the "real" database connection to wrap.
      */
     public ConnectionInPool(Connection con) {
-        this.con = con;
-        preparedStatementCache = psCaches.get(con);
-        if (preparedStatementCache == null) {
-            PreparedStatementFactory factory = new PreparedStatementFactory(con);
-            preparedStatementCache = new LeastRecentlyUsedCache(factory, preparedStatementCacheSize);
-            psCaches.put(con, preparedStatementCache);
-        }
-        statements = new HashSet<Statement>();
-        listeners = new Vector<PoolEventListener>();
-    }
-
-    /**
-     * Creates a new connection wrapper, using the specified maximum size for the prepared statement cache.
-     * 
-     * @param con
-     *            The "real" database connection to wrap.
-     * @param psCacheSize
-     *            The size of the PreparedStatement cache.
-     * @see #PS_CACHE_UNLIMITED
-     * @see #PS_CACHE_DISABLED
-     */
-    public ConnectionInPool(Connection con, int psCacheSize) {
-        this.con = con;
-        if (psCacheSize >= 0) {
-            preparedStatementCache = psCaches.get(con);
-            if (preparedStatementCache == null) {
-                PreparedStatementFactory factory = new PreparedStatementFactory(con);
-                preparedStatementCache = new LeastRecentlyUsedCache(factory, preparedStatementCacheSize);
-                psCaches.put(con, preparedStatementCache);
-            }
-        }
-        setPSCacheSize(psCacheSize);
-        statements = new HashSet<Statement>();
-        listeners = new Vector<PoolEventListener>();
-    }
-
-    /**
-     * Sets the number of PreparedStatements to be cached for each Connection. Your DB product may impose a limit on the number of
-     * open PreparedStatements.
-     * 
-     * @see #PS_CACHE_UNLIMITED
-     * @see #PS_CACHE_DISABLED
-     */
-    public void setPSCacheSize(int maxSize) {
-        preparedStatementCacheSize = maxSize;
-        if (maxSize >= 0 && preparedStatementCache != null)
-            preparedStatementCache.setSize(maxSize);
-    }
-
-    /**
-     * Gets the number of PreparedStatements to be cached for each Connection.
-     */
-    public int getPSCacheSize() {
-        return preparedStatementCacheSize;
+        this._con = con;
     }
 
     /**
      * Adds a listener for pool events.
      */
     public void addPoolEventListener(PoolEventListener listener) {
-        listeners.addElement(listener);
+        _listeners.add(listener);
     }
 
     /**
      * Removes a listener for pool events.
      */
     public void removePoolEventListener(PoolEventListener listener) {
-        listeners.remove(listener);
+        _listeners.remove(listener);
     }
 
     /**
@@ -153,16 +103,7 @@
      * proprietary method - you will defeat all the pooling if you use the underlying connection directly.
      */
     public Connection getUnderlyingConnection() {
-        return con;
-    }
-
-    /**
-     * Closes this connection wrapper permanently. All further calls with throw a SQLException.
-     */
-    public void shutdown() {
-        con = null;
-        statements = null;
-        listeners = null;
+        return _con;
     }
 
     /**
@@ -188,173 +129,153 @@
         firePoolEvent(pe);
     }
 
-    /**
-     * Indicates that a statement has been closed and no longer needs to be tracked. Outstanding statements are closed when the
-     * connection is returned to the pool.
-     */
-    public void statementClosed(Statement st) {
-        statements.remove(st);
-        if ((con != null) && (st instanceof PreparedStatementInPool)) {
-            // Now return the "real" statement to the pool
-            PreparedStatementInPool ps = (PreparedStatementInPool) st;
-            PreparedStatement ups = ps.getUnderlyingPreparedStatement();
-            if (preparedStatementCacheSize >= 0) {
-                preparedStatementCache.returnObject(ps.getArgs(), ups);
-            } else {
-                try {
-                    ups.close();
-                } catch (SQLException e) {
-                }
-            }
-            /*
-             * int rsType = ResultSet.TYPE_FORWARD_ONLY; int rsConcur = ResultSet.CONCUR_READ_ONLY; // We may have JDBC 1.0 driver
-             * try { rsType = ups.getResultSetType(); rsConcur = ups.getResultSetConcurrency(); } catch (Throwable th) { }
-             * PreparedStatementInPool.preparedStatementCache.put( new PSCacheKey(con, ps.getSql(), rsType, rsConcur), ups);
-             */
-        }
-    }
 
     /**
      * Prepares a connection to be returned to the pool. All outstanding statements are closed, and if AutoCommit is off, the
-     * connection is rolled back. No further SQL calls are possible once this is called.
+     * connection is rolled back. No further SQL calls are possible once this is called. This method may be invoked outside the
+     * normal application thread (typically by the transaction manager synchronizer).
      */
-    public void reset() throws SQLException {
-        List<Statement> copy = new ArrayList<Statement>(statements);
-        Iterator<Statement> it = copy.iterator();
-        while (it.hasNext())
-            try {
-                it.next().close();
-            } catch (SQLException e) {
+    public void invalidate() throws SQLException {
+        if (_invalid)
+            return;
+
+        _invalid = true; // this will prevent any further invocations.
+
+        try {
+            // Grab the lock, no waiting, if there is some rogue thread holding on to this
+            // connection, we cannot return to the pool.
+            if (!_spinlock.compareAndSet(false, true)) {
+                // throwing the exception will cause this connection to be purged from the pool.
+                throw new SQLException(CONCURRENT);
             }
-        if (!con.getAutoCommit()) {
-            con.rollback();
+
+            // We have the lock, we're safe, can clean up properly: close all the statements/results sets
+            for (ManagedObject s : _managedObjects)
+                s.invalidate();
+
+            if (!_con.getAutoCommit()) {
+                _con.rollback();
+            }
+        } finally {
+            _con = null;
         }
-        con = null;
     }
 
     /**
      * Dispatches an event to the listeners.
      */
     protected void firePoolEvent(PoolEvent evt) {
-        Vector local = (Vector) listeners.clone();
-        for (int i = local.size() - 1; i >= 0; i--)
+        for (PoolEventListener pel : _listeners) {
             if (evt.getType() == PoolEvent.OBJECT_CLOSED)
-                ((PoolEventListener) local.elementAt(i)).objectClosed(evt);
+                pel.objectClosed(evt);
             else if (evt.getType() == PoolEvent.OBJECT_ERROR)
-                ((PoolEventListener) local.elementAt(i)).objectError(evt);
+                pel.objectError(evt);
             else
-                ((PoolEventListener) local.elementAt(i)).objectUsed(evt);
+                pel.objectUsed(evt);
+        }
     }
 
     // ---- Implementation of java.sql.Connection ----
     public Statement createStatement() throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            StatementInPool st = new StatementInPool(con.createStatement(), this);
-            statements.add(st);
-            return st;
-        } catch (SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public PreparedStatement prepareStatement(PreparedStatementArgs args) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
-        try {
-            PreparedStatementInPool wrapper = null;
-            if (preparedStatementCacheSize >= 0) {
-                PreparedStatement ps = (PreparedStatement) preparedStatementCache.useObject(args);
-                if (ps == null)
-                    throw new SQLException("Unable to create PreparedStatement!");
-                wrapper = new PreparedStatementInPool(ps, this, args);
-            } else {
-                wrapper = new PreparedStatementInPool(con.prepareStatement(args.sql), this, args);
-            }
-            statements.add(wrapper);
-            return wrapper;
+            return proxy(_con.createStatement(), Statement.class);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public CallableStatement prepareCall(String sql) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            return con.prepareCall(sql);
+            return proxy(_con.prepareCall(sql), CallableStatement.class);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public String nativeSQL(String sql) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            return con.nativeSQL(sql);
+            return _con.nativeSQL(sql);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public void setAutoCommit(boolean autoCommit) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            con.setAutoCommit(autoCommit);
+            _con.setAutoCommit(autoCommit);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public boolean getAutoCommit() throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            return con.getAutoCommit();
+            return _con.getAutoCommit();
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public void commit() throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            con.commit();
+            _con.commit();
         } catch (SQLException e) {
             setCatastrophicError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public void rollback() throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            con.rollback();
+            _con.rollback();
         } catch (SQLException e) {
             setCatastrophicError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public void close() throws SQLException {
-        if (con == null)
+        // IMPORTANT: do not call enter()/exit() in this method, doing so will cause deadlock
+        // due to invalidate() being called via callback.
+
+        if (_con == null || _invalid)
             throw new SQLException(CLOSED);
+
         firePoolEvent(new PoolEvent(this, PoolEvent.OBJECT_CLOSED));
-        shutdown();
+
+        _con = null;
+        _listeners = null;
     }
 
     public boolean isClosed() throws SQLException {
+        Connection con = _con; // avoid NPE if _con changes between null test and isClosed() call.
+
         if (con == null)
             return true;
         try {
@@ -366,301 +287,320 @@
     }
 
     public DatabaseMetaData getMetaData() throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            return con.getMetaData();
+            return _con.getMetaData();
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public void setReadOnly(boolean readOnly) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            con.setReadOnly(readOnly);
+            _con.setReadOnly(readOnly);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public boolean isReadOnly() throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            return con.isReadOnly();
+            return _con.isReadOnly();
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public void setCatalog(String catalog) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            con.setCatalog(catalog);
+            _con.setCatalog(catalog);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public String getCatalog() throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            return con.getCatalog();
+            return _con.getCatalog();
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public void setTransactionIsolation(int level) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            con.setTransactionIsolation(level);
+            _con.setTransactionIsolation(level);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public int getTransactionIsolation() throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            return con.getTransactionIsolation();
+            return _con.getTransactionIsolation();
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public SQLWarning getWarnings() throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            return con.getWarnings();
+            return _con.getWarnings();
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public void clearWarnings() throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            con.clearWarnings();
+            _con.clearWarnings();
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            StatementInPool st = new StatementInPool(con.createStatement(resultSetType, resultSetConcurrency), this);
-            statements.add(st);
-            return st;
+            return proxy(_con.createStatement(resultSetType, resultSetConcurrency), Statement.class);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
-        return prepareStatement(sql);
+        enter();
+        try {
+            return proxy(_con.prepareStatement(sql, resultSetType, resultSetConcurrency), PreparedStatement.class);
+        } catch (SQLException e) {
+            setError(e);
+            throw e;
+        } finally {
+            exit();
+        }
     }
 
     public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            return con.prepareCall(sql, resultSetType, resultSetConcurrency);
+            return proxy(_con.prepareCall(sql, resultSetType, resultSetConcurrency), CallableStatement.class);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public Map<String, Class<?>> getTypeMap() throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            return con.getTypeMap();
+            return _con.getTypeMap();
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
-        if (con == null) {
-            throw new SQLException(CLOSED);
-        }
+        enter();
         try {
-            con.setTypeMap(map);
+            _con.setTypeMap(map);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public int getHoldability() throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            return con.getHoldability();
+            return _con.getHoldability();
 
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public void setHoldability(int holdability) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            con.setHoldability(holdability);
+            _con.setHoldability(holdability);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public Savepoint setSavepoint() throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
-
+        enter();
         try {
-            return con.setSavepoint();
+            return _con.setSavepoint();
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public void releaseSavepoint(Savepoint savepoint) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            con.releaseSavepoint(savepoint);
+            _con.releaseSavepoint(savepoint);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public void rollback(Savepoint savepoint) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            con.rollback(savepoint);
+            _con.rollback(savepoint);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            Statement s = con.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
-            statements.add(s);
-            return s;
+            return proxy(_con.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability), Statement.class);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
 
     }
 
     public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
             throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            CallableStatement cs = con.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
-            statements.add(cs);
-            return cs;
+            return proxy(_con.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability), CallableStatement.class);
+
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            return prepareStatement(new PreparedStatementArgs(sql, autoGeneratedKeys));
+            return proxy(_con.prepareStatement(sql, autoGeneratedKeys), PreparedStatement.class);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
 
     }
 
     public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
             throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            PreparedStatement ps = con.prepareStatement(sql, resultSetType, resultSetConcurrency);
-            statements.add(ps);
-            return ps;
+            return proxy(_con.prepareStatement(sql, resultSetType, resultSetConcurrency), PreparedStatement.class);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public PreparedStatement prepareStatement(String sql, int columnIndexes[]) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            PreparedStatement ps = con.prepareStatement(sql, columnIndexes);
-            statements.add(ps);
-            return ps;
+            return proxy(_con.prepareStatement(sql, columnIndexes), PreparedStatement.class);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public Savepoint setSavepoint(String name) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
-
+        enter();
         try {
-            return con.setSavepoint(name);
+            return _con.setSavepoint(name);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
     public PreparedStatement prepareStatement(String sql, String columnNames[]) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
+        enter();
         try {
-            PreparedStatement ps = con.prepareStatement(sql, columnNames);
-            statements.add(ps);
-            return ps;
+            return proxy(_con.prepareStatement(sql, columnNames), PreparedStatement.class);
         } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
     }
 
@@ -668,9 +608,126 @@
      * @see java.sql.Connection#prepareStatement(java.lang.String)
      */
     public PreparedStatement prepareStatement(String sql) throws SQLException {
-        if (con == null)
-            throw new SQLException(CLOSED);
-        return prepareStatement(new PreparedStatementArgs(sql));
+        enter();
+        try {
+            return proxy(_con.prepareStatement(sql), PreparedStatement.class);
+        } finally {
+            exit();
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    /**
+     * Build a managed proxy for a JDBC Statement-type object.
+     */
+    private <ST extends Statement> ST proxy(ST st, Class<ST> cls) throws SQLException {
+        StatementInvocationHandler sih = new StatementInvocationHandler(st);
+        Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { cls }, sih);
+        _managedObjects.add(sih);
+        return (ST) proxy;
+    }
+
+    private ResultSet proxy(ResultSet rs) throws SQLException {
+        ResultSetInvocationHandler sih = new ResultSetInvocationHandler(rs);
+        Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), RESULT_SET_CLASS, sih);
+        _managedObjects.add(sih);
+        return (ResultSet) proxy;
+    }
+
+    protected void enter() throws SQLException {
+        if (_spinlock.compareAndSet(false, true)) {
+            // Got lock, check if we are ok to proceed
+            if (_con == null || _invalid) {
+                // remember, we need to release the lock.
+                _spinlock.set(false);
+                throw new SQLException(CLOSED);
+            }
+        } else {
+            // couldn't get lock. indicates concurrent access attempt.
+            throw new SQLException(CONCURRENT);
+        }
+    }
+
+    protected void exit() {
+        if (!_spinlock.compareAndSet(true, false))
+            throw new IllegalStateException("INTERNAL ERROR: Releasing unheld lock!");
+    }
+
+    private abstract class ManagedObject implements InvocationHandler {
+        protected Object _target;
+
+        protected ManagedObject(Object target) {
+            _target = target;
+        }
+
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            enter();
+            try {
+                if (_target == null)
+                    throw new SQLException(CLOSED);
+
+                Object ret = method.invoke(_target, args);
+
+                if (method.getName().equals("close")) {
+                    _target = null;
+                    _managedObjects.remove(this);
+                }
+                    
+
+                if (ret instanceof ResultSet)
+                    return proxy((ResultSet) ret);
+                if (ret instanceof PreparedStatement)
+                    return proxy((PreparedStatement) ret, PreparedStatement.class);
+                if (ret instanceof CallableStatement)
+                    return proxy((CallableStatement) ret, CallableStatement.class);
+                if (ret instanceof Statement)
+                    return proxy((Statement) ret, Statement.class);
+                return ret;
+            } catch (InvocationTargetException ite) {
+                Throwable ex = ite.getTargetException();
+                if (ex instanceof SQLException)
+                    setError((SQLException) ex);
+                throw ex;
+            } finally {
+                exit();
+            }
+        }
+
+        abstract void invalidate();
+
     }
 
+    private class StatementInvocationHandler extends ManagedObject {
+
+        public StatementInvocationHandler(Statement target) {
+            super(target);
+        }
+
+        public void invalidate() {
+            try {
+                ((Statement) _target).close();
+
+            } catch (Exception ex) {
+                ;
+                ; // not much we can do here.
+            }
+        }
+
+    }
+
+    private class ResultSetInvocationHandler extends ManagedObject {
+
+        public ResultSetInvocationHandler(ResultSet target) {
+            super(target);
+        }
+
+        public void invalidate() {
+            try {
+                ((ResultSet) _target).close();
+            } catch (Exception ex) {
+                ;
+                ; // not much we can do here.
+            }
+        }
+    }
 }

Modified: incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/ConnectionWrapper.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/ConnectionWrapper.java?view=diff&rev=511910&r1=511909&r2=511910
==============================================================================
--- incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/ConnectionWrapper.java (original)
+++ incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/ConnectionWrapper.java Mon Feb 26 09:24:33 2007
@@ -39,15 +39,11 @@
      * it) was used.
      */
     public void setLastUsed();
+    
     /**
      * Indicates to the connection that an error occured.  This is typically
      * used by statements and result sets derived from this connection.
      */
     public void setError(SQLException e);
-    /**
-     * Indicates that a statement derived from this connection was closed.
-     * Statements are tracked so that any open statements can be closed when
-     * the connection is closed (or reused in a pool).
-     */
-    public void statementClosed(Statement st);
+
 }

Modified: incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/JDBCConnectionFactory.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/JDBCConnectionFactory.java?view=diff&rev=511910&r1=511909&r2=511910
==============================================================================
--- incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/JDBCConnectionFactory.java (original)
+++ incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/JDBCConnectionFactory.java Mon Feb 26 09:24:33 2007
@@ -28,7 +28,6 @@
 import java.sql.SQLException;
 import java.util.Properties;
 
-import org.opentools.minerva.cache.ObjectCache;
 import org.opentools.minerva.pool.ObjectPool;
 import org.opentools.minerva.pool.PoolObjectFactory;
 
@@ -47,7 +46,6 @@
     private String userName;
     private String password;
     private PrintWriter log;
-    private int psCacheSize = 10;
     private ObjectPool pool;
 
     /**
@@ -101,20 +99,18 @@
     public String getPassword() {return password;}
 
     /**
-     * Sets the number of PreparedStatements to be cached for each
-     * Connection.  Your DB product may impose a limit on the number
-     * of open PreparedStatements.  The default value is 10.
+     * NOOP 
+     * @deprecated
      */
     public void setPSCacheSize(int size) {
-        psCacheSize = size;
     }
 
     /**
-     * Gets the number of PreparedStatements to be cached for each
-     * Connection.  The default value is 10.
+     * Returns 0.
+     * @deprecated
      */
     public int getPSCacheSize() {
-        return psCacheSize;
+        return 0;
     }
 
     /**
@@ -161,7 +157,6 @@
     public Object prepareObject(Object pooledObject) {
         Connection con = (Connection)pooledObject;
         ConnectionInPool wrapper = new ConnectionInPool(con);
-        wrapper.setPSCacheSize(psCacheSize);
         return wrapper;
     }
 
@@ -181,7 +176,7 @@
         ConnectionInPool wrapper = (ConnectionInPool)clientObject;
         Connection con = wrapper.getUnderlyingConnection();
         try {
-            wrapper.reset();
+            wrapper.invalidate();
         } catch(SQLException e) {
             pool.markObjectAsInvalid(clientObject);
         }
@@ -196,12 +191,6 @@
         try {
             con.rollback();
         } catch(SQLException e) {}
-
-        // Removed all the cached PreparedStatements for this Connection
-        ObjectCache cache = ConnectionInPool.psCaches.remove(con);
-        if(cache != null) {
-            cache.close();
-        }
 
         try {
             con.close();

Modified: incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/xa/wrapper/XAClientConnection.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/xa/wrapper/XAClientConnection.java?view=diff&rev=511910&r1=511909&r2=511910
==============================================================================
--- incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/xa/wrapper/XAClientConnection.java (original)
+++ incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/xa/wrapper/XAClientConnection.java Mon Feb 26 09:24:33 2007
@@ -22,142 +22,39 @@
  */
 package org.opentools.minerva.jdbc.xa.wrapper;
 
-import java.sql.*;
-import java.util.*;
+import java.sql.Connection;
+import java.sql.SQLException;
 
-import org.opentools.minerva.cache.LeastRecentlyUsedCache;
-import org.opentools.minerva.cache.ObjectCache;
-import org.opentools.minerva.jdbc.*;
+import org.opentools.minerva.jdbc.ConnectionInPool;
 import org.opentools.minerva.pool.PoolEvent;
 
 /**
- * Wrapper for database connections used by an XAConnection.  When close is
- * called, it does not close the underlying connection, just informs the
- * XAConnection that close was called.  The connection will not be closed (or
- * returned to the pool) until the transactional details are taken care of.
- * This instance only lives as long as one client is using it - though we
- * probably want to consider reusing it to save object allocations.
- *
+ * Wrapper for database connections used by an XAConnection. When close is called, it does not close the underlying connection, just
+ * informs the XAConnection that close was called. The connection will not be closed (or returned to the pool) until the
+ * transactional details are taken care of. This instance only lives as long as one client is using it - though we probably want to
+ * consider reusing it to save object allocations.
+ * 
  * @author Aaron Mulder (ammulder@alumni.princeton.edu)
  */
-public class XAClientConnection implements ConnectionWrapper {
-    private final static String CLOSED = "Connection has been closed!";
+public class XAClientConnection extends ConnectionInPool {
 
-    private Connection con;
-    private Set<Statement> statements;
     private XAConnectionImpl xaCon;
-    private int preparedStatementCacheSize = 0;
-    private ObjectCache preparedStatementCache;
-
-  public int getHoldability() throws SQLException {
-    throw new UnsupportedOperationException("New JDBC features not supported!");
-
-  }
-
-  public void setHoldability(int holdability) throws SQLException {
-    throw new UnsupportedOperationException("New JDBC features not supported!");
-  }
-
-  public Savepoint setSavepoint() throws SQLException {
-    throw new UnsupportedOperationException("New JDBC features not supported!");
-  }
-
-  public void releaseSavepoint(Savepoint savepoint) throws SQLException {
-    throw new UnsupportedOperationException("New JDBC features not supported!");
-  }
-
-  public void rollback(Savepoint savepoint) throws SQLException {
-    throw new UnsupportedOperationException("New JDBC features not supported!");
-  }
-
-  public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
-    throw new UnsupportedOperationException("New JDBC features not supported!");
-  }
-
-  public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
-    throw new UnsupportedOperationException("New JDBC features not supported!");
-  }
-
-  public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
-    throw new UnsupportedOperationException("New JDBC features not supported!");
-  }
-
-  public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
-    throw new UnsupportedOperationException("New JDBC features not supported!");
-  }
-
-  public PreparedStatement prepareStatement(String sql, int columnIndexes[]) throws SQLException {
-    throw new UnsupportedOperationException("New JDBC features not supported!");
-  }
-
-  public Savepoint setSavepoint(String name) throws SQLException {
-    throw new UnsupportedOperationException("New JDBC features not supported!");
-  }
-
-  public PreparedStatement prepareStatement(String sql, String columnNames[]) throws SQLException {
-    throw new UnsupportedOperationException("New JDBC features not supported!");
-  }
 
     /**
      * Creates a new connection wrapper.
-     * @param xaCon The handler for all the transactional details.
-     * @param con The "real" database connection to wrap.
+     * 
+     * @param xaCon
+     *            The handler for all the transactional details.
+     * @param con
+     *            The "real" database connection to wrap.
      */
     public XAClientConnection(XAConnectionImpl xaCon, Connection con) {
-        this.con = con;
+        super(con);
         this.xaCon = xaCon;
-        preparedStatementCache = ConnectionInPool.psCaches.get(con);
-        if(preparedStatementCache == null) {
-            PreparedStatementFactory factory = new PreparedStatementFactory(con);
-            preparedStatementCache = new LeastRecentlyUsedCache(factory, preparedStatementCacheSize);
-            ConnectionInPool.psCaches.put(con, preparedStatementCache);
-        }
-        statements = new HashSet<Statement>();
-    }
-
-    /**
-     * Sets the number of PreparedStatements to be cached for each
-     * Connection.  Your DB product may impose a limit on the number
-     * of open PreparedStatements.
-     */
-    public void setPSCacheSize(int maxSize) {
-        preparedStatementCacheSize = maxSize;
-        if(maxSize >= 0 && preparedStatementCache != null) {
-            preparedStatementCache.setSize(maxSize);
-        }
     }
 
     /**
-     * Gets the number of PreparedStatements to be cached for each
-     * Connection.
-     */
-    public int getPSCacheSize() {
-        return preparedStatementCacheSize;
-    }
-
-    /**
-     * Gets a reference to the "real" connection.  This should only be used if
-     * you need to cast that to a specific type to call a proprietary method -
-     * you will defeat all the pooling if you use the underlying connection
-     * directly.
-     */
-    public Connection getUnderlyingConnection() {
-        return con;
-    }
-
-    /**
-     * Closes this connection wrapper permanently.  All further calls with throw
-     * a SQLException.
-     */
-    public void shutdown() {
-        con = null;
-        statements = null;
-        xaCon = null;
-    }
-
-    /**
-     * Updates the last used time for this connection to the current time.
-     * This is not used by the current implementation.
+     * Updates the last used time for this connection to the current time. This is not used by the current implementation.
      */
     public void setLastUsed() {
         xaCon.firePoolEvent(new PoolEvent(xaCon, PoolEvent.OBJECT_USED));
@@ -170,281 +67,56 @@
         xaCon.setConnectionError(e);
     }
 
-    /**
-     * Indicates that a statement has been closed and no longer needs to be
-     * tracked.  Outstanding statements are closed when the connection is
-     * returned to the pool.
-     */
-    public void statementClosed(Statement st) {
-        statements.remove(st);
-        if ((con != null) && (st instanceof PreparedStatementInPool)) {
-            // Now return the "real" statement to the pool
-            PreparedStatementInPool ps = (PreparedStatementInPool) st;
-            PreparedStatement ups = ps.getUnderlyingPreparedStatement();
-            preparedStatementCache.returnObject(ps.getArgs(), ups);
-/*
-            int rsType = ResultSet.TYPE_FORWARD_ONLY;
-            int rsConcur = ResultSet.CONCUR_READ_ONLY;
+    public void setAutoCommit(boolean autoCommit) throws SQLException {
+        enter();
+        try {
+            if (((XAResourceImpl) xaCon.getXAResource()).isTransaction() && autoCommit)
+                throw new SQLException(
+                        "Cannot set AutoCommit for a transactional connection: See JDBC 2.0 Optional Package Specification section 7.1 (p25)");
 
-            // We may have JDBC 1.0 driver
             try {
-                rsType = ups.getResultSetType();
-                rsConcur = ups.getResultSetConcurrency();
-            } catch (Throwable th) {
+                _con.setAutoCommit(autoCommit);
+            } catch (SQLException e) {
+                setError(e);
+                throw e;
             }
-            PreparedStatementInPool.preparedStatementCache.put(
-                    new PSCacheKey(con, ps.getSql(), rsType, rsConcur), ups);
-*/
-        }
-    }
-
-    // ---- Implementation of java.sql.Connection ----
-    public Statement createStatement() throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            StatementInPool st = new StatementInPool(con.createStatement(), this);
-            statements.add(st);
-            return st;
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
+        } finally {
+            exit();
         }
-    }
 
-    public PreparedStatement prepareStatement(String sql) throws SQLException {
-      PreparedStatementArgs args = new PreparedStatementArgs(sql);
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            PreparedStatement ps = (PreparedStatement)preparedStatementCache.useObject(args);
-            if(ps == null)
-                throw new SQLException("Unable to create PreparedStatement!");
-            PreparedStatementInPool wrapper = new PreparedStatementInPool(ps, this, args);
-            statements.add(wrapper);
-            return wrapper;
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
     }
 
-    public CallableStatement prepareCall(String sql) throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            return con.prepareCall(sql);
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public String nativeSQL(String sql) throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
+    public void commit() throws SQLException {
+        enter();
         try {
-            return con.nativeSQL(sql);
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public void setAutoCommit(boolean autoCommit) throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        if(((XAResourceImpl)xaCon.getXAResource()).isTransaction() && autoCommit)
-            throw new SQLException("Cannot set AutoCommit for a transactional connection: See JDBC 2.0 Optional Package Specification section 7.1 (p25)");
+            if (((XAResourceImpl) xaCon.getXAResource()).isTransaction())
+                throw new SQLException(
+                        "Cannot commit a transactional connection: See JDBC 2.0 Optional Package Specification section 7.1 (p25)");
 
-        try {
-            con.setAutoCommit(autoCommit);
-        } catch(SQLException e) {
+            _con.commit();
+        } catch (SQLException e) {
             setError(e);
             throw e;
+        } finally {
+            exit();
         }
-
     }
 
-    public boolean getAutoCommit() throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            return con.getAutoCommit();
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public void commit() throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        if(((XAResourceImpl)xaCon.getXAResource()).isTransaction())
-            throw new SQLException("Cannot commit a transactional connection: See JDBC 2.0 Optional Package Specification section 7.1 (p25)");
+    public void rollback() throws SQLException {
+        enter();
         try {
-            con.commit();
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
+            if (((XAResourceImpl) xaCon.getXAResource()).isTransaction())
+                throw new SQLException(
+                        "Cannot rollback a transactional connection: See JDBC 2.0 Optional Package Specification section 7.1 (p25)");
+        } finally {
+            exit();
         }
     }
 
-    public void rollback() throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        if(((XAResourceImpl)xaCon.getXAResource()).isTransaction())
-            throw new SQLException("Cannot rollback a transactional connection: See JDBC 2.0 Optional Package Specification section 7.1 (p25)");
-    }
-
     public void close() throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        List<Statement> copy = new ArrayList<Statement>(statements);
-        Iterator<Statement> it = copy.iterator();
-        while(it.hasNext())
-            try {
-                it.next().close();
-            } catch(SQLException e) {}
-
+        super.close();
         xaCon.clientConnectionClosed();
-        shutdown();
-    }
-
-    public boolean isClosed() throws SQLException {
-        if(con == null) return true;
-        try {
-            return con.isClosed();
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public DatabaseMetaData getMetaData() throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            return con.getMetaData();
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public void setReadOnly(boolean readOnly) throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            con.setReadOnly(readOnly);
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public boolean isReadOnly() throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            return con.isReadOnly();
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public void setCatalog(String catalog) throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            con.setCatalog(catalog);
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public String getCatalog() throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            return con.getCatalog();
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public void setTransactionIsolation(int level) throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            con.setTransactionIsolation(level);
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public int getTransactionIsolation() throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            return con.getTransactionIsolation();
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public SQLWarning getWarnings() throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            return con.getWarnings();
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public void clearWarnings() throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            con.clearWarnings();
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            StatementInPool st = new StatementInPool(con.createStatement(resultSetType, resultSetConcurrency), this);
-            statements.add(st);
-            return st;
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
-        return prepareStatement(sql);
-    }
-
-    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            return con.prepareCall(sql, resultSetType, resultSetConcurrency);
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public Map<String,Class<?>> getTypeMap() throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            return con.getTypeMap();
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
-    }
-
-    public void setTypeMap(Map<String,Class<?>> map) throws SQLException {
-        if(con == null) throw new SQLException(CLOSED);
-        try {
-            con.setTypeMap(map);
-        } catch(SQLException e) {
-            setError(e);
-            throw e;
-        }
+        xaCon = null;
     }
+   
 }

Modified: incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/xa/wrapper/XAConnectionImpl.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/xa/wrapper/XAConnectionImpl.java?view=diff&rev=511910&r1=511909&r2=511910
==============================================================================
--- incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/xa/wrapper/XAConnectionImpl.java (original)
+++ incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/jdbc/xa/wrapper/XAConnectionImpl.java Mon Feb 26 09:24:33 2007
@@ -31,8 +31,6 @@
 import javax.sql.XAConnection;
 import javax.transaction.xa.XAResource;
 
-import org.opentools.minerva.cache.ObjectCache;
-import org.opentools.minerva.jdbc.ConnectionInPool;
 import org.opentools.minerva.pool.PoolEvent;
 import org.opentools.minerva.pool.PoolEventListener;
 import org.opentools.minerva.pool.PooledObject;
@@ -125,9 +123,7 @@
         try {
             con.close();
         } catch(SQLException e) {}
-        ObjectCache cache = ConnectionInPool.psCaches.remove(con);
-        if(cache != null)
-            cache.close();
+
         con = null;
         resource = null;
         listeners.clear();
@@ -218,7 +214,6 @@
     public Connection getConnection() {
         ++clientConnectionCount;
         XAClientConnection xaCon = new XAClientConnection(this, con);
-        xaCon.setPSCacheSize(preparedStatementCacheSize);
         return xaCon;
     }
 

Modified: incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/pool/ObjectPool.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/pool/ObjectPool.java?view=diff&rev=511910&r1=511909&r2=511910
==============================================================================
--- incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/pool/ObjectPool.java (original)
+++ incubator/ode/trunk/minerva/src/main/java/org/opentools/minerva/pool/ObjectPool.java Mon Feb 26 09:24:33 2007
@@ -707,7 +707,7 @@
             log("Pool "+this+" returned object "+object+" to the pool.");
         if(blocking) {
             synchronized(this) {
-                notify();
+                notifyAll();
             }
         }
     }