Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 50 additions & 2 deletions src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,11 @@ protected static void validateConnectionFactory(final PoolableConnectionFactory
*/
private ObjectNameWrapper registeredJmxObjectName;

/**
* The fully qualified Java class name of the connectionFactoryName to be used.
*/
private String connectionFactoryClassName;

/**
* Adds a custom connection property to the set that will be passed to our JDBC driver. This <strong>MUST</strong>
* be called before the first connection is retrieved (along with all the other configuration property setters).
Expand Down Expand Up @@ -526,8 +531,7 @@ protected ConnectionFactory createConnectionFactory() throws SQLException {
log("DBCP DataSource configured without a 'password'");
}

final ConnectionFactory driverConnectionFactory = new DriverConnectionFactory(driverToUse, url,
connectionProperties);
final ConnectionFactory driverConnectionFactory = getConnectionFactoryInstance(driverToUse);
return driverConnectionFactory;
}

Expand Down Expand Up @@ -990,6 +994,18 @@ public synchronized String getDriverClassName() {
return this.driverClassName;
}

/**
* Returns the ConnectionFactoryClassName that has been configured for use by this pool.
* <p>
* Note: This getter only returns the last value set by a call to {@link #setConnectionFactoryClassName(connectionFactoryClassName)}.
* </p>
*
* @return the ConnectionFactoryClassName that has been configured for use by this pool
*/
public String getConnectionFactoryClassName() {
return this.connectionFactoryClassName;
}

/**
* Returns the value of the flag that controls whether or not connections being returned to the pool will be checked
* and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
Expand Down Expand Up @@ -1967,6 +1983,21 @@ public synchronized void setDriverClassName(final String driverClassName) {
this.driverClassName = null;
}
}

/**
* Sets the ConnectionFactory class name.
*
* @param connectionFactoryClassName
*
*/

public void setConnectionFactoryClassName(final String connectionFactoryClassName) {
if (connectionFactoryClassName != null && connectionFactoryClassName.trim().length() > 0) {
this.connectionFactoryClassName = connectionFactoryClassName;
} else {
this.connectionFactoryClassName = null;
}
}

/**
* Sets the value of the flag that controls whether or not connections being returned to the pool will be checked
Expand Down Expand Up @@ -2527,4 +2558,21 @@ private void updateJmxName(final GenericObjectPoolConfig<?> config) {
config.setJmxNameBase(base.toString());
config.setJmxNamePrefix(Constants.JMX_CONNECTION_POOL_PREFIX);
}

private ConnectionFactory getConnectionFactoryInstance(Driver driver) throws SQLException {
if (connectionFactoryClassName != null) {
try {
Class<?> connectionFactoryFromCCL = Class.forName(connectionFactoryClassName);
return (ConnectionFactory) connectionFactoryFromCCL.getConstructor(Driver.class, String.class, Properties.class)
.newInstance(driver, url, connectionProperties);
} catch (final Exception t) {
final String message = "Cannot load ConnectionFactory class '" + connectionFactoryClassName + "'";
logWriter.println(message);
t.printStackTrace(logWriter);
throw new SQLException(message, t);
}
} else {
return new DriverConnectionFactory(driver, url, connectionProperties);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public class BasicDataSourceFactory implements ObjectFactory {
private static final String PROP_VALIDATION_QUERY = "validationQuery";
private static final String PROP_VALIDATION_QUERY_TIMEOUT = "validationQueryTimeout";
private static final String PROP_JMX_NAME = "jmxName";
private static final String PROP_CONNECTION_FACTORY_CLASS_NAME = "connectionFactoryClassName";

/**
* The property name for connectionInitSqls. The associated value String must be of the form [query;]*
Expand Down Expand Up @@ -141,7 +142,8 @@ public class BasicDataSourceFactory implements ObjectFactory {
PROP_REMOVE_ABANDONED_TIMEOUT, PROP_LOG_ABANDONED, PROP_ABANDONED_USAGE_TRACKING, PROP_POOL_PREPARED_STATEMENTS,
PROP_MAX_OPEN_PREPARED_STATEMENTS, PROP_CONNECTION_PROPERTIES, PROP_MAX_CONN_LIFETIME_MILLIS,
PROP_LOG_EXPIRED_CONNECTIONS, PROP_ROLLBACK_ON_RETURN, PROP_ENABLE_AUTO_COMMIT_ON_RETURN,
PROP_DEFAULT_QUERY_TIMEOUT, PROP_FAST_FAIL_VALIDATION, PROP_DISCONNECTION_SQL_CODES, PROP_JMX_NAME };
PROP_DEFAULT_QUERY_TIMEOUT, PROP_FAST_FAIL_VALIDATION, PROP_DISCONNECTION_SQL_CODES, PROP_JMX_NAME,
PROP_CONNECTION_FACTORY_CLASS_NAME };

/**
* Obsolete properties from DBCP 1.x. with warning strings suggesting new properties. LinkedHashMap will guarantee
Expand Down Expand Up @@ -547,7 +549,14 @@ public static BasicDataSource createDataSource(final Properties properties) thro
if (value != null) {
dataSource.setDisconnectionSqlCodes(parseList(value, ','));
}

value = properties.getProperty(PROP_CONNECTION_FACTORY_CLASS_NAME);
if (value != null) {
dataSource.setConnectionFactoryClassName(value);
}



// DBCP-215
// Trick to make sure that initialSize connections are created
if (dataSource.getInitialSize() > 0) {
Expand Down
45 changes: 43 additions & 2 deletions src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@

package org.apache.commons.dbcp2;

import static org.junit.jupiter.api.Assertions.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import java.io.IOException;
import java.lang.management.ManagementFactory;
Expand All @@ -38,8 +43,8 @@
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

/**
Expand Down Expand Up @@ -875,6 +880,42 @@ public void testMutateAbandonedConfig() throws Exception {
Assertions.assertNotEquals(Boolean.valueOf(original),
Boolean.valueOf(ds.getConnectionPool().getLogAbandoned()));
}

/**
* JIRA: DBCP-547
* Verify that ConnectionFactory interface in BasicDataSource.createConnectionFactory().
*/
@Test
public void testCreateConnectionFactory() throws Exception {

/** not set ConnectionFactoryClassName */
Properties properties = new Properties();
properties.put("initialSize", "1");
properties.put("driverClassName", "org.apache.commons.dbcp2.TesterDriver");
properties.put("url", "jdbc:apache:commons:testdriver");
properties.put("username", "foo");
properties.put("password", "bar");
BasicDataSource ds = BasicDataSourceFactory.createDataSource(properties);
Connection conn = ds.getConnection();
assertNotNull(conn);
conn.close();
ds.close();

/** set ConnectionFactoryClassName */
properties = new Properties();
properties.put("initialSize", "1");
properties.put("driverClassName", "org.apache.commons.dbcp2.TesterDriver");
properties.put("url", "jdbc:apache:commons:testdriver");
properties.put("username", "foo");
properties.put("password", "bar");
properties.put("connectionFactoryClassName", "org.apache.commons.dbcp2.TestOracleDriverConnectionFactory");
ds = BasicDataSourceFactory.createDataSource(properties);
conn = ds.getConnection();
assertNotNull(conn);

conn.close();
ds.close();
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* 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.commons.dbcp2;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.Properties;

/**
* Simple ConnectionFactory impl class that use BasicDataSource.createConnectionFactory()
*/

public class TestOracleDriverConnectionFactory implements ConnectionFactory {
private final String connectionString;
private final Driver driver;
private final Properties properties;

/**
* Constructs a connection factory for a given Driver.
*
* @param driver
* The Driver.
* @param connectString
* The connection string.
* @param properties
* The connection properties.
*/
public TestOracleDriverConnectionFactory(final Driver driver, final String connectString, final Properties properties) {
this.driver = driver;
this.connectionString = connectString;
this.properties = properties;
}

@Override
public Connection createConnection() throws SQLException {
Connection conn = driver.connect(connectionString, properties);
callOracleSetModule(conn);
return conn;
}

/**
* @return The connection String.
* @since 2.6.0
*/
public String getConnectionString() {
return connectionString;
}

/**
* @return The Driver.
* @since 2.6.0
*/
public Driver getDriver() {
return driver;
}

/**
* @return The Properties.
* @since 2.6.0
*/
public Properties getProperties() {
return properties;
}

@Override
public String toString() {
return this.getClass().getName() + " [" + String.valueOf(driver) + ";" + String.valueOf(connectionString) + ";"
+ String.valueOf(properties) + "]";
}

private void callOracleSetModule(Connection conn) {
// do something
}
}