cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aadamc...@apache.org
Subject svn commit: r447124 - in /incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src: main/java/org/apache/cayenne/conf/ test/java/org/apache/cayenne/conf/
Date Sun, 17 Sep 2006 19:45:47 GMT
Author: aadamchik
Date: Sun Sep 17 12:45:47 2006
New Revision: 447124

URL: http://svn.apache.org/viewvc?view=rev&rev=447124
Log:
CAY-654 - rewriting DBCP DataSourceFactory

Added:
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceBuilder.java
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceProperties.java
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/conf/DBCPDataSourcePropertiesTst.java
      - copied, changed from r446997, incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/conf/DBCPDataSourceFactoryTst.java
Removed:
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/conf/DBCPDataSourceFactoryTst.java
Modified:
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceFactory.java

Added: incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceBuilder.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceBuilder.java?view=auto&rev=447124
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceBuilder.java (added)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceBuilder.java Sun Sep 17 12:45:47 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/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceFactory.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceFactory.java?view=diff&rev=447124&r1=447123&r2=447124
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceFactory.java (original)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceFactory.java Sun Sep 17 12:45:47 2006
@@ -19,565 +19,60 @@
 
 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.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.logging.Log;
 import org.apache.commons.logging.LogFactory;
-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;
 
 /**
- * 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.&lt;param&gt; = configure the connection pool
- *            # cayenne.dbcp.ps.&lt;param&gt; = 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 Log logger = LogFactory.getLog(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;
     }
 
     /**
-     * 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;
-    }
-
-    /**
-     * 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) {
-            }
-        }
+        DBCPDataSourceProperties properties = new DBCPDataSourceProperties(
+                parentConfiguration.getResourceLocator(),
+                location);
 
-        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/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceProperties.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceProperties.java?view=auto&rev=447124
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceProperties.java (added)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DBCPDataSourceProperties.java Sun Sep 17 12:45:47 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);
+            }
+        }
+    }
+
+}

Copied: incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/conf/DBCPDataSourcePropertiesTst.java (from r446997, incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/conf/DBCPDataSourceFactoryTst.java)
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/conf/DBCPDataSourcePropertiesTst.java?view=diff&rev=447124&p1=incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/conf/DBCPDataSourceFactoryTst.java&r1=446997&p2=incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/conf/DBCPDataSourcePropertiesTst.java&r2=447124
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/conf/DBCPDataSourceFactoryTst.java (original)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/test/java/org/apache/cayenne/conf/DBCPDataSourcePropertiesTst.java Sun Sep 17 12:45:47 2006
@@ -22,101 +22,95 @@
 import java.sql.Connection;
 import java.util.Properties;
 
-import org.apache.commons.pool.impl.GenericObjectPool;
-import org.apache.cayenne.ConfigurationException;
-
 import junit.framework.TestCase;
 
+import org.apache.cayenne.ConfigurationException;
+import org.apache.commons.pool.impl.GenericObjectPool;
+
 /**
  * @author Andrus Adamchik
  */
-public class DBCPDataSourceFactoryTst extends TestCase {
+public class DBCPDataSourcePropertiesTst extends TestCase {
 
     public void testStringProperty() {
-        DBCPDataSourceFactory factory = new DBCPDataSourceFactory();
         Properties props = new Properties();
         props.put("a", "X");
         props.put("cayenne.dbcp.c", "Y");
+        DBCPDataSourceProperties factory = new DBCPDataSourceProperties(props);
 
-        assertNull(factory.stringProperty(props, "a"));
-        assertNull(factory.stringProperty(props, "b"));
-        assertEquals("Y", factory.stringProperty(props, "c"));
+        assertNull(factory.getString("a"));
+        assertNull(factory.getString("b"));
+        assertEquals("Y", factory.getString("c"));
     }
 
     public void testIntProperty() {
-        DBCPDataSourceFactory factory = new DBCPDataSourceFactory();
+
         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.intProperty(props, "b", -1));
-        assertEquals(-1, factory.intProperty(props, "a", -1));
-        assertEquals(-1, factory.intProperty(props, "c", -1));
-        assertEquals(-2, factory.intProperty(props, "d", -2));
+        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 {
-        DBCPDataSourceFactory factory = new DBCPDataSourceFactory();
         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.whenExhaustedAction(props, "a", (byte) 100));
-        assertEquals(GenericObjectPool.WHEN_EXHAUSTED_BLOCK, factory.whenExhaustedAction(
-                props,
-                "b",
-                (byte) 100));
-        assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW, factory.whenExhaustedAction(
-                props,
-                "c",
-                (byte) 100));
-        assertEquals(GenericObjectPool.WHEN_EXHAUSTED_FAIL, factory.whenExhaustedAction(
-                props,
-                "d",
-                (byte) 100));
+        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.whenExhaustedAction(props, "e", (byte) 100);
+            factory.getWhenExhaustedAction("e", (byte) 100);
             fail("must throw on invalid key");
         }
         catch (ConfigurationException ex) {
             // expected
         }
 
-        assertEquals(100, factory.whenExhaustedAction(props, "f", (byte) 100));
+        assertEquals(100, factory.getWhenExhaustedAction("f", (byte) 100));
     }
 
     public void testTransactionIsolation() throws Exception {
-        DBCPDataSourceFactory factory = new DBCPDataSourceFactory();
         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");
-
-        assertEquals(1, factory.defaultTransactionIsolation(props, "a", (byte) 100));
-        assertEquals(Connection.TRANSACTION_NONE, factory.defaultTransactionIsolation(
-                props,
+        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
-                .defaultTransactionIsolation(props, "c", (byte) 100));
+                .getTransactionIsolation("c", (byte) 100));
         assertEquals(Connection.TRANSACTION_SERIALIZABLE, factory
-                .defaultTransactionIsolation(props, "d", (byte) 100));
+                .getTransactionIsolation("d", (byte) 100));
 
         try {
-            factory.defaultTransactionIsolation(props, "e", (byte) 100);
+            factory.getTransactionIsolation("e", (byte) 100);
             fail("must throw on invalid key");
         }
         catch (ConfigurationException ex) {
             // expected
         }
 
-        assertEquals(100, factory.defaultTransactionIsolation(props, "f", (byte) 100));
+        assertEquals(100, factory.getTransactionIsolation("f", (byte) 100));
     }
 }



Mime
View raw message