You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2015/05/03 11:18:35 UTC

[3/3] cayenne git commit: CAY-2009 Non-blocking connection pool

CAY-2009 Non-blocking connection pool

    * moving everything into a new datasource package ("conn" package name makes no sense)
    * stopped using javax.sql.ConnectionPoolDataSource. Using simple delegation
      to a non-pooled DataSource instead
    * non-blocking data structures for operating the pool


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/517df07b
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/517df07b
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/517df07b

Branch: refs/heads/master
Commit: 517df07b7665fb7786b4ffd519e8c9a2f3855ff9
Parents: d28c036
Author: aadamchik <aa...@apache.org>
Authored: Sun May 3 05:14:19 2015 -0400
Committer: aadamchik <aa...@apache.org>
Committed: Sun May 3 05:15:06 2015 -0400

----------------------------------------------------------------------
 .../org/apache/cayenne/access/DbGenerator.java  |   2 +-
 .../server/PropertyDataSourceFactory.java       |   4 +-
 .../server/XMLPoolingDataSourceFactory.java     |   4 +-
 .../apache/cayenne/conn/ConnectionWrapper.java  | 749 -------------------
 .../apache/cayenne/conn/DataSourceBuilder.java  | 140 ----
 .../apache/cayenne/conn/DriverDataSource.java   | 298 --------
 .../cayenne/conn/ManagedPoolingDataSource.java  | 155 ----
 .../cayenne/conn/PooledConnectionFactory.java   |  90 ---
 .../cayenne/conn/PooledConnectionImpl.java      | 195 -----
 .../apache/cayenne/conn/PoolingDataSource.java  | 471 ------------
 .../conn/PoolingDataSourceParameters.java       |  64 --
 .../java/org/apache/cayenne/conn/package.html   |  26 -
 .../datasource/BadValidationQueryException.java |  41 +
 .../cayenne/datasource/DataSourceBuilder.java   | 135 ++++
 .../cayenne/datasource/DriverDataSource.java    | 298 ++++++++
 .../datasource/ManagedPoolingDataSource.java    | 107 +++
 .../cayenne/datasource/PoolAwareConnection.java | 609 +++++++++++++++
 .../cayenne/datasource/PoolingDataSource.java   | 314 ++++++++
 .../datasource/PoolingDataSourceManager.java    |  65 ++
 .../datasource/PoolingDataSourceParameters.java |  64 ++
 .../cayenne/datasource/StoppedDataSource.java   |  88 +++
 .../cayenne/conn/BasePoolingDataSourceIT.java   |  74 --
 .../cayenne/conn/DriverDataSourceTest.java      |  43 --
 .../cayenne/conn/PooledConnectionImplTest.java  |  67 --
 .../cayenne/conn/PoolingDataSourceIT.java       |  72 --
 ...lingDataSource_FailingValidationQueryIT.java |  43 --
 .../PoolingDataSource_ValidationQueryIT.java    |  55 --
 .../datasource/BasePoolingDataSourceIT.java     |  77 ++
 .../datasource/DriverDataSourceTest.java        |  44 ++
 .../datasource/PoolAwareConnectionTest.java     |  99 +++
 .../cayenne/datasource/PoolingDataSourceIT.java | 160 ++++
 .../datasource/PoolingDataSourceTest.java       | 196 +++++
 ...lingDataSource_FailingValidationQueryIT.java |  66 ++
 .../PoolingDataSource_StaticsTest.java          |  41 +
 .../PoolingDataSource_ValidationQueryIT.java    |  56 ++
 .../di/server/ServerCaseDataSourceFactory.java  |   2 +-
 .../apache/cayenne/tools/DbGeneratorTask.java   |   2 +-
 .../configuration/DriverDataSourceFactory.java  |   2 +-
 docs/doc/src/main/resources/RELEASE-NOTES.txt   |   1 +
 .../dialog/pref/DataSourcePreferences.java      |   2 +-
 .../cayenne/modeler/pref/DBConnectionInfo.java  |   2 +-
 .../apache/cayenne/tools/DbGeneratorMojo.java   |   2 +-
 42 files changed, 2472 insertions(+), 2553 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/access/DbGenerator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbGenerator.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbGenerator.java
index f31f61c..275e07e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbGenerator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DbGenerator.java
@@ -36,7 +36,7 @@ import javax.sql.DataSource;
 
 import org.apache.cayenne.ashwood.AshwoodEntitySorter;
 import org.apache.cayenne.conn.DataSourceInfo;
-import org.apache.cayenne.conn.DriverDataSource;
+import org.apache.cayenne.datasource.DriverDataSource;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.PkGenerator;
 import org.apache.cayenne.dba.TypesMapping;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PropertyDataSourceFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PropertyDataSourceFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PropertyDataSourceFactory.java
index 60bf717..0826d7c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PropertyDataSourceFactory.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/PropertyDataSourceFactory.java
@@ -24,8 +24,8 @@ import org.apache.cayenne.ConfigurationException;
 import org.apache.cayenne.configuration.Constants;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.conn.DataSourceBuilder;
-import org.apache.cayenne.conn.PoolingDataSource;
+import org.apache.cayenne.datasource.DataSourceBuilder;
+import org.apache.cayenne.datasource.PoolingDataSource;
 import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.log.JdbcEventLogger;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/XMLPoolingDataSourceFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/XMLPoolingDataSourceFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/XMLPoolingDataSourceFactory.java
index a62a2d9..c333325 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/XMLPoolingDataSourceFactory.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/XMLPoolingDataSourceFactory.java
@@ -24,9 +24,9 @@ import org.apache.cayenne.ConfigurationException;
 import org.apache.cayenne.configuration.Constants;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.conn.DataSourceBuilder;
 import org.apache.cayenne.conn.DataSourceInfo;
-import org.apache.cayenne.conn.PoolingDataSource;
+import org.apache.cayenne.datasource.DataSourceBuilder;
+import org.apache.cayenne.datasource.PoolingDataSource;
 import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.log.JdbcEventLogger;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/conn/ConnectionWrapper.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/conn/ConnectionWrapper.java b/cayenne-server/src/main/java/org/apache/cayenne/conn/ConnectionWrapper.java
deleted file mode 100644
index 006a72a..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/conn/ConnectionWrapper.java
+++ /dev/null
@@ -1,749 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-
-package org.apache.cayenne.conn;
-
-import java.sql.Array;
-import java.sql.Blob;
-import java.sql.CallableStatement;
-import java.sql.Clob;
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.NClob;
-import java.sql.PreparedStatement;
-import java.sql.SQLClientInfoException;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.sql.SQLXML;
-import java.sql.Savepoint;
-import java.sql.Statement;
-import java.sql.Struct;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.Executor;
-
-/**
- * ConnectionWrapper is a <code>java.sql.Connection</code> implementation that wraps
- * another Connection, delegating method calls to this connection. It works in conjunction
- * with PooledConnectionImpl, to generate pool events, provide limited automated
- * reconnection functionality, etc.
- * 
- */
-public class ConnectionWrapper implements Connection {
-
-    private Connection connection;
-    private PooledConnectionImpl pooledConnection;
-    private long lastReconnected;
-    private int reconnectCount;
-
-    /**
-     * Fixes Sybase problems with autocommit. Used idea from Jonas
-     * org.objectweb.jonas.jdbc_xa.ConnectionImpl (http://www.objectweb.org/jonas/).
-     * <p>
-     * If problem is not the one that can be fixed by this patch, original exception is
-     * rethrown. If exception occurs when fixing the problem, new exception is thrown.
-     * </p>
-     */
-    static void sybaseAutoCommitPatch(Connection c, SQLException e, boolean autoCommit)
-            throws SQLException {
-
-        String s = e.getMessage().toLowerCase();
-        if (s.contains("set chained command not allowed")) {
-            c.commit();
-            c.setAutoCommit(autoCommit); // Shouldn't fail now.
-        }
-        else {
-            throw e;
-        }
-    }
-
-    /**
-     * Creates new ConnectionWrapper
-     */
-    public ConnectionWrapper(Connection connection, PooledConnectionImpl pooledConnection) {
-        this.connection = connection;
-        this.pooledConnection = pooledConnection;
-    }
-
-    protected void reconnect(SQLException exception) throws SQLException {
-
-        // if there was a relatively recent reconnect, just rethrow an error
-        // and retire itself. THIS WILL PREVENT RECONNECT LOOPS
-        if (reconnectCount > 0 && System.currentTimeMillis() - lastReconnected < 60000) {
-
-            retire(exception);
-            throw exception;
-        }
-
-        pooledConnection.reconnect();
-
-        // Pooled connection will wrap returned connection into
-        // another ConnectionWrapper.... lets get the real connection
-        // underneath...
-        Connection connection = pooledConnection.getConnection();
-        if (connection instanceof ConnectionWrapper) {
-            this.connection = ((ConnectionWrapper) connection).connection;
-        }
-        else {
-            this.connection = connection;
-        }
-
-        lastReconnected = System.currentTimeMillis();
-        reconnectCount++;
-    }
-
-    protected void retire(SQLException exception) {
-        // notify all the listeners....
-        pooledConnection.connectionErrorNotification(exception);
-    }
-
-    @Override
-    public void clearWarnings() throws SQLException {
-        try {
-            connection.clearWarnings();
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public void close() throws SQLException {
-        if (null != pooledConnection) {
-            pooledConnection.returnConnectionToThePool();
-        }
-        connection = null;
-        pooledConnection = null;
-    }
-
-    @Override
-    public void commit() throws SQLException {
-        try {
-            connection.commit();
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public Statement createStatement() throws SQLException {
-        try {
-            return connection.createStatement();
-        }
-        catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return createStatement();
-        }
-    }
-
-    @Override
-    public Statement createStatement(int resultSetType, int resultSetConcurrency)
-            throws SQLException {
-        try {
-            return connection.createStatement(resultSetType, resultSetConcurrency);
-        }
-        catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return createStatement(resultSetType, resultSetConcurrency);
-        }
-    }
-
-    @Override
-    public boolean getAutoCommit() throws SQLException {
-        try {
-            return connection.getAutoCommit();
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public String getCatalog() throws SQLException {
-        try {
-            return connection.getCatalog();
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public DatabaseMetaData getMetaData() throws SQLException {
-        try {
-            return connection.getMetaData();
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public int getTransactionIsolation() throws SQLException {
-        try {
-            return connection.getTransactionIsolation();
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public SQLWarning getWarnings() throws SQLException {
-        try {
-            return connection.getWarnings();
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public boolean isClosed() throws SQLException {
-        if (connection != null) {
-            try {
-                return connection.isClosed();
-            }
-            catch (SQLException sqlEx) {
-                retire(sqlEx);
-                throw sqlEx;
-            }
-        }
-        else
-            return true;
-    }
-
-    @Override
-    public boolean isReadOnly() throws SQLException {
-        try {
-            return connection.isReadOnly();
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public String nativeSQL(String sql) throws SQLException {
-        try {
-            return connection.nativeSQL(sql);
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public CallableStatement prepareCall(String sql) throws SQLException {
-        try {
-            return connection.prepareCall(sql);
-        }
-        catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return prepareCall(sql);
-        }
-    }
-
-    @Override
-    public CallableStatement prepareCall(
-            String sql,
-            int resultSetType,
-            int resultSetConcurrency) throws SQLException {
-        try {
-            return connection.prepareCall(sql, resultSetType, resultSetConcurrency);
-        }
-        catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return prepareCall(sql, resultSetType, resultSetConcurrency);
-        }
-    }
-
-    @Override
-    public PreparedStatement prepareStatement(String sql) throws SQLException {
-        try {
-            return connection.prepareStatement(sql);
-        }
-        catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return prepareStatement(sql);
-        }
-    }
-
-    @Override
-    public PreparedStatement prepareStatement(
-            String sql,
-            int resultSetType,
-            int resultSetConcurrency) throws SQLException {
-        try {
-            return connection.prepareStatement(sql, resultSetType, resultSetConcurrency);
-        }
-        catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return prepareStatement(sql, resultSetType, resultSetConcurrency);
-        }
-    }
-
-    @Override
-    public void rollback() throws SQLException {
-        try {
-            connection.rollback();
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public void setAutoCommit(boolean autoCommit) throws SQLException {
-        try {
-            connection.setAutoCommit(autoCommit);
-        }
-        catch (SQLException sqlEx) {
-
-            try {
-                // apply Sybase patch
-                sybaseAutoCommitPatch(connection, sqlEx, autoCommit);
-            }
-            catch (SQLException patchEx) {
-                retire(sqlEx);
-                throw sqlEx;
-            }
-        }
-    }
-
-    @Override
-    public void setCatalog(String catalog) throws SQLException {
-        try {
-            connection.setCatalog(catalog);
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public void setReadOnly(boolean readOnly) throws SQLException {
-        try {
-            connection.setReadOnly(readOnly);
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public void setTransactionIsolation(int level) throws SQLException {
-        try {
-            connection.setTransactionIsolation(level);
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public Map<String,Class<?>> getTypeMap() throws SQLException {
-        try {
-            return connection.getTypeMap();
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
-        try {
-            connection.setTypeMap(map);
-        }
-        catch (SQLException sqlEx) {
-            retire(sqlEx);
-            throw sqlEx;
-        }
-    }
-
-    @Override
-    public void setHoldability(int holdability) throws SQLException {
-        throw new java.lang.UnsupportedOperationException(
-                "Method setHoldability() not yet implemented.");
-    }
-
-    @Override
-    public int getHoldability() throws SQLException {
-        throw new java.lang.UnsupportedOperationException(
-                "Method getHoldability() not yet implemented.");
-    }
-
-    @Override
-    public Savepoint setSavepoint() throws SQLException {
-        throw new java.lang.UnsupportedOperationException(
-                "Method setSavepoint() not yet implemented.");
-    }
-
-    @Override
-    public Savepoint setSavepoint(String name) throws SQLException {
-        throw new java.lang.UnsupportedOperationException(
-                "Method setSavepoint() not yet implemented.");
-    }
-
-    @Override
-    public void rollback(Savepoint savepoint) throws SQLException {
-        throw new java.lang.UnsupportedOperationException(
-                "Method rollback() not yet implemented.");
-    }
-
-    @Override
-    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
-        throw new java.lang.UnsupportedOperationException(
-                "Method releaseSavepoint() not yet implemented.");
-    }
-
-    @Override
-    public Statement createStatement(
-            int resultSetType,
-            int resultSetConcurrency,
-            int resultSetHoldability) throws SQLException {
-        throw new java.lang.UnsupportedOperationException(
-                "Method createStatement() not yet implemented.");
-    }
-
-    @Override
-    public PreparedStatement prepareStatement(
-            String sql,
-            int resultSetType,
-            int resultSetConcurrency,
-            int resultSetHoldability) throws SQLException {
-        throw new java.lang.UnsupportedOperationException(
-                "Method prepareStatement() not yet implemented.");
-    }
-
-    @Override
-    public CallableStatement prepareCall(
-            String sql,
-            int resultSetType,
-            int resultSetConcurrency,
-            int resultSetHoldability) throws SQLException {
-        try {
-            return connection.prepareCall(
-                    sql,
-                    resultSetType,
-                    resultSetConcurrency,
-                    resultSetHoldability);
-        }
-        catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return prepareCall(
-                    sql,
-                    resultSetType,
-                    resultSetConcurrency,
-                    resultSetHoldability);
-        }
-    }
-    
-    @Override
-    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
-            throws SQLException {
-
-        try {
-            return connection.prepareStatement(sql, autoGeneratedKeys);
-        }
-        catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return prepareStatement(sql, autoGeneratedKeys);
-        }
-    }
-
-    @Override
-    public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
-            throws SQLException {
-        try {
-            return connection.prepareStatement(sql, columnIndexes);
-        }
-        catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return prepareStatement(sql, columnIndexes);
-        }
-    }
-
-    @Override
-    public PreparedStatement prepareStatement(String sql, String[] columnNames)
-            throws SQLException {
-        try {
-            return connection.prepareStatement(sql, columnNames);
-        }
-        catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return prepareStatement(sql, columnNames);
-        }
-    }
-
-    /**
-     * @since 3.0
-     */
-    @Override
-    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
-        try {
-            return connection.createArrayOf(typeName, elements);
-        }
-        catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return createArrayOf(typeName, elements);
-        }
-    }
-
-    /**
-     * @since 3.0
-     */
-    @Override
-    public Blob createBlob() throws SQLException {
-        try {
-            return connection.createBlob();
-        } catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return createBlob();
-        }
-    }
-
-    /**
-     * @since 3.0
-     */
-    @Override
-    public Clob createClob() throws SQLException {
-        try {
-            return connection.createClob();
-        } catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return createClob();
-        }
-    }
-
-    /**
-     * @since 3.0
-     */
-    @Override
-    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
-        try {
-            return connection.createStruct(typeName, attributes);
-        } catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return createStruct(typeName, attributes);
-        }
-    }
-
-    /**
-     * @since 3.0
-     */
-    @Override
-    public Properties getClientInfo() throws SQLException {
-        try {
-            return connection.getClientInfo();
-        } catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return getClientInfo();
-        }
-    }
-
-    /**
-     * @since 3.0
-     */
-    @Override
-    public String getClientInfo(String name) throws SQLException {
-        try {
-            return connection.getClientInfo(name);
-        } catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return getClientInfo(name);
-        }
-    }
-
-    /**
-     * @since 3.0
-     */
-    @Override
-    public boolean isValid(int timeout) throws SQLException {
-        try {
-            return connection.isValid(timeout);
-        } catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return isValid(timeout);
-        }
-    }
-
-    /**
-     * @since 3.0
-     */
-    @Override
-    public boolean isWrapperFor(Class<?> iface) throws SQLException {
-        // TODO: we can implement that now.
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @since 3.0
-     */
-    @Override
-    public <T> T unwrap(Class<T> iface) throws SQLException {
-        // TODO: we can implement that now.
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @since 3.0
-     */
-    @Override
-    public NClob createNClob() throws SQLException {
-        try {
-            return connection.createNClob();
-        } catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return createNClob();
-        }
-    }
-
-    /**
-     * @since 3.0
-     */
-    @Override
-    public SQLXML createSQLXML() throws SQLException {
-        try {
-            return connection.createSQLXML();
-        } catch (SQLException sqlEx) {
-
-            // reconnect has code to prevent loops
-            reconnect(sqlEx);
-            return createSQLXML();
-        }
-    }
-
-    /**
-     * @since 3.0
-     */
-    // JDBC 4 compatibility under Java 1.5
-    @Override
-    public void setClientInfo(Properties properties) throws SQLClientInfoException {
-        // TODO: we can implement that now.
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @since 3.0
-     */
-    // JDBC 4 compatibility under Java 1.5
-    @Override
-    public void setClientInfo(String name, String value) throws SQLClientInfoException {
-        // TODO: we can implement that now.
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @since 3.1
-     *
-     * JDBC 4.1 compatibility under Java 1.5
-     */
-    public void setSchema(String schema) throws SQLException {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @since 3.1
-     *
-     * JDBC 4.1 compatibility under Java 1.5
-     */
-    public String getSchema() throws SQLException {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @since 3.1
-     *
-     * JDBC 4.1 compatibility under Java 1.5
-     */
-    public void abort(Executor executor) throws SQLException {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @since 3.1
-     *
-     * JDBC 4.1 compatibility under Java 1.5
-     */
-    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @since 3.1
-     *
-     * JDBC 4.1 compatibility under Java 1.5
-     */
-    public int getNetworkTimeout() throws SQLException {
-        throw new UnsupportedOperationException();
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/conn/DataSourceBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/conn/DataSourceBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/conn/DataSourceBuilder.java
deleted file mode 100644
index 504a053..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/conn/DataSourceBuilder.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.conn;
-
-import java.sql.Driver;
-
-import javax.sql.DataSource;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.di.AdhocObjectFactory;
-import org.apache.cayenne.log.JdbcEventLogger;
-import org.apache.cayenne.log.NoopJdbcEventLogger;
-
-/**
- * A builder class that creates a default Cayenne implementation of a pooling
- * {@link DataSource}.
- * 
- * @since 4.0
- */
-public class DataSourceBuilder {
-
-	private AdhocObjectFactory objectFactory;
-	private JdbcEventLogger logger;
-	private String userName;
-	private String password;
-	private String driver;
-	private String url;
-	private PoolingDataSourceParameters poolParameters;
-
-	public static DataSourceBuilder builder(AdhocObjectFactory objectFactory, JdbcEventLogger logger) {
-		return new DataSourceBuilder(objectFactory, logger);
-	}
-
-	private DataSourceBuilder(AdhocObjectFactory objectFactory, JdbcEventLogger logger) {
-		this.objectFactory = objectFactory;
-		this.logger = logger;
-		this.logger = NoopJdbcEventLogger.getInstance();
-		this.poolParameters = new PoolingDataSourceParameters();
-
-		poolParameters.setMinConnections(1);
-		poolParameters.setMaxConnections(1);
-		poolParameters.setMaxQueueWaitTime(PoolingDataSource.MAX_QUEUE_WAIT_DEFAULT);
-	}
-
-	public DataSourceBuilder userName(String userName) {
-		this.userName = userName;
-		return this;
-	}
-
-	public DataSourceBuilder password(String password) {
-		this.password = password;
-		return this;
-	}
-
-	public DataSourceBuilder driver(String driver) {
-		this.driver = driver;
-		return this;
-	}
-
-	public DataSourceBuilder url(String url) {
-		this.url = url;
-		return this;
-	}
-
-	public DataSourceBuilder minConnections(int minConnections) {
-		poolParameters.setMinConnections(minConnections);
-		return this;
-	}
-
-	public DataSourceBuilder maxConnections(int maxConnections) {
-		poolParameters.setMaxConnections(maxConnections);
-		return this;
-	}
-
-	public DataSourceBuilder maxQueueWaitTime(long maxQueueWaitTime) {
-		poolParameters.setMaxQueueWaitTime(maxQueueWaitTime);
-		return this;
-	}
-
-	public DataSourceBuilder validationQuery(String validationQuery) {
-		poolParameters.setValidationQuery(validationQuery);
-		return this;
-	}
-
-	public DataSource build() {
-
-		// sanity checks...
-		if (poolParameters.getMaxConnections() < 0) {
-			throw new CayenneRuntimeException("Maximum number of connections can not be negative ("
-					+ poolParameters.getMaxConnections() + ").");
-		}
-
-		if (poolParameters.getMinConnections() < 0) {
-			throw new CayenneRuntimeException("Minimum number of connections can not be negative ("
-					+ poolParameters.getMinConnections() + ").");
-		}
-
-		if (poolParameters.getMinConnections() > poolParameters.getMaxConnections()) {
-			throw new CayenneRuntimeException("Minimum number of connections can not be bigger then maximum.");
-		}
-
-		DataSource nonPooling = buildNonPoolingDataSource();
-		return buildPoolingDataSource(new PooledConnectionFactory(nonPooling));
-	}
-
-	private DataSource buildNonPoolingDataSource() {
-		Driver driver = objectFactory.newInstance(Driver.class, this.driver);
-		DriverDataSource dataSource = new DriverDataSource(driver, url, userName, password);
-		dataSource.setLogger(logger);
-		return dataSource;
-	}
-
-	private DataSource buildPoolingDataSource(PooledConnectionFactory connectionFactory) {
-		PoolingDataSource poolDS;
-		try {
-			poolDS = new PoolingDataSource(connectionFactory, poolParameters);
-		} catch (Exception e) {
-			logger.logConnectFailure(e);
-			throw new CayenneRuntimeException("Error creating DataSource", e);
-		}
-
-		return new ManagedPoolingDataSource(poolDS);
-	}
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/conn/DriverDataSource.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/conn/DriverDataSource.java b/cayenne-server/src/main/java/org/apache/cayenne/conn/DriverDataSource.java
deleted file mode 100644
index 0cf9afc..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/conn/DriverDataSource.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-
-package org.apache.cayenne.conn;
-
-import java.io.PrintWriter;
-import java.sql.Connection;
-import java.sql.Driver;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
-import java.util.Properties;
-import java.util.logging.Logger;
-
-import javax.sql.DataSource;
-
-import org.apache.cayenne.log.JdbcEventLogger;
-import org.apache.cayenne.util.Util;
-
-/**
- * A non-pooling DataSource implementation wrapping a JDBC driver.
- * 
- */
-public class DriverDataSource implements DataSource {
-
-    protected Driver _driver;
-    protected String driverClassName;
-    
-    protected String connectionUrl;
-    protected String userName;
-    protected String password;
-
-    protected JdbcEventLogger logger;
-
-    /**
-     * Loads JDBC driver using current thread class loader.
-     * 
-     * @since 3.0
-     * @deprecated since 4.0 as class loading should not happen here.
-     */
-    @Deprecated
-    private static Driver loadDriver(String driverClassName) throws SQLException {
-
-        Class<?> driverClass;
-        try {
-            driverClass = Util.getJavaClass(driverClassName);
-        }
-        catch (Exception ex) {
-            throw new SQLException("Can not load JDBC driver named '"
-                    + driverClassName
-                    + "': "
-                    + ex.getMessage());
-        }
-
-        try {
-            return (Driver) driverClass.newInstance();
-        }
-        catch (Exception ex) {
-            throw new SQLException("Error instantiating driver '"
-                    + driverClassName
-                    + "': "
-                    + ex.getMessage());
-        }
-    }
-
-    /**
-     * Creates a new DriverDataSource. If "driverClassName" is null, DriverDataSource will
-     * consult DriverManager for a registered driver for the given URL. So when specifying
-     * null, a user must take care of registering the driver. "connectionUrl" on the other
-     * hand must NOT be null.
-     */
-    public DriverDataSource(String driverClassName, String connectionUrl) {
-        this(driverClassName, connectionUrl, null, null);
-    }
-
-    /**
-     * Creates a new DriverDataSource. If "driverClassName" is null, DriverDataSource will
-     * consult DriverManager for a registered driver for the given URL. So when specifying
-     * null, a user must take care of registering the driver. "connectionUrl" on the other
-     * hand must NOT be null.
-     * 
-     * @since 3.0
-     */
-    public DriverDataSource(String driverClassName, String connectionUrl,
-            String userName, String password) {
-
-        setDriverClassName(driverClassName);
-
-        this.connectionUrl = connectionUrl;
-        this.userName = userName;
-        this.password = password;
-    }
-
-    /**
-     * Creates a new DriverDataSource wrapping a given Driver. If "driver" is null,
-     * DriverDataSource will consult DriverManager for a registered driver for the given
-     * URL. So when specifying null, a user must take care of registering the driver.
-     * "connectionUrl" on the other hand must NOT be null.
-     * 
-     * @since 1.1
-     */
-    public DriverDataSource(Driver driver, String connectionUrl, String userName,
-            String password) {
-
-        this._driver = driver;
-        this.driverClassName = driver.getClass().getName();
-        this.connectionUrl = connectionUrl;
-        this.userName = userName;
-        this.password = password;
-    }
-
-    /**
-     * Returns a new database connection, using preconfigured data to locate the database
-     * and obtain a connection.
-     */
-    public Connection getConnection() throws SQLException {
-        // login with internal credentials
-        return getConnection(userName, password);
-    }
-
-    /**
-     * Returns a new database connection using provided credentials to login to the
-     * database.
-     */
-    public Connection getConnection(String userName, String password) throws SQLException {
-        try {
-            if (logger != null) {
-                logger.logConnect(connectionUrl, userName, password);
-            }
-
-            Connection c = null;
-
-            if (getDriver() == null) {
-                c = DriverManager.getConnection(connectionUrl, userName, password);
-            }
-            else {
-                Properties connectProperties = new Properties();
-
-                if (userName != null) {
-                    connectProperties.put("user", userName);
-                }
-
-                if (password != null) {
-                    connectProperties.put("password", password);
-                }
-                c = getDriver().connect(connectionUrl, connectProperties);
-            }
-
-            // some drivers (Oracle) return null connections instead of throwing
-            // an exception... fix it here
-
-            if (c == null) {
-                throw new SQLException("Can't establish connection: " + connectionUrl);
-            }
-
-            if (logger != null) {
-                logger.logConnectSuccess();
-            }
-
-            return c;
-        }
-        catch (SQLException sqlex) {
-            if (logger != null) {
-                logger.logConnectFailure(sqlex);
-            }
-
-            throw sqlex;
-        }
-    }
-
-    public int getLoginTimeout() throws SQLException {
-        return -1;
-    }
-
-    public void setLoginTimeout(int seconds) throws SQLException {
-        // noop
-    }
-
-    public PrintWriter getLogWriter() throws SQLException {
-        return DriverManager.getLogWriter();
-    }
-
-    public void setLogWriter(PrintWriter out) throws SQLException {
-        DriverManager.setLogWriter(out);
-    }
-
-    public JdbcEventLogger getLogger() {
-        return logger;
-    }
-
-    public void setLogger(JdbcEventLogger delegate) {
-        logger = delegate;
-    }
-
-    /**
-     * @since 3.0
-     */
-    public String getConnectionUrl() {
-        return connectionUrl;
-    }
-
-    /**
-     * @since 3.0
-     */
-    public void setConnectionUrl(String connectionUrl) {
-        this.connectionUrl = connectionUrl;
-    }
-
-    /**
-     * @since 3.0
-     */
-    public String getPassword() {
-        return password;
-    }
-
-    /**
-     * @since 3.0
-     */
-    public void setPassword(String password) {
-        this.password = password;
-    }
-
-    /**
-     * @since 3.0
-     */
-    public String getUserName() {
-        return userName;
-    }
-
-    /**
-     * @since 3.0
-     */
-    public void setUserName(String userName) {
-        this.userName = userName;
-    }
-
-    public String getDriverClassName() {
-        return driverClassName;
-    }
-
-    public void setDriverClassName(String driverClassName) {
-        if (!Util.nullSafeEquals(getDriverClassName(), driverClassName)) {
-            this.driverClassName = driverClassName;
-            this._driver = null; // force reload
-        }
-    }
-    
-    /**
-     * Lazily instantiate the driver class to prevent errors for connections that are never opened
-     */
-    private Driver getDriver() throws SQLException {
-        if (_driver == null && driverClassName != null) {
-            _driver = loadDriver(driverClassName);
-        }
-        return _driver;
-    }
-    
-    /**
-     * @since 3.0
-     */
-    // JDBC 4 compatibility under Java 1.5
-    public boolean isWrapperFor(Class<?> iface) throws SQLException {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @since 3.0
-     */
-    // JDBC 4 compatibility under Java 1.5
-    public <T> T unwrap(Class<T> iface) throws SQLException {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @since 3.1
-     *
-     * JDBC 4.1 compatibility under Java 1.5
-     */
-    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
-        throw new UnsupportedOperationException();
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/conn/ManagedPoolingDataSource.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/conn/ManagedPoolingDataSource.java b/cayenne-server/src/main/java/org/apache/cayenne/conn/ManagedPoolingDataSource.java
deleted file mode 100644
index 357c3e0..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/conn/ManagedPoolingDataSource.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.conn;
-
-import java.io.PrintWriter;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
-import java.util.logging.Logger;
-
-import javax.sql.DataSource;
-
-import org.apache.cayenne.di.ScopeEventListener;
-
-/**
- * A wrapper for {@link PoolingDataSourceManager} that manages the underlying
- * connection pool size, shrinking it if needed.
- * 
- * @since 4.0
- */
-public class ManagedPoolingDataSource implements DataSource, ScopeEventListener {
-
-	private PoolingDataSourceManager dataSourceManager;
-	private PoolingDataSource dataSource;
-
-	public ManagedPoolingDataSource(PoolingDataSource dataSource) {
-
-		this.dataSource = dataSource;
-		this.dataSourceManager = new PoolingDataSourceManager();
-
-		dataSourceManager.start();
-	}
-
-	@Override
-	public void beforeScopeEnd() {
-		dataSourceManager.shouldStop();
-	}
-
-	@Override
-	public Connection getConnection() throws SQLException {
-		return dataSource.getConnection();
-	}
-
-	@Override
-	public Connection getConnection(String username, String password) throws SQLException {
-		return dataSource.getConnection(username, password);
-	}
-
-	@Override
-	public PrintWriter getLogWriter() throws SQLException {
-		return dataSource.getLogWriter();
-	}
-
-	@Override
-	public int getLoginTimeout() throws SQLException {
-		return dataSource.getLoginTimeout();
-	}
-
-	@Override
-	public boolean isWrapperFor(Class<?> iface) throws SQLException {
-		return (ManagedPoolingDataSource.class.equals(iface)) ? true : dataSource.isWrapperFor(iface);
-	}
-
-	@Override
-	public void setLogWriter(PrintWriter arg0) throws SQLException {
-		dataSource.setLogWriter(arg0);
-	}
-
-	@Override
-	public void setLoginTimeout(int arg0) throws SQLException {
-		dataSource.setLoginTimeout(arg0);
-	}
-
-	@SuppressWarnings("unchecked")
-	@Override
-	public <T> T unwrap(Class<T> iface) throws SQLException {
-		return ManagedPoolingDataSource.class.equals(iface) ? (T) this : dataSource.unwrap(iface);
-	}
-
-	// JDBC 4.1 compatibility under Java 1.6 and newer
-	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
-		throw new UnsupportedOperationException();
-	}
-
-	boolean shouldShrinkPool() {
-		int unused = dataSource.getCurrentlyUnused();
-		int used = dataSource.getCurrentlyInUse();
-		int total = unused + used;
-		int median = dataSource.getMinConnections() + 1
-				+ (dataSource.getMaxConnections() - dataSource.getMinConnections()) / 2;
-
-		return unused > 0 && total > median;
-	}
-
-	class PoolingDataSourceManager extends Thread {
-
-		private volatile boolean shouldStop;
-
-		PoolingDataSourceManager() {
-			setName("PoolManagerCleanup-" + dataSource.hashCode());
-			setDaemon(true);
-			this.shouldStop = false;
-		}
-
-		public void shouldStop() {
-			shouldStop = true;
-			interrupt();
-		}
-
-		@Override
-		public void run() {
-			while (true) {
-
-				try {
-					// don't do it too often
-					Thread.sleep(600000);
-				} catch (InterruptedException iex) {
-					// ignore...
-				}
-
-				synchronized (dataSource) {
-
-					// simple pool management - close one connection if the
-					// count is
-					// above median and there are any idle connections.
-
-					if (shouldStop) {
-						break;
-					}
-
-					if (shouldShrinkPool()) {
-						dataSource.shrinkPool(1);
-					}
-				}
-			}
-		}
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/conn/PooledConnectionFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/conn/PooledConnectionFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/conn/PooledConnectionFactory.java
deleted file mode 100644
index 2ebfeab..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/conn/PooledConnectionFactory.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-
-package org.apache.cayenne.conn;
-
-import java.io.PrintWriter;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
-import java.util.logging.Logger;
-
-import javax.sql.ConnectionPoolDataSource;
-import javax.sql.DataSource;
-import javax.sql.PooledConnection;
-
-/**
- * A {@link ConnectionPoolDataSource} implementation.
- * <p>
- * It is implemented as a wrapper around a non-pooled data source object.
- * Delegates all method calls except for "getPooledConnection" to the underlying
- * DataSource.
- * 
- * @since 4.0
- */
-public class PooledConnectionFactory implements ConnectionPoolDataSource {
-
-	private DataSource nonPooledDatasource;
-
-	public PooledConnectionFactory(DataSource nonPooledDatasource) {
-		this.nonPooledDatasource = nonPooledDatasource;
-	}
-
-	public PooledConnectionFactory(String jdbcDriver, String connectionUrl) throws SQLException {
-		nonPooledDatasource = new DriverDataSource(jdbcDriver, connectionUrl);
-	}
-
-	@Override
-	public int getLoginTimeout() throws SQLException {
-		return nonPooledDatasource.getLoginTimeout();
-	}
-
-	@Override
-	public void setLoginTimeout(int seconds) throws SQLException {
-		nonPooledDatasource.setLoginTimeout(seconds);
-	}
-
-	@Override
-	public PrintWriter getLogWriter() throws SQLException {
-		return nonPooledDatasource.getLogWriter();
-	}
-
-	@Override
-	public void setLogWriter(PrintWriter out) throws SQLException {
-		nonPooledDatasource.setLogWriter(out);
-	}
-
-	@Override
-	public PooledConnection getPooledConnection() throws SQLException {
-		return new PooledConnectionImpl(nonPooledDatasource, null, null);
-	}
-
-	@Override
-	public PooledConnection getPooledConnection(String user, String password) throws SQLException {
-		return new PooledConnectionImpl(nonPooledDatasource, user, password);
-	}
-
-	/**
-	 * @since 3.1
-	 *
-	 *        JDBC 4.1 compatibility under Java 1.7
-	 */
-	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
-		throw new UnsupportedOperationException();
-	}
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/conn/PooledConnectionImpl.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/conn/PooledConnectionImpl.java b/cayenne-server/src/main/java/org/apache/cayenne/conn/PooledConnectionImpl.java
deleted file mode 100644
index eb327ff..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/conn/PooledConnectionImpl.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-
-package org.apache.cayenne.conn;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import javax.sql.ConnectionEvent;
-import javax.sql.ConnectionEventListener;
-import javax.sql.DataSource;
-import javax.sql.PooledConnection;
-import javax.sql.StatementEventListener;
-
-/**
- * PooledConnectionImpl is an implementation of a pooling wrapper for the
- * database connection as per JDBC3 spec. Most of the modern JDBC drivers should
- * have its own implementation that may be used instead of this class.
- */
-public class PooledConnectionImpl implements PooledConnection {
-
-	private Connection connectionObj;
-	private List<ConnectionEventListener> connectionEventListeners;
-	private boolean hadErrors;
-	private DataSource dataSource;
-	private String userName;
-	private String password;
-
-	public PooledConnectionImpl(DataSource dataSource, String userName, String password) {
-
-		// TODO: maybe remove synchronization and use
-		// FastArrayList from commons-collections? After
-		// all the only listener is usually pool manager.
-		this.connectionEventListeners = Collections.synchronizedList(new ArrayList<ConnectionEventListener>(10));
-
-		this.dataSource = dataSource;
-		this.userName = userName;
-		this.password = password;
-	}
-
-	public void reconnect() throws SQLException {
-		if (connectionObj != null) {
-			try {
-				connectionObj.close();
-			} catch (SQLException ex) {
-				// ignore exception, since connection is expected
-				// to be in a bad state
-			} finally {
-				connectionObj = null;
-			}
-		}
-
-		connectionObj = (userName != null) ? dataSource.getConnection(userName, password) : dataSource.getConnection();
-	}
-
-	@Override
-	public void addConnectionEventListener(ConnectionEventListener listener) {
-		synchronized (connectionEventListeners) {
-			if (!connectionEventListeners.contains(listener)) {
-				connectionEventListeners.add(listener);
-			}
-		}
-	}
-
-	@Override
-	public void removeConnectionEventListener(ConnectionEventListener listener) {
-		synchronized (connectionEventListeners) {
-			connectionEventListeners.remove(listener);
-		}
-	}
-
-	@Override
-	public void close() throws SQLException {
-
-		synchronized (connectionEventListeners) {
-			// remove all listeners
-			connectionEventListeners.clear();
-		}
-
-		if (connectionObj != null) {
-			try {
-				connectionObj.close();
-			} finally {
-				connectionObj = null;
-			}
-		}
-	}
-
-	@Override
-	public Connection getConnection() throws SQLException {
-		if (connectionObj == null) {
-			reconnect();
-		}
-
-		// set autocommit to false to return connection
-		// always in consistent state
-		if (!connectionObj.getAutoCommit()) {
-
-			try {
-				connectionObj.setAutoCommit(true);
-			} catch (SQLException sqlEx) {
-				// try applying Sybase patch
-				ConnectionWrapper.sybaseAutoCommitPatch(connectionObj, sqlEx, true);
-			}
-		}
-
-		connectionObj.clearWarnings();
-		return new ConnectionWrapper(connectionObj, this);
-	}
-
-	protected void returnConnectionToThePool() throws SQLException {
-		// do not return to pool bad connections
-		if (hadErrors)
-			close();
-		else
-			// notify the listeners that connection is no longer used by
-			// application...
-			this.connectionClosedNotification();
-	}
-
-	/**
-	 * This method creates and sents an event to listeners when an error occurs
-	 * in the underlying connection. Listeners can have special logic to analyze
-	 * the error and do things like closing this PooledConnection (if the error
-	 * is fatal), etc...
-	 */
-	public void connectionErrorNotification(SQLException exception) {
-		// hint for later to avoid returning bad connections to the pool
-		hadErrors = true;
-
-		synchronized (connectionEventListeners) {
-			if (connectionEventListeners.isEmpty()) {
-				return;
-			}
-
-			ConnectionEvent closedEvent = new ConnectionEvent(this, exception);
-			for (ConnectionEventListener nextListener : connectionEventListeners) {
-				nextListener.connectionErrorOccurred(closedEvent);
-			}
-		}
-	}
-
-	/**
-	 * Creates and sends an event to listeners when a user closes
-	 * java.sql.Connection object belonging to this PooledConnection.
-	 */
-	protected void connectionClosedNotification() {
-		synchronized (connectionEventListeners) {
-			if (connectionEventListeners.size() == 0) {
-				return;
-			}
-
-			ConnectionEvent closedEvent = new ConnectionEvent(this);
-
-			for (ConnectionEventListener nextListener : connectionEventListeners) {
-				nextListener.connectionClosed(closedEvent);
-			}
-		}
-	}
-
-	/**
-	 * @since 3.0
-	 */
-	@Override
-	public void addStatementEventListener(StatementEventListener listener) {
-		throw new UnsupportedOperationException("Statement events are unsupported");
-	}
-
-	/**
-	 * @since 3.0
-	 */
-	@Override
-	public void removeStatementEventListener(StatementEventListener listener) {
-		throw new UnsupportedOperationException("Statement events are unsupported");
-	}
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/conn/PoolingDataSource.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/conn/PoolingDataSource.java b/cayenne-server/src/main/java/org/apache/cayenne/conn/PoolingDataSource.java
deleted file mode 100644
index cccf905..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/conn/PoolingDataSource.java
+++ /dev/null
@@ -1,471 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-
-package org.apache.cayenne.conn;
-
-import java.io.PrintWriter;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
-import java.sql.Statement;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.logging.Logger;
-
-import javax.sql.ConnectionEvent;
-import javax.sql.ConnectionEventListener;
-import javax.sql.ConnectionPoolDataSource;
-import javax.sql.DataSource;
-import javax.sql.PooledConnection;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.di.ScopeEventListener;
-
-/**
- * A {@link DataSource} with a pool of connections, that can automatically grow
- * to the max size as more connections are requested.
- * 
- * @since 4.0
- */
-public class PoolingDataSource implements ScopeEventListener, DataSource, ConnectionEventListener {
-
-	/**
-	 * Defines a maximum time in milliseconds that a connection request could
-	 * wait in the connection queue. After this period expires, an exception
-	 * will be thrown in the calling method.
-	 */
-	public static final int MAX_QUEUE_WAIT_DEFAULT = 20000;
-
-	/**
-	 * An exception indicating that a connection request waiting in the queue
-	 * timed out and was unable to obtain a connection.
-	 */
-	public static class ConnectionUnavailableException extends SQLException {
-		private static final long serialVersionUID = 1063973806941023165L;
-
-		public ConnectionUnavailableException(String message) {
-			super(message);
-		}
-	}
-
-	protected ConnectionPoolDataSource pooledConnectionFactory;
-
-	private int minConnections;
-	private int maxConnections;
-	private long maxQueueWaitTime;
-	private String validationQuery;
-
-	private List<PooledConnection> unusedPool;
-	private List<PooledConnection> usedPool;
-	private boolean shuttingDown;
-
-	/**
-	 * Creates new PoolManager with the specified policy for connection pooling
-	 * and a ConnectionPoolDataSource object.
-	 * 
-	 * @param poolDataSource
-	 *            data source for pooled connections
-	 * @param minCons
-	 *            Non-negative integer that specifies a minimum number of open
-	 *            connections to keep in the pool at all times
-	 * @param maxCons
-	 *            Non-negative integer that specifies maximum number of
-	 *            simultaneously open connections
-	 * @throws SQLException
-	 *             if pool manager can not be created.
-	 * @since 4.0
-	 */
-	public PoolingDataSource(ConnectionPoolDataSource poolDataSource, PoolingDataSourceParameters parameters)
-			throws SQLException {
-
-		this.pooledConnectionFactory = poolDataSource;
-
-		// clone parameters to keep DataSource immutable
-		this.minConnections = parameters.getMinConnections();
-		this.maxConnections = parameters.getMaxConnections();
-		this.maxQueueWaitTime = parameters.getMaxQueueWaitTime();
-		this.validationQuery = parameters.getValidationQuery();
-
-		// init pool... use linked lists to use the queue in the FIFO manner
-		this.usedPool = new LinkedList<PooledConnection>();
-		this.unusedPool = new LinkedList<PooledConnection>();
-		growPool(minConnections);
-	}
-
-	/**
-	 * Creates and returns new PooledConnection object, adding itself as a
-	 * listener for connection events.
-	 */
-	protected PooledConnection newPooledConnection() throws SQLException {
-		PooledConnection connection = pooledConnectionFactory.getPooledConnection();
-		connection.addConnectionEventListener(this);
-		return connection;
-	}
-
-	/**
-	 * Shuts down the pool, closing all open connections. This is an
-	 * implementation of {@link ScopeEventListener}.
-	 * 
-	 * @since 3.1
-	 */
-	@Override
-	public synchronized void beforeScopeEnd() {
-		try {
-
-			// using boolean variable instead of locking PoolManager instance
-			// due to possible deadlock during shutdown when one of connections
-			// locks its event listeners list trying to invoke locked
-			// PoolManager's listener methods
-			shuttingDown = true;
-
-			ListIterator<PooledConnection> unusedIterator = unusedPool.listIterator();
-			while (unusedIterator.hasNext()) {
-				PooledConnection con = unusedIterator.next();
-				// close connection
-				con.close();
-				// remove connection from the list
-				unusedIterator.remove();
-			}
-
-			// clean used connections
-			ListIterator<PooledConnection> usedIterator = usedPool.listIterator();
-			while (usedIterator.hasNext()) {
-				PooledConnection con = usedIterator.next();
-				// stop listening for connection events
-				con.removeConnectionEventListener(this);
-				// close connection
-				con.close();
-				// remove connection from the list
-				usedIterator.remove();
-			}
-		} catch (SQLException e) {
-			throw new CayenneRuntimeException("Error while shutting down");
-		}
-	}
-
-	/**
-	 * @return true if at least one more connection can be added to the pool.
-	 */
-	protected synchronized boolean canGrowPool() {
-		return getPoolSize() < maxConnections;
-	}
-
-	/**
-	 * Increases connection pool by the specified number of connections.
-	 * 
-	 * @return the actual number of created connections.
-	 * @throws SQLException
-	 *             if an error happens when creating a new connection.
-	 */
-	protected synchronized int growPool(int addConnections) throws SQLException {
-
-		int i = 0;
-		int startPoolSize = getPoolSize();
-		for (; i < addConnections && startPoolSize + i < maxConnections; i++) {
-			PooledConnection newConnection = newPooledConnection();
-			unusedPool.add(newConnection);
-		}
-
-		return i;
-	}
-
-	public synchronized void shrinkPool(int closeConnections) {
-		int idleSize = unusedPool.size();
-		for (int i = 0; i < closeConnections && i < idleSize; i++) {
-			PooledConnection con = unusedPool.remove(i);
-
-			try {
-				con.close();
-			} catch (SQLException ex) {
-				// ignore
-			}
-		}
-	}
-
-	public String getValidationQuery() {
-		return validationQuery;
-	}
-
-	/**
-	 * Returns maximum number of connections this pool can keep. This parameter
-	 * when configured allows to limit the number of simultaneously open
-	 * connections.
-	 */
-	public int getMaxConnections() {
-		return maxConnections;
-	}
-
-	/**
-	 * Returns the absolute minimum number of connections allowed in this pool
-	 * at any moment in time.
-	 */
-	public int getMinConnections() {
-		return minConnections;
-	}
-
-	/**
-	 * Returns current number of connections.
-	 */
-	public synchronized int getPoolSize() {
-		return usedPool.size() + unusedPool.size();
-	}
-
-	/**
-	 * Returns the number of connections obtained via this DataSource that are
-	 * currently in use by the DataSource clients.
-	 */
-	public synchronized int getCurrentlyInUse() {
-		return usedPool.size();
-	}
-
-	/**
-	 * Returns the number of connections maintained in the pool that are
-	 * currently not used by any clients and are available immediately via
-	 * <code>getConnection</code> method.
-	 */
-	public synchronized int getCurrentlyUnused() {
-		return unusedPool.size();
-	}
-
-	/**
-	 * Returns connection from the pool using internal values of user name and
-	 * password.
-	 */
-	@Override
-	public synchronized Connection getConnection() throws SQLException {
-		if (shuttingDown) {
-			throw new SQLException("Pool manager is shutting down.");
-		}
-
-		PooledConnection pooledConnection = uncheckPooledConnection();
-
-		try {
-			return uncheckAndValidateConnection(pooledConnection);
-		} catch (SQLException ex) {
-
-			try {
-				pooledConnection.close();
-			} catch (SQLException ignored) {
-			}
-
-			// do one reconnect attempt...
-			pooledConnection = uncheckPooledConnection();
-			try {
-				return uncheckAndValidateConnection(pooledConnection);
-			} catch (SQLException reconnectEx) {
-				try {
-					pooledConnection.close();
-				} catch (SQLException ignored) {
-				}
-
-				throw reconnectEx;
-			}
-		}
-	}
-
-	/**
-	 * Returns connection from the pool.
-	 */
-	@Override
-	public synchronized Connection getConnection(String userName, String password) throws SQLException {
-		throw new UnsupportedOperationException(
-				"Connections for a specific user are not supported by the pooled DataSource");
-	}
-
-	private Connection uncheckConnection(PooledConnection pooledConnection) throws SQLException {
-		Connection c = pooledConnection.getConnection();
-
-		// only do that on successfully unchecked connection...
-		usedPool.add(pooledConnection);
-		return c;
-	}
-
-	private Connection uncheckAndValidateConnection(PooledConnection pooledConnection) throws SQLException {
-		Connection c = uncheckConnection(pooledConnection);
-
-		if (validationQuery != null) {
-
-			Statement statement = c.createStatement();
-			try {
-				ResultSet rs = statement.executeQuery(validationQuery);
-				try {
-
-					if (!rs.next()) {
-						throw new SQLException("Connection validation failed, no result for query: " + validationQuery);
-					}
-
-				} finally {
-					rs.close();
-				}
-			} finally {
-				statement.close();
-			}
-		}
-
-		return c;
-	}
-
-	private PooledConnection uncheckPooledConnection() throws SQLException {
-		// wait for returned connections or the maintenance thread
-		// to bump the pool size...
-
-		if (unusedPool.size() == 0) {
-
-			// first try to open a new connection
-			if (canGrowPool()) {
-				return newPooledConnection();
-			}
-
-			// can't open no more... will have to wait for others to return a
-			// connection
-
-			// note that if we were woken up
-			// before the full wait period expired, and no connections are
-			// available yet, go back to sleep. Otherwise we don't give a
-			// maintenance
-			// thread a chance to increase pool size
-			long waitTill = System.currentTimeMillis() + maxQueueWaitTime;
-
-			do {
-				try {
-					wait(maxQueueWaitTime);
-				} catch (InterruptedException iex) {
-					// ignoring
-				}
-
-			} while (unusedPool.size() == 0 && (maxQueueWaitTime == 0 || waitTill > System.currentTimeMillis()));
-
-			if (unusedPool.size() == 0) {
-				throw new ConnectionUnavailableException(
-						"Can't obtain connection. Request timed out. Total used connections: " + usedPool.size());
-			}
-		}
-
-		// get first connection... lets cycle them in FIFO manner
-		return unusedPool.remove(0);
-	}
-
-	@Override
-	public int getLoginTimeout() throws java.sql.SQLException {
-		return pooledConnectionFactory.getLoginTimeout();
-	}
-
-	@Override
-	public void setLoginTimeout(int seconds) throws java.sql.SQLException {
-		pooledConnectionFactory.setLoginTimeout(seconds);
-	}
-
-	@Override
-	public PrintWriter getLogWriter() throws java.sql.SQLException {
-		return pooledConnectionFactory.getLogWriter();
-	}
-
-	@Override
-	public void setLogWriter(PrintWriter out) throws java.sql.SQLException {
-		pooledConnectionFactory.setLogWriter(out);
-	}
-
-	/**
-	 * Returns closed connection to the pool.
-	 */
-	@Override
-	public synchronized void connectionClosed(ConnectionEvent event) {
-
-		if (shuttingDown) {
-			return;
-		}
-
-		// return connection to the pool
-		PooledConnection closedConn = (PooledConnection) event.getSource();
-
-		// remove this connection from the list of connections
-		// managed by this pool...
-		int usedInd = usedPool.indexOf(closedConn);
-		if (usedInd >= 0) {
-			usedPool.remove(usedInd);
-			unusedPool.add(closedConn);
-
-			// notify threads waiting for connections
-			notifyAll();
-		}
-		// else ....
-		// other possibility is that this is a bad connection, so just ignore
-		// its closing
-		// event,
-		// since it was unregistered in "connectionErrorOccurred"
-	}
-
-	/**
-	 * Removes connection with an error from the pool. This method is called by
-	 * PoolManager connections on connection errors to notify PoolManager that
-	 * connection is in invalid state.
-	 */
-	@Override
-	public synchronized void connectionErrorOccurred(ConnectionEvent event) {
-
-		if (shuttingDown) {
-			return;
-		}
-
-		// later on we should analyze the error to see if this
-		// is fatal... right now just kill this PooledConnection
-
-		PooledConnection errorSrc = (PooledConnection) event.getSource();
-
-		// remove this connection from the list of connections
-		// managed by this pool...
-
-		int usedInd = usedPool.indexOf(errorSrc);
-		if (usedInd >= 0) {
-			usedPool.remove(usedInd);
-		} else {
-			int unusedInd = unusedPool.indexOf(errorSrc);
-			if (unusedInd >= 0) {
-				unusedPool.remove(unusedInd);
-			}
-		}
-
-		// do not close connection,
-		// let the code that catches the exception handle it
-		// ....
-	}
-
-	@Override
-	public boolean isWrapperFor(Class<?> iface) throws SQLException {
-		return PoolingDataSource.class.equals(iface);
-	}
-
-	@SuppressWarnings("unchecked")
-	@Override
-	public <T> T unwrap(Class<T> iface) throws SQLException {
-		if (PoolingDataSource.class.equals(iface)) {
-			return (T) this;
-		}
-
-		throw new SQLException("Not a wrapper for " + iface);
-	}
-
-	// JDBC 4.1 compatibility under Java <= 1.6
-	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
-		throw new UnsupportedOperationException();
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/conn/PoolingDataSourceParameters.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/conn/PoolingDataSourceParameters.java b/cayenne-server/src/main/java/org/apache/cayenne/conn/PoolingDataSourceParameters.java
deleted file mode 100644
index 3066553..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/conn/PoolingDataSourceParameters.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.conn;
-
-/**
- * A collection of pooling parameters used by {@link PoolingDataSource}.
- * 
- * @since 4.0
- */
-public class PoolingDataSourceParameters {
-
-	private String validationQuery;
-	private int minConnections;
-	private int maxConnections;
-	private long maxQueueWaitTime;
-
-	public int getMinConnections() {
-		return minConnections;
-	}
-
-	public void setMinConnections(int minConnections) {
-		this.minConnections = minConnections;
-	}
-
-	public int getMaxConnections() {
-		return maxConnections;
-	}
-
-	public void setMaxConnections(int maxConnections) {
-		this.maxConnections = maxConnections;
-	}
-
-	public long getMaxQueueWaitTime() {
-		return maxQueueWaitTime;
-	}
-
-	public void setMaxQueueWaitTime(long maxQueueWaitTime) {
-		this.maxQueueWaitTime = maxQueueWaitTime;
-	}
-
-	public String getValidationQuery() {
-		return validationQuery;
-	}
-
-	public void setValidationQuery(String validationQuery) {
-		this.validationQuery = validationQuery;
-	}
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/conn/package.html
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/conn/package.html b/cayenne-server/src/main/java/org/apache/cayenne/conn/package.html
deleted file mode 100644
index 4fe2394..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/conn/package.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
-   Licensed to the Apache Software Foundation (ASF) under one
-   or more contributor license agreements.  See the NOTICE file
-   distributed with this work for additional information
-   regarding copyright ownership.  The ASF licenses this file
-   to you under the Apache License, Version 2.0 (the
-   "License"); you may not use this file except in compliance
-   with the License.  You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing,
-   software distributed under the License is distributed on an
-   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-   KIND, either express or implied.  See the License for the
-   specific language governing permissions and limitations
-   under the License.
--->
-<html>
-<body>
-Provides full DataSource implementation. Allows to wrap JDBC
-drivers into a DataSource-compatible classes. Adds features like connection 
-pooling, etc. Can be used as a DataSource implementation with application
-servers, web containers, etc.
-</body>
-</html>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/datasource/BadValidationQueryException.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/datasource/BadValidationQueryException.java b/cayenne-server/src/main/java/org/apache/cayenne/datasource/BadValidationQueryException.java
new file mode 100644
index 0000000..9f7e74b
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/datasource/BadValidationQueryException.java
@@ -0,0 +1,41 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.datasource;
+
+import java.sql.SQLException;
+
+/**
+ * Thrown when the pool fails to validate a fresh connection that is known to be
+ * in a good state.
+ * 
+ * @since 4.0
+ */
+public class BadValidationQueryException extends SQLException {
+
+	private static final long serialVersionUID = -3690715196865727679L;
+
+	public BadValidationQueryException(String message) {
+		super(message);
+	}
+
+	public BadValidationQueryException(String message, Throwable cause) {
+		super(message, cause);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/517df07b/cayenne-server/src/main/java/org/apache/cayenne/datasource/DataSourceBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/datasource/DataSourceBuilder.java b/cayenne-server/src/main/java/org/apache/cayenne/datasource/DataSourceBuilder.java
new file mode 100644
index 0000000..e02f8eb
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/datasource/DataSourceBuilder.java
@@ -0,0 +1,135 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.datasource;
+
+import java.sql.Driver;
+
+import javax.sql.DataSource;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.di.AdhocObjectFactory;
+import org.apache.cayenne.log.JdbcEventLogger;
+import org.apache.cayenne.log.NoopJdbcEventLogger;
+
+/**
+ * A builder class that creates a default Cayenne implementation of a pooling
+ * {@link DataSource}.
+ * 
+ * @since 4.0
+ */
+public class DataSourceBuilder {
+
+	private AdhocObjectFactory objectFactory;
+	private JdbcEventLogger logger;
+	private String userName;
+	private String password;
+	private String driver;
+	private String url;
+	private PoolingDataSourceParameters poolParameters;
+
+	public static DataSourceBuilder builder(AdhocObjectFactory objectFactory, JdbcEventLogger logger) {
+		return new DataSourceBuilder(objectFactory, logger);
+	}
+
+	private DataSourceBuilder(AdhocObjectFactory objectFactory, JdbcEventLogger logger) {
+		this.objectFactory = objectFactory;
+		this.logger = logger;
+		this.logger = NoopJdbcEventLogger.getInstance();
+		this.poolParameters = new PoolingDataSourceParameters();
+
+		poolParameters.setMinConnections(1);
+		poolParameters.setMaxConnections(1);
+		poolParameters.setMaxQueueWaitTime(PoolingDataSource.MAX_QUEUE_WAIT_DEFAULT);
+	}
+
+	public DataSourceBuilder userName(String userName) {
+		this.userName = userName;
+		return this;
+	}
+
+	public DataSourceBuilder password(String password) {
+		this.password = password;
+		return this;
+	}
+
+	public DataSourceBuilder driver(String driver) {
+		this.driver = driver;
+		return this;
+	}
+
+	public DataSourceBuilder url(String url) {
+		this.url = url;
+		return this;
+	}
+
+	public DataSourceBuilder minConnections(int minConnections) {
+		poolParameters.setMinConnections(minConnections);
+		return this;
+	}
+
+	public DataSourceBuilder maxConnections(int maxConnections) {
+		poolParameters.setMaxConnections(maxConnections);
+		return this;
+	}
+
+	public DataSourceBuilder maxQueueWaitTime(long maxQueueWaitTime) {
+		poolParameters.setMaxQueueWaitTime(maxQueueWaitTime);
+		return this;
+	}
+
+	public DataSourceBuilder validationQuery(String validationQuery) {
+		poolParameters.setValidationQuery(validationQuery);
+		return this;
+	}
+
+	public DataSource build() {
+
+		// sanity checks...
+		if (poolParameters.getMaxConnections() < 0) {
+			throw new CayenneRuntimeException("Maximum number of connections can not be negative ("
+					+ poolParameters.getMaxConnections() + ").");
+		}
+
+		if (poolParameters.getMinConnections() < 0) {
+			throw new CayenneRuntimeException("Minimum number of connections can not be negative ("
+					+ poolParameters.getMinConnections() + ").");
+		}
+
+		if (poolParameters.getMinConnections() > poolParameters.getMaxConnections()) {
+			throw new CayenneRuntimeException("Minimum number of connections can not be bigger then maximum.");
+		}
+
+		return buildManaged(buildPooling(buildNonPooling()));
+	}
+
+	private DataSource buildNonPooling() {
+		Driver driver = objectFactory.newInstance(Driver.class, this.driver);
+		DriverDataSource dataSource = new DriverDataSource(driver, url, userName, password);
+		dataSource.setLogger(logger);
+		return dataSource;
+	}
+
+	private PoolingDataSource buildPooling(DataSource nonPoolingDataSource) {
+		return new PoolingDataSource(nonPoolingDataSource, poolParameters);
+	}
+
+	private DataSource buildManaged(PoolingDataSource dataSource) {
+		return new ManagedPoolingDataSource(dataSource);
+	}
+}