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);
+ }
+}