Author: aadamchik
Date: Sun Sep 17 15:12:23 2006
New Revision: 447160
URL: http://svn.apache.org/viewvc?view=rev&rev=447160
Log:
CAY-654 - 2.0 branch port of DBCPDataSourceFactory
Added:
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceBuilder.java
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceProperties.java
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/conf/DBCPDataSourcePropertiesTst.java
Removed:
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/conf/DBCPDataSourceFactoryTst.java
Modified:
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceFactory.java
Added:
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceBuilder.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceBuilder.java?view=auto&rev=447160
==============================================================================
---
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceBuilder.java
(added)
+++
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceBuilder.java
Sun Sep 17 15:12:23 2006
@@ -0,0 +1,244 @@
+/*****************************************************************
+ * 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.conf;
+
+import java.sql.Connection;
+
+import javax.sql.DataSource;
+
+import org.apache.cayenne.ConfigurationException;
+import org.apache.commons.dbcp.ConnectionFactory;
+import org.apache.commons.dbcp.DriverManagerConnectionFactory;
+import org.apache.commons.dbcp.PoolableConnectionFactory;
+import org.apache.commons.dbcp.PoolingDataSource;
+import org.apache.commons.pool.KeyedObjectPoolFactory;
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory;
+import org.apache.commons.pool.impl.GenericObjectPool;
+
+/**
+ * A helper class that loads DBCP DataSource from properties.
+ *
+ * @author Andrus Adamchik
+ * @since 2.0
+ */
+class DBCPDataSourceBuilder {
+
+ // DataSource Properties
+ static final String DRIVER_CLASS_NAME = "driverClassName";
+ static final String URL = "url";
+ static final String USER_NAME = "username";
+ static final String PASSWORD = "password";
+
+ // Connection Pool Properties
+ static final String MAX_ACTIVE = "maxActive";
+ static final String MIN_IDLE = "minIdle";
+ static final String MAX_IDLE = "maxIdle";
+ static final String MAX_WAIT = "maxWait";
+ static final String VALIDATION_QUERY = "validationQuery";
+ static final String TEST_ON_BORROW = "testOnBorrow";
+ static final String TEST_ON_RETURN = "testOnReturn";
+ static final String TEST_IDLE = "testWhileIdle";
+ static final String TIME_BETWEEN_EVICTIONS =
"timeBetweenEvictionRunsMillis";
+ static final String NUM_TEST_PER_EVICTION = "numTestsPerEvictionRun";
+ static final String MIN_EVICTABLE_TIME = "minEvictableIdleTimeMillis";
+ static final String EXHAUSTED_ACTION = "whenExhaustedAction";
+ static final String AUTO_COMMIT = "defaultAutoCommit";
+ static final String READ_ONLY = "defaultReadOnly";
+ static final String TRANSACTION_ISOLATION = "defaultTransactionIsolation";
+ static final String CONNECTION_NOWRAP =
"accessToUnderlyingConnectionAllowed";
+ static final String CATALOG = "defaultCatalog";
+
+ // PreparedStatementPool properties
+
+ static final String POOL_PS = "poolPreparedStatements";
+ static final String PS_MAX_ACTIVE = "ps.maxActive";
+ static final String PS_MAX_IDLE = "ps.maxIdle";
+ static final String PS_MAX_TOTAL = "ps.maxTotal";
+ static final String PS_MAX_WAIT = "ps.maxWait";
+ static final String PS_MIN_EVICTABLE_TIME =
"ps.minEvictableIdleTimeMillis";
+ static final String PS_NUM_TEST_PER_EVICTION = "ps.numTestsPerEvictionRun";
+ static final String PS_TEST_ON_BORROW = "ps.testOnBorrow";
+ static final String PS_TEST_ON_RETURN = "ps.testOnReturn";
+ static final String PS_TEST_IDLE = "ps.testWhileIdle";
+ static final String PS_TIME_BETWEEN_EVICTIONS =
"ps.timeBetweenEvictionRunsMillis";
+ static final String PS_EXHAUSTED_ACTION = "ps.whenExhaustedAction";
+
+ private DBCPDataSourceProperties config;
+
+ DBCPDataSourceBuilder(DBCPDataSourceProperties properties) {
+ this.config = properties;
+ }
+
+ DataSource createDataSource() {
+ boolean connectionNoWrap = config.getBoolean(CONNECTION_NOWRAP, false);
+ ObjectPool connectionPool = createConnectionPool();
+ PoolingDataSource dataSource = new PoolingDataSource(connectionPool);
+ dataSource.setAccessToUnderlyingConnectionAllowed(connectionNoWrap);
+
+ return dataSource;
+ }
+
+ private void loadDriverClass() {
+ String driver = config.getString(DRIVER_CLASS_NAME, true);
+ try {
+ Class.forName(driver);
+ }
+ catch (ClassNotFoundException e) {
+ throw new ConfigurationException("Error loading driver " + driver,
e);
+ }
+ }
+
+ private ObjectPool createConnectionPool() {
+
+ ConnectionFactory factory = createConnectionFactory();
+ GenericObjectPool.Config poolConfig = createConnectionPoolConfig();
+ KeyedObjectPoolFactory statementPool = createPreparedStatementPool();
+
+ String validationQuery = config.getString(VALIDATION_QUERY);
+ boolean defaultReadOnly = config.getBoolean(READ_ONLY, false);
+ boolean defaultAutoCommit = config.getBoolean(AUTO_COMMIT, false);
+ int defaultTransactionIsolation = config.getTransactionIsolation(
+ TRANSACTION_ISOLATION,
+ Connection.TRANSACTION_SERIALIZABLE);
+ String defaultCatalog = config.getString(CATALOG);
+
+ ObjectPool connectionPool = new GenericObjectPool(null, poolConfig);
+
+ // a side effect of PoolableConnectionFactory constructor call is that
newly
+ // created factory object is assigned to "connectionPool", which is
definitely a
+ // very confusing part of DBCP - new object is not visibly assigned to
anything,
+ // still it is preserved...
+ new PoolableConnectionFactory(
+ factory,
+ connectionPool,
+ statementPool,
+ validationQuery,
+ defaultReadOnly ? Boolean.TRUE : Boolean.FALSE,
+ defaultAutoCommit,
+ defaultTransactionIsolation,
+ defaultCatalog,
+ null);
+
+ return connectionPool;
+ }
+
+ private ConnectionFactory createConnectionFactory() {
+ loadDriverClass();
+ String url = config.getString(URL, true);
+ String userName = config.getString(USER_NAME);
+ String password = config.getString(PASSWORD);
+ return new DriverManagerConnectionFactory(url, userName, password);
+ }
+
+ private KeyedObjectPoolFactory createPreparedStatementPool() {
+
+ if (!config.getBoolean("poolPreparedStatements", false)) {
+ return null;
+ }
+
+ // the GenericKeyedObjectPool.Config object isn't used because
+ // although it has provision for the maxTotal parameter when
+ // passed to the GenericKeyedObjectPoolFactory constructor
+ // this parameter is not being properly set as a default for
+ // creating prepared statement pools
+
+ int maxActive = config
+ .getInt(PS_MAX_ACTIVE, GenericObjectPool.DEFAULT_MAX_ACTIVE);
+ byte whenExhaustedAction = config.getWhenExhaustedAction(
+ PS_EXHAUSTED_ACTION,
+ GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION);
+ long maxWait = config.getLong(PS_MAX_WAIT,
GenericObjectPool.DEFAULT_MAX_WAIT);
+ int maxIdle = config.getInt(PS_MAX_IDLE,
GenericObjectPool.DEFAULT_MAX_IDLE);
+ int maxTotal = config.getInt(PS_MAX_TOTAL, 1);
+
+ boolean testOnBorrow = config.getBoolean(
+ PS_TEST_ON_BORROW,
+ GenericObjectPool.DEFAULT_TEST_ON_BORROW);
+ boolean testOnReturn = config.getBoolean(
+ PS_TEST_ON_RETURN,
+ GenericObjectPool.DEFAULT_TEST_ON_RETURN);
+
+ long timeBetweenEvictionRunsMillis = config.getLong(
+ PS_TIME_BETWEEN_EVICTIONS,
+ GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS);
+ int numTestsPerEvictionRun = config.getInt(
+ PS_NUM_TEST_PER_EVICTION,
+ GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN);
+
+ long minEvictableIdleTimeMillis = config.getLong(
+ PS_MIN_EVICTABLE_TIME,
+ GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
+
+ boolean testWhileIdle = config.getBoolean(
+ PS_TEST_IDLE,
+ GenericObjectPool.DEFAULT_TEST_WHILE_IDLE);
+
+ return new GenericKeyedObjectPoolFactory(
+ null,
+ maxActive,
+ whenExhaustedAction,
+ maxWait,
+ maxIdle,
+ maxTotal,
+ testOnBorrow,
+ testOnReturn,
+ timeBetweenEvictionRunsMillis,
+ numTestsPerEvictionRun,
+ minEvictableIdleTimeMillis,
+ testWhileIdle);
+ }
+
+ private GenericObjectPool.Config createConnectionPoolConfig() {
+ GenericObjectPool.Config poolConfig = new GenericObjectPool.Config();
+
+ poolConfig.maxIdle = config.getInt(MAX_IDLE,
GenericObjectPool.DEFAULT_MAX_IDLE);
+ poolConfig.minIdle = config.getInt(MIN_IDLE,
GenericObjectPool.DEFAULT_MIN_IDLE);
+ poolConfig.maxActive = config.getInt(
+ MAX_ACTIVE,
+ GenericObjectPool.DEFAULT_MAX_ACTIVE);
+ poolConfig.maxWait = config.getLong(MAX_WAIT,
GenericObjectPool.DEFAULT_MAX_WAIT);
+
+ poolConfig.testOnBorrow = config.getBoolean(
+ TEST_ON_BORROW,
+ GenericObjectPool.DEFAULT_TEST_ON_BORROW);
+ poolConfig.testOnReturn = config.getBoolean(
+ TEST_ON_RETURN,
+ GenericObjectPool.DEFAULT_TEST_ON_RETURN);
+ poolConfig.testWhileIdle = config.getBoolean(
+ TEST_IDLE,
+ GenericObjectPool.DEFAULT_TEST_WHILE_IDLE);
+
+ poolConfig.timeBetweenEvictionRunsMillis = config.getLong(
+ TIME_BETWEEN_EVICTIONS,
+ GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS);
+ poolConfig.numTestsPerEvictionRun = config.getInt(
+ NUM_TEST_PER_EVICTION,
+ GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN);
+ poolConfig.minEvictableIdleTimeMillis = config.getLong(
+ MIN_EVICTABLE_TIME,
+ GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
+
+ poolConfig.whenExhaustedAction = config.getWhenExhaustedAction(
+ EXHAUSTED_ACTION,
+ GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION);
+
+ return poolConfig;
+ }
+}
Modified:
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceFactory.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceFactory.java?view=diff&rev=447160&r1=447159&r2=447160
==============================================================================
---
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceFactory.java
(original)
+++
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceFactory.java
Sun Sep 17 15:12:23 2006
@@ -19,215 +19,46 @@
package org.apache.cayenne.conf;
-import java.io.IOException;
-import java.io.InputStream;
-import java.sql.Connection;
-import java.util.Properties;
-
import javax.sql.DataSource;
-import org.apache.commons.dbcp.ConnectionFactory;
-import org.apache.commons.dbcp.DriverManagerConnectionFactory;
-import org.apache.commons.dbcp.PoolableConnectionFactory;
-import org.apache.commons.dbcp.PoolingDataSource;
-import org.apache.commons.pool.KeyedObjectPoolFactory;
-import org.apache.commons.pool.ObjectPool;
-import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory;
-import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
-import org.apache.cayenne.ConfigurationException;
/**
- * An implementation of DataSourceFactory that instantiates a DataSource from
Apache
- * Commons DBCP. Configured via a properties file specified by the location
hint in the
- * modeler and under datasource attribute in cayenne.xml. Note that if
location doesn't
- * have a ".properties" extension, such extension is added automatically.
Sample
- * properties file:
- *
- * <pre>
- *
- *
- *
- *
- *
- * #
- * # This file defines the configuration properties for Commons DBCP
pool
- * # which is used for Cayenne during some of the test cases.
- * # For more info on setting parameters see the documentation for
commons
- * # dbcp and commons pool. The following prefixes are required:
- * # cayenne.dbcp.<param> = configure the connection pool
- * # cayenne.dbcp.ps.<param> = configuration for the prepared
connection pools
- * # that are associated with each pooled connections
- *
- *
- * #driver class to use to connect to the database
- * cayenne.dbcp.driverClassName=net.sourceforge.jtds.jdbc.Driver
- *
- * #url to the database, the parameters should be part of the
connection string
- * #and not here
- *
cayenne.dbcp.url=jdbc:jtds:sqlserver://192.168.20.2:1433/x_test2;TDS=8.0
- *
- * #username to use to connect to the database
- * cayenne.dbcp.username=garyj
- *
- * #password to use to connect to the database
- * cayenne.dbcp.password=somepass
- *
- * #maximum number of active connections
- * cayenne.dbcp.maxActive=500
- *
- * #minimum number of idle connections
- * cayenne.dbcp.minIdle=10
- *
- * #maximum number of active connections that can remain idle in the
pool
- * cayenne.dbcp.maxIdle=10
- *
- * #maximum number of milliseconds to wait for a connection to be
returned to the
- * #pool before throwing an exception when the connection is
required and the pool
- * #is exhaused of the active connections. -1 for indefinetly
- * cayenne.dbcp.maxWait=10000
- *
- * #sql query to be used to validate connections from the pool. Must
return
- * #at least one row
- * cayenne.dbcp.validationQuery=SELECT GETDATE()
- *
- * #should the object be validated when it is borrowed from the pool
- * cayenne.dbcp.testOnBorrow=false
- *
- * #should the object be validated when it is returned to the pool
- * cayenne.dbcp.testOnReturn=true
- *
- * #should the object be validated when it is idle
- * cayenne.dbcp.testWhileIdle=true
- *
- * #number of milliseconds to sleep between runs of the idle object
evictor thread
- * cayenne.dbcp.timeBetweenEvictionRunsMillis=120000
- *
- *
- * #number of objects to examin during each run of the idle object
evictor
- * cayenne.dbcp.numTestsPerEvictionRun=10
- *
- * #minimum time an object may sit idle in the pool before it is
elegible for
- * #an eviction
- * cayenne.dbcp.minEvictableIdleTimeMillis=2000000
- *
- * #action to take the the pool is exhausted of all active
connections
- * #see GenericObjectPool class
- * #this value can be set as either an int or a String the setter
method
- * #will attempt to convert the String value to it's resective
representation
- * #in the GenericObjectPool class and if successfull will use the
byte
- * #value as the config paramter to the pool. If not the default
value will
- * #be used
- * cayenne.dbcp.whenExhaustedAction=WHEN_EXHAUSTED_GROW
- *
- * #The default auto-commit state of connections created by this pool
- * caynne.dbcp.defaultAutoCommit=false
- *
- * #Default read only state of connections created by the pool. Can
be left
- * #as null for driver default
- * cayenne.dbcp.defaultReadOnly=true
- *
- *
- * # Default TransactionIsolation state of connections created by
this pool. This can
- * # be either a String representation of the isolation level
defined in the interface
- * # java.sql.Connection. Can be left as null for
- * # driver default
- * cayenne.dbcp.defaultTransactionIsolation=TRANSACTION_SERIALIZABLE
- *
- * #If set to true the application will be able to get access to the
- * #actual connection object which is normally wrapped by a poolable
connections
- * cayenne.dbcp.accessToUnderlyingConnectionAllowed=true
- *
- * #Default catalog of connections created by this pool
- * cayenne.dbcp.defaultCatalog=someCat
- *
- * #Specifies whether prepared statments should be pooled
- * cayenne.dbcp.poolPreparedStatements=true
- *
- *
- * #Controlls the maximum number of objects that can be borrowed
from the pool at
- * #one time
- * cayenne.dbcp.ps.maxActive=500
- *
- * #Maximum number of idle objects in the pool
- * cayenne.dbcp.ps.maxIdle=50
- *
- * #Maximum number of objects that can exist in the prepared
statement pool at one time
- * cayenne.dbcp.ps.maxTotal=600
- *
- *
- * # Minimum number of milliseconds to wait for an objec the the
pool of
- * # prepared statements is exhausted and the whenExhaustedAction is
set to
- * # 1 (WHEN_EXHAUSTED_BLOCK)
- * cayenne.dbcp.ps.maxWait=10000
- *
- *
- * # Number of milliseconds an object can sit idle in the pool
before it is
- * # elegible for eviction
- * cayenne.dbcp.ps.minEvictableIdleTimeMillis=2000000
- *
- *
- * #Number of idle objects that should be examined per eviction run
- * cayenne.dbcp.ps.numTestsPerEvictionRun=20
- *
- *
- * #Specifies whether objects should be validated before they are
borrowed from this pool
- * cayenne.dbcp.ps.testOnBorrow=false
- *
- * #Specifies whether objects should be validated when they are
returned to the pool
- * cayenne.dbcp.ps.testOnReturn=true
- *
- *
- * #Specifies whether objects should be validated in the idle
eviction thread
- * cayenne.dbcp.ps.testWhileIdle=true
- *
- * #Specifies the time between the runs of the eviction thread
- * cayenne.dbcp.ps.timeBetweenEvictionRunsMillis=120000
- *
- * # action to take when the the pool is exhausted of all active
objects.
- * # acceptable values are strings (WHEN_EXHAUSTED_FAIL,
WHEN_EXHAUSTED_BLOCK (default),
- * # WHEN_EXHAUSTED_GROW), or their corresponding int values defined
in commons-pool GenericObjectPool:
- * cayenne.dbcp.ps.whenExhaustedAction=WHEN_EXHAUSTED_FAIL
- *
- *
- *
- *
- *
- * </pre>
+ * A DataSourceFactory that creates a connection pool based on Apache Jakarta
<a
+ * href="http://jakarta.apache.org/commons/dbcp/">commons-dbcp</a>. If you are
using this
+ * factory, commons-pool and commons-dbcp jars must be present in runtime. <p/>
+ * DBCPDataSourceFactory can be selected in the Modeler for a DataNode. DBCP
pool
+ * configuration is done via a properties file that is specified in the
modeler. See this
+ * <a href="http://cwiki.apache.org/CAYDOC/DBCPDataSourceFactory">wiki
page</a> for the
+ * list of supported properties.
*
* @since 1.2
- * @author Gary Jarrel
+ * @author Andrus Adamchik
*/
public class DBCPDataSourceFactory implements DataSourceFactory {
private static final Logger logger =
Logger.getLogger(DBCPDataSourceFactory.class);
/**
- * Suffix of the properties file
- */
- private static final String SUFFIX = ".properties";
-
- /**
- * All the properties in the configuration properties file should be
prefixed with
- * this prefix, namely cayenne.dbcp. The config parameter as set out in
commons dbcp
- * configuration should follow this prefix.
+ * @deprecated since 2.0 - this information is now private.
*/
public static final String PROPERTY_PREFIX = "cayenne.dbcp.";
/**
- * The the properties in the configuration file, related to Prepared
Statement pooling
- * and used to configure <code>KeyedObjectPoolFactory</code> are followed
by this
- * prefix. This constants is set to PROPERTY_PREFIX + ps.
+ * @deprecated since 2.0 - this information is now private.
*/
public static final String PS_PROPERTY_PREFIX = PROPERTY_PREFIX + "ps.";
protected Configuration parentConfiguration;
+ /**
+ * Stores parent configuration in an ivar, using it later to resolve
resources.
+ */
public void initializeWithParentConfiguration(Configuration
parentConfiguration) {
this.parentConfiguration = parentConfiguration;
}
-
+
/**
* @deprecated since 1.2
*/
@@ -236,355 +67,19 @@
}
/**
- * Creates a DBCP <code>PoolingDataSource</code>
- *
- * @return <code>DataSource</code> which is an instance of
- * <code>PoolingDataSource</code>
- * @throws Exception
+ * Creates and returns a {{org.apache.commons.dbcp.PoolingDataSource}}
instance.
*/
public DataSource getDataSource(String location) throws Exception {
- if (!location.endsWith(SUFFIX)) {
- location = location.concat(SUFFIX);
- }
-
- logger.info("Loading DBCP properties from " + location);
-
- Properties properties = loadProperties(location);
- logger.info("Loaded DBCP properties: " + properties);
-
- loadDriverClass(properties);
-
- // build and assemble parts of DBCP DataSource...
- ConnectionFactory factory = createConnectionFactory(properties);
- KeyedObjectPoolFactory statementPool = createStatementPool(properties);
-
- GenericObjectPool.Config config = createPoolConfig(properties);
-
- // PoolableConnectionFactory properties
- String validationQuery = stringProperty(properties, "validationQuery");
- boolean defaultReadOnly = booleanProperty(properties,
"defaultReadOnly", false);
- boolean defaultAutoCommit = booleanProperty(
- properties,
- "defaultAutoCommit",
- false);
- int defaultTransactionIsolation = defaultTransactionIsolation(
- properties,
- "defaultTransactionIsolation",
- Connection.TRANSACTION_SERIALIZABLE);
- String defaultCatalog = stringProperty(properties, "defaultCatalog");
-
- // a side effect of PoolableConnectionFactory constructor call is that
newly
- // created factory object is assigned to "connectionPool", which is
definitely a
- // very confusing part of DBCP - new object is not visibly assigned to
anything,
- // still it is preserved...
- ObjectPool connectionPool = new GenericObjectPool(null, config);
- new PoolableConnectionFactory(
- factory,
- connectionPool,
- statementPool,
- validationQuery,
- defaultReadOnly ? Boolean.TRUE : Boolean.FALSE,
- defaultAutoCommit,
- defaultTransactionIsolation,
- defaultCatalog,
- null);
-
- PoolingDataSource dataSource = new PoolingDataSource(connectionPool);
- dataSource.setAccessToUnderlyingConnectionAllowed(booleanProperty(
- properties,
- "accessToUnderlyingConnectionAllowed",
- false));
-
- return dataSource;
- }
+ DBCPDataSourceProperties properties = new DBCPDataSourceProperties(
+ parentConfiguration.getResourceLocator(),
+ location);
- /**
- * Loads driver class into driver manager.
- */
- void loadDriverClass(Properties properties) throws Exception {
- String driver = stringProperty(properties, "driverClassName");
- logger.info("loading JDBC driver class: " + driver);
-
- if (driver == null) {
- throw new NullPointerException("No value for required property: "
- + PROPERTY_PREFIX
- + "driverClassName");
- }
- Class.forName(driver);
- }
-
- KeyedObjectPoolFactory createStatementPool(Properties properties) throws
Exception {
-
- if (!booleanProperty(properties, "poolPreparedStatements", false)) {
- return null;
- }
-
- // the GenericKeyedObjectPool.Config object isn't used because
- // although it has provision for the maxTotal parameter when
- // passed to the GenericKeyedObjectPoolFactory constructor
- // this parameter is not being properly set as a default for
- // creating prepared statement pools
-
- int maxActive = intProperty(
- properties,
- "ps.maxActive",
- GenericObjectPool.DEFAULT_MAX_ACTIVE);
- byte whenExhaustedAction = whenExhaustedAction(
- properties,
- "ps.whenExhaustedAction",
- GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION);
-
- long maxWait = longProperty(
- properties,
- "ps.maxWait",
- GenericObjectPool.DEFAULT_MAX_WAIT);
-
- int maxIdle = intProperty(
- properties,
- "ps.maxIdle",
- GenericObjectPool.DEFAULT_MAX_IDLE);
-
- int maxTotal = intProperty(properties, "ps.maxTotal", 1);
-
- boolean testOnBorrow = booleanProperty(
- properties,
- "ps.testOnBorrow",
- GenericObjectPool.DEFAULT_TEST_ON_BORROW);
- boolean testOnReturn = booleanProperty(
- properties,
- "ps.testOnReturn",
- GenericObjectPool.DEFAULT_TEST_ON_RETURN);
-
- long timeBetweenEvictionRunsMillis = longProperty(
- properties,
- "ps.timeBetweenEvictionRunsMillis",
- GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS);
- int numTestsPerEvictionRun = intProperty(
- properties,
- "ps.numTestsPerEvictionRun",
- GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN);
-
- long minEvictableIdleTimeMillis = longProperty(
- properties,
- "ps.minEvictableIdleTimeMillis",
- GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
-
- boolean testWhileIdle = booleanProperty(
- properties,
- "ps.testWhileIdle",
- GenericObjectPool.DEFAULT_TEST_WHILE_IDLE);
-
- return new GenericKeyedObjectPoolFactory(
- null,
- maxActive,
- whenExhaustedAction,
- maxWait,
- maxIdle,
- maxTotal,
- testOnBorrow,
- testOnReturn,
- timeBetweenEvictionRunsMillis,
- numTestsPerEvictionRun,
- minEvictableIdleTimeMillis,
- testWhileIdle);
- }
-
- ConnectionFactory createConnectionFactory(Properties properties) {
- String url = stringProperty(properties, "url");
- String userName = stringProperty(properties, "username");
- String password = stringProperty(properties, "password");
-
- // sanity check
- if (url == null) {
- throw new NullPointerException("No value for required property: "
- + PROPERTY_PREFIX
- + "url");
- }
-
- return new DriverManagerConnectionFactory(url, userName, password);
- }
-
- GenericObjectPool.Config createPoolConfig(Properties properties) throws
Exception {
- GenericObjectPool.Config config = new GenericObjectPool.Config();
-
- config.maxIdle = intProperty(
- properties,
- "maxIdle",
- GenericObjectPool.DEFAULT_MAX_IDLE);
- config.minIdle = intProperty(
- properties,
- "minIdle",
- GenericObjectPool.DEFAULT_MIN_IDLE);
- config.maxActive = intProperty(
- properties,
- "maxActive",
- GenericObjectPool.DEFAULT_MAX_ACTIVE);
- config.maxWait = longProperty(
- properties,
- "maxWait",
- GenericObjectPool.DEFAULT_MAX_WAIT);
-
- config.testOnBorrow = booleanProperty(
- properties,
- "testOnBorrow",
- GenericObjectPool.DEFAULT_TEST_ON_BORROW);
- config.testOnReturn = booleanProperty(
- properties,
- "testOnReturn",
- GenericObjectPool.DEFAULT_TEST_ON_RETURN);
- config.testWhileIdle = booleanProperty(
- properties,
- "testWhileIdle",
- GenericObjectPool.DEFAULT_TEST_WHILE_IDLE);
-
- config.timeBetweenEvictionRunsMillis = longProperty(
- properties,
- "timeBetweenEvictionRunsMillis",
- GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS);
- config.numTestsPerEvictionRun = intProperty(
- properties,
- "numTestsPerEvictionRun",
- GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN);
- config.minEvictableIdleTimeMillis = longProperty(
- properties,
- "minEvictableIdleTimeMillis",
- GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
-
- config.whenExhaustedAction = whenExhaustedAction(
- properties,
- "whenExhaustedAction",
- GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION);
-
- return config;
- }
-
- Properties loadProperties(String location) throws IOException {
-
- Properties properties = new Properties();
- InputStream in = getInputStream(location);
- if (in == null) {
- throw new ConfigurationException("DBCP properties file not found: "
- + location);
- }
-
- try {
- properties.load(in);
- }
- finally {
- try {
- in.close();
- }
- catch (IOException ignore) {
- }
- }
-
- return properties;
- }
-
- int defaultTransactionIsolation(
- Properties properties,
- String property,
- int defaultValue) {
-
- String value = stringProperty(properties, property);
-
- if (value == null) {
- return defaultValue;
- }
-
- // try int...
- try {
- return Integer.parseInt(value);
- }
- catch (NumberFormatException nfex) {
- // try symbolic
- try {
- return Connection.class.getField(value).getInt(null);
- }
- catch (Throwable th) {
- throw new ConfigurationException(
- "Invalid 'defaultTransactionIsolation': " + value);
- }
- }
- }
-
- byte whenExhaustedAction(Properties properties, String property, byte
defaultValue)
- throws Exception {
-
- String value = stringProperty(properties, property);
-
- if (value == null) {
- return defaultValue;
- }
-
- // try byte...
- try {
- return Byte.parseByte(value);
- }
- catch (NumberFormatException nfex) {
- // try symbolic
- try {
- return GenericObjectPool.class.getField(value).getByte(null);
- }
- catch (Throwable th) {
- throw new ConfigurationException("Invalid
'whenExhaustedAction': "
- + value);
- }
- }
- }
-
- String stringProperty(Properties properties, String property) {
- return properties.getProperty(PROPERTY_PREFIX + property);
- }
-
- boolean booleanProperty(Properties properties, String property, boolean
defaultValue) {
- String value = stringProperty(properties, property);
- return (value != null) ? "true".equalsIgnoreCase(stringProperty(
- properties,
- property)) : defaultValue;
- }
-
- int intProperty(Properties properties, String property, int defaultValue) {
- String value = stringProperty(properties, property);
-
- try {
- return (value != null) ? Integer.parseInt(value) : defaultValue;
- }
- catch (NumberFormatException nfex) {
- return defaultValue;
- }
- }
-
- long longProperty(Properties properties, String property, long
defaultValue) {
- String value = stringProperty(properties, property);
- try {
- return (value != null) ? Long.parseLong(value) : defaultValue;
- }
- catch (NumberFormatException nfex) {
- return defaultValue;
- }
- }
-
- byte byteProperty(Properties properties, String property, byte
defaultValue) {
- String value = stringProperty(properties, property);
- try {
- return (value != null) ? Byte.parseByte(value) : defaultValue;
- }
- catch (NumberFormatException nfex) {
- return defaultValue;
- }
- }
-
- /**
- * Returns an input stream for the file corresponding to location.
- */
- InputStream getInputStream(String location) {
- if (this.parentConfiguration == null) {
- throw new ConfigurationException(
- "No parent Configuration set - cannot continue.");
+ if (logger.isDebugEnabled()) {
+ logger.debug("DBCP Properties: " + properties.getProperties());
}
- return
this.parentConfiguration.getResourceLocator().findResourceStream(location);
+ DBCPDataSourceBuilder builder = new DBCPDataSourceBuilder(properties);
+ return builder.createDataSource();
}
}
Added:
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceProperties.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceProperties.java?view=auto&rev=447160
==============================================================================
---
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceProperties.java
(added)
+++
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/conf/DBCPDataSourceProperties.java
Sun Sep 17 15:12:23 2006
@@ -0,0 +1,192 @@
+/*****************************************************************
+ * 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.conf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Connection;
+import java.util.Properties;
+
+import org.apache.cayenne.ConfigurationException;
+import org.apache.cayenne.util.ResourceLocator;
+import org.apache.commons.pool.impl.GenericObjectPool;
+
+/**
+ * A helper class providing access to DBCP properties.
+ *
+ * @author Andrus Adamchik
+ * @since 2.0
+ */
+class DBCPDataSourceProperties {
+
+ private static final String PROPERTY_PREFIX = "cayenne.dbcp.";
+
+ private Properties properties;
+
+ /**
+ * Loads properties from the specified location.
+ */
+ private static Properties loadProperties(
+ ResourceLocator resourceLocator,
+ String location) throws IOException {
+
+ InputStream in = resourceLocator.findResourceStream(location);
+
+ // try appending ".properties" extension..
+ if (in == null && !location.endsWith(".properties")) {
+ in = resourceLocator.findResourceStream(location + ".properties");
+ }
+
+ if (in == null) {
+ throw new ConfigurationException("DBCP properties file not found: "
+ + location);
+ }
+
+ Properties properties = new Properties();
+ try {
+ properties.load(in);
+ }
+ finally {
+ try {
+ in.close();
+ }
+ catch (IOException e) {
+ }
+ }
+
+ return properties;
+ }
+
+ DBCPDataSourceProperties(ResourceLocator resourceLocator, String location)
+ throws IOException {
+ this(loadProperties(resourceLocator, location));
+ }
+
+ DBCPDataSourceProperties(Properties properties) {
+ this.properties = properties;
+ }
+
+ Properties getProperties() {
+ return properties;
+ }
+
+ String getString(String property, boolean required) {
+ String value = properties.getProperty(PROPERTY_PREFIX + property);
+
+ if (required && value == null) {
+ throw new ConfigurationException("No value for required property: "
+ + PROPERTY_PREFIX
+ + property);
+ }
+
+ return value;
+ }
+
+ String getString(String property) {
+ return getString(property, false);
+ }
+
+ boolean getBoolean(String property, boolean defaultValue) {
+ String value = getString(property);
+ return (value != null)
+ ? "true".equalsIgnoreCase(getString(property))
+ : defaultValue;
+ }
+
+ int getInt(String property, int defaultValue) {
+ String value = getString(property);
+
+ try {
+ return (value != null) ? Integer.parseInt(value) : defaultValue;
+ }
+ catch (NumberFormatException nfex) {
+ return defaultValue;
+ }
+ }
+
+ long getLong(String property, long defaultValue) {
+ String value = getString(property);
+ try {
+ return (value != null) ? Long.parseLong(value) : defaultValue;
+ }
+ catch (NumberFormatException nfex) {
+ return defaultValue;
+ }
+ }
+
+ byte getByte(String property, byte defaultValue) {
+ String value = getString(property);
+ try {
+ return (value != null) ? Byte.parseByte(value) : defaultValue;
+ }
+ catch (NumberFormatException nfex) {
+ return defaultValue;
+ }
+ }
+
+ byte getWhenExhaustedAction(String property, byte defaultValue)
+ throws ConfigurationException {
+
+ String value = getString(property);
+
+ if (value == null) {
+ return defaultValue;
+ }
+
+ // try byte...
+ try {
+ return Byte.parseByte(value);
+ }
+ catch (NumberFormatException nfex) {
+ // try symbolic
+ try {
+ return GenericObjectPool.class.getField(value).getByte(null);
+ }
+ catch (Throwable th) {
+ throw new ConfigurationException("Invalid
'whenExhaustedAction': "
+ + value);
+ }
+ }
+ }
+
+ int getTransactionIsolation(String property, int defaultValue) {
+
+ String value = getString(property);
+
+ if (value == null) {
+ return defaultValue;
+ }
+
+ // try int...
+ try {
+ return Integer.parseInt(value);
+ }
+ catch (NumberFormatException nfex) {
+ // try symbolic
+ try {
+ return Connection.class.getField(value).getInt(null);
+ }
+ catch (Throwable th) {
+ throw new ConfigurationException(
+ "Invalid 'defaultTransactionIsolation': " + value);
+ }
+ }
+ }
+
+}
Added:
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/conf/DBCPDataSourcePropertiesTst.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/conf/DBCPDataSourcePropertiesTst.java?view=auto&rev=447160
==============================================================================
---
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/conf/DBCPDataSourcePropertiesTst.java
(added)
+++
incubator/cayenne/main/branches/STABLE-2.0/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/conf/DBCPDataSourcePropertiesTst.java
Sun Sep 17 15:12:23 2006
@@ -0,0 +1,116 @@
+/*****************************************************************
+ * 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.conf;
+
+import java.sql.Connection;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.apache.cayenne.ConfigurationException;
+import org.apache.commons.pool.impl.GenericObjectPool;
+
+/**
+ * @author Andrus Adamchik
+ */
+public class DBCPDataSourcePropertiesTst extends TestCase {
+
+ public void testStringProperty() {
+ Properties props = new Properties();
+ props.put("a", "X");
+ props.put("cayenne.dbcp.c", "Y");
+ DBCPDataSourceProperties factory = new DBCPDataSourceProperties(props);
+
+ assertNull(factory.getString("a"));
+ assertNull(factory.getString("b"));
+ assertEquals("Y", factory.getString("c"));
+ }
+
+ public void testIntProperty() {
+
+ Properties props = new Properties();
+ props.put("a", "10");
+ props.put("cayenne.dbcp.b", "11");
+ props.put("cayenne.dbcp.d", "**");
+ DBCPDataSourceProperties factory = new DBCPDataSourceProperties(props);
+
+ assertEquals(11, factory.getInt("b", -1));
+ assertEquals(-1, factory.getInt("a", -1));
+ assertEquals(-1, factory.getInt("c", -1));
+ assertEquals(-2, factory.getInt("d", -2));
+ }
+
+ public void testWhenExhaustedAction() throws Exception {
+ Properties props = new Properties();
+ props.put("cayenne.dbcp.a", "1");
+ props.put("cayenne.dbcp.b", "WHEN_EXHAUSTED_BLOCK");
+ props.put("cayenne.dbcp.c", "WHEN_EXHAUSTED_GROW");
+ props.put("cayenne.dbcp.d", "WHEN_EXHAUSTED_FAIL");
+ props.put("cayenne.dbcp.e", "garbage");
+ DBCPDataSourceProperties factory = new DBCPDataSourceProperties(props);
+
+ assertEquals(1, factory.getWhenExhaustedAction("a", (byte) 100));
+ assertEquals(GenericObjectPool.WHEN_EXHAUSTED_BLOCK, factory
+ .getWhenExhaustedAction("b", (byte) 100));
+ assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW, factory
+ .getWhenExhaustedAction("c", (byte) 100));
+ assertEquals(GenericObjectPool.WHEN_EXHAUSTED_FAIL, factory
+ .getWhenExhaustedAction("d", (byte) 100));
+
+ try {
+ factory.getWhenExhaustedAction("e", (byte) 100);
+ fail("must throw on invalid key");
+ }
+ catch (ConfigurationException ex) {
+ // expected
+ }
+
+ assertEquals(100, factory.getWhenExhaustedAction("f", (byte) 100));
+ }
+
+ public void testTransactionIsolation() throws Exception {
+ Properties props = new Properties();
+ props.put("cayenne.dbcp.a", "1");
+ props.put("cayenne.dbcp.b", "TRANSACTION_NONE");
+ props.put("cayenne.dbcp.c", "TRANSACTION_READ_UNCOMMITTED");
+ props.put("cayenne.dbcp.d", "TRANSACTION_SERIALIZABLE");
+ props.put("cayenne.dbcp.e", "garbage");
+ DBCPDataSourceProperties factory = new DBCPDataSourceProperties(props);
+ assertEquals(1, factory.getTransactionIsolation("a", (byte) 100));
+ assertEquals(Connection.TRANSACTION_NONE,
factory.getTransactionIsolation(
+ "b",
+ (byte) 100));
+
+ assertEquals(Connection.TRANSACTION_READ_UNCOMMITTED, factory
+ .getTransactionIsolation("c", (byte) 100));
+ assertEquals(Connection.TRANSACTION_SERIALIZABLE, factory
+ .getTransactionIsolation("d", (byte) 100));
+
+ try {
+ factory.getTransactionIsolation("e", (byte) 100);
+ fail("must throw on invalid key");
+ }
+ catch (ConfigurationException ex) {
+ // expected
+ }
+
+ assertEquals(100, factory.getTransactionIsolation("f", (byte) 100));
+ }
+}