You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2009/12/06 12:22:21 UTC

svn commit: r887667 [1/2] - in /cayenne/main/trunk/framework: cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conf/ cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/ cayenne-jdk1.5-unpublished/src/main/java/org/apac...

Author: aadamchik
Date: Sun Dec  6 11:22:19 2009
New Revision: 887667

URL: http://svn.apache.org/viewvc?rev=887667&view=rev
Log:
CAY-1319 Switch Cayenne configuration loading to cayenne-di container

* configuration.DataSourceFactoryLoader
* configuration.DataSourceFactory
* configuration.XMLPoolingDataSourceFactory
* configuration.DbAdapterFactory
* configuration.AdhocObjectFactory

Added:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/AdhocObjectFactory.java
      - copied, changed from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataSourceFactory.java
      - copied, changed from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataSourceFactoryLoader.java
      - copied, changed from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DbAdapterDetector.java
      - copied, changed from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DbAdapterFactory.java
      - copied, changed from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultAdhocObjectFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultDataSourceFactoryLoader.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultDbAdapterFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/XMLPoolingDataSourceFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/configuration/DefaultDataSourceFactoryLoaderTest.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/configuration/DefaultDbAdapterFactoryTest.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/configuration/XMLPoolingDataSourceFactoryTest.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/configuration/mock/
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/configuration/mock/MockDataSourceFactory.java
      - copied, changed from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/runtime/MockDataSourceFactory1.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/configuration/mock/MockDataSourceFactory1.java
      - copied, changed from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/runtime/MockDataSourceFactory2.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/configuration/mock/MockDataSourceFactoryLoader.java
      - copied, changed from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/runtime/MockDataSourceFactory2.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/resource/mock/
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/resource/mock/MockResourceLocator.java
      - copied, changed from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DriverDataSourceFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/org/apache/cayenne/configuration/testNode1.driver.xml
    cayenne/main/trunk/framework/cayenne-server/pom.properties
Removed:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DriverDataSourceFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/JNDIDataSourceFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/runtime/MockDataSourceFactory1.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/runtime/MockDataSourceFactory2.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conf/DataSourceFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conf/DriverDataSourceFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/CayenneModule.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactoryChain.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataDomainProvider.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/dba/MockDbAdapter.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/runtime/DataDomainProviderTest.java

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conf/DataSourceFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conf/DataSourceFactory.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conf/DataSourceFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conf/DataSourceFactory.java Sun Dec  6 11:22:19 2009
@@ -22,19 +22,22 @@
 import javax.sql.DataSource;
 
 /**
- * A pluggable factory for javax.sql.DataSource instances used by Cayenne runtime.
+ * A pluggable factory for {@link DataSource} instances used by Cayenne runtime.
+ * 
+ * @deprecated since 3.1, replaced by
+ *             {@link org.apache.cayenne.configuration.DataSourceFactory}
  */
 public interface DataSourceFactory {
 
     /**
      * Initializes factory with the parent configuration object.
      */
-    public void initializeWithParentConfiguration(Configuration conf);
+    void initializeWithParentConfiguration(Configuration conf);
 
     /**
      * Returns DataSource object corresponding to <code>location</code>. Concrete
      * implementations may treat location differently - as a file path, JNDI location,
      * etc.
      */
-    public DataSource getDataSource(String location) throws Exception;
+    DataSource getDataSource(String location) throws Exception;
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conf/DriverDataSourceFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conf/DriverDataSourceFactory.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conf/DriverDataSourceFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/conf/DriverDataSourceFactory.java Sun Dec  6 11:22:19 2009
@@ -33,6 +33,7 @@
 import org.apache.cayenne.access.QueryLogger;
 import org.apache.cayenne.conn.DataSourceInfo;
 import org.apache.cayenne.conn.PoolManager;
+import org.apache.cayenne.resource.ResourceLocator;
 import org.apache.cayenne.util.Util;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -47,17 +48,19 @@
  * Creates DataSource objects from XML configuration files that describe a JDBC driver.
  * Wraps JDBC driver in a generic DataSource implementation.
  * 
+ * @deprecated since 3.1 {@link org.apache.cayenne.configuration.XMLPoolingDataSourceFactory}
+ *             replaces this class.
  */
-// TODO: factory shouldn't contain any state specific to location ("driverInfo" ivar
-// should go, and probably "parser" too)... Otherwise the API doesn't make sense -
-// sequential invocations of getDataSource() will have side effects....
 public class DriverDataSourceFactory implements DataSourceFactory {
 
     private static final Log logger = LogFactory.getLog(DriverDataSourceFactory.class);
 
+    protected Configuration parentConfiguration;
+
+    // TODO: andrus 12.5.2009: non-thread-safe local ivars... SInce this class is
+    // deprecated, I guess we don't have to fix it here...
     protected XMLReader parser;
     protected DataSourceInfo driverInfo;
-    protected Configuration parentConfiguration;
 
     /**
      * Creates new DriverDataSourceFactory.
@@ -74,7 +77,7 @@
     }
 
     public DataSource getDataSource(String location) throws Exception {
-        this.load(location);
+        load(location);
 
         ConnectionLogger logger = new ConnectionLogger();
 
@@ -114,12 +117,11 @@
     }
 
     /**
-     * Loads driver information from the file at <code>location</code>. Called
-     * internally from "getDataSource"
+     * Loads driver information from the file at <code>location</code>. Called internally
+     * from "getDataSource"
+     * 
+     * @deprecated since 3.1
      */
-    // TODO: andrus 2008/04/22, while this never caused any troubles, storing loaded
-    // DataSourceInfo in an ivar clearly violates the scope logic, as "location" is a
-    // local variable.
     protected void load(String location) throws Exception {
         logger.info("loading driver information from '" + location + "'.");
 
@@ -236,6 +238,7 @@
     }
 
     private class LoginHandler extends AbstractHandler {
+
         /**
          * Constructor which just delegates to the superconstructor.
          * 
@@ -312,10 +315,10 @@
             String password = atts.getValue("password");
             String passwordLocation = atts.getValue("passwordLocation");
             String passwordSource = atts.getValue("passwordSource");
-            if(passwordSource == null) {
+            if (passwordSource == null) {
                 passwordSource = DataSourceInfo.PASSWORD_LOCATION_MODEL;
             }
-            
+
             String username = atts.getValue("userName");
 
             driverInfo.setPasswordEncoderClass(encoderClass);

Copied: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/AdhocObjectFactory.java (from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/AdhocObjectFactory.java?p2=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/AdhocObjectFactory.java&p1=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java&r1=887666&r2=887667&rev=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/AdhocObjectFactory.java Sun Dec  6 11:22:19 2009
@@ -16,21 +16,18 @@
  *  specific language governing permissions and limitations
  *  under the License.
  ****************************************************************/
-package org.apache.cayenne.runtime;
-
-import javax.sql.DataSource;
-
-import org.apache.cayenne.configuration.DataNodeDescriptor;
+package org.apache.cayenne.configuration;
 
 /**
- * Provides instances of {@link DataSource} for DataNodes.
+ * Creates objects for user-provided String class names, injecting dependencies into them.
  * 
  * @since 3.1
  */
-public interface DataSourceFactory {
+public interface AdhocObjectFactory {
 
     /**
-     * Returns a DataSource for a given {@link DataNodeDescriptor} configuration object.
+     * Returns an instance of "className" that implements "superType", injecting
+     * dependencies from the registry into it.
      */
-    DataSource getDataSource(DataNodeDescriptor nodeDescriptor);
+    <T> T newInstance(Class<? super T> superType, String className);
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/CayenneModule.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/CayenneModule.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/CayenneModule.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/CayenneModule.java Sun Dec  6 11:22:19 2009
@@ -21,8 +21,20 @@
 import org.apache.cayenne.DataChannel;
 import org.apache.cayenne.access.dbsync.SchemaUpdateStrategy;
 import org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy;
-import org.apache.cayenne.dba.AutoAdapter;
 import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.db2.DB2Sniffer;
+import org.apache.cayenne.dba.derby.DerbySniffer;
+import org.apache.cayenne.dba.frontbase.FrontBaseSniffer;
+import org.apache.cayenne.dba.h2.H2Sniffer;
+import org.apache.cayenne.dba.hsqldb.HSQLDBSniffer;
+import org.apache.cayenne.dba.ingres.IngresSniffer;
+import org.apache.cayenne.dba.mysql.MySQLSniffer;
+import org.apache.cayenne.dba.openbase.OpenBaseSniffer;
+import org.apache.cayenne.dba.oracle.OracleSniffer;
+import org.apache.cayenne.dba.postgres.PostgresSniffer;
+import org.apache.cayenne.dba.sqlite.SQLiteSniffer;
+import org.apache.cayenne.dba.sqlserver.SQLServerSniffer;
+import org.apache.cayenne.dba.sybase.SybaseSniffer;
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.Module;
 import org.apache.cayenne.di.Scopes;
@@ -30,8 +42,6 @@
 import org.apache.cayenne.resource.ResourceLocator;
 import org.apache.cayenne.runtime.CayenneRuntime;
 import org.apache.cayenne.runtime.DataDomainProvider;
-import org.apache.cayenne.runtime.DataSourceFactory;
-import org.apache.cayenne.runtime.DriverDataSourceFactory;
 
 /**
  * A DI module containing all Cayenne runtime configurations. To customize Cayenne runtime
@@ -55,6 +65,27 @@
                 RuntimeProperties.CAYENNE_RUNTIME_NAME,
                 runtimeName);
 
+        // configure known DbAdapter detectors in reverse order of popularity. Users can
+        // add their own for their own to install custom adapters automatically
+        binder
+                .bindList(DbAdapter.class)
+                .add(new OpenBaseSniffer())
+                .add(new FrontBaseSniffer())
+                .add(new IngresSniffer())
+                .add(new SQLiteSniffer())
+                .add(new DB2Sniffer())
+                .add(new H2Sniffer())
+                .add(new HSQLDBSniffer())
+                .add(new SybaseSniffer())
+                .add(new DerbySniffer())
+                .add(new SQLServerSniffer())
+                .add(new OracleSniffer())
+                .add(new PostgresSniffer())
+                .add(new MySQLSniffer());
+
+        binder.bind(AdhocObjectFactory.class).to(DefaultAdhocObjectFactory.class).in(
+                Scopes.SINGLETON);
+
         // a service to provide the main stack DataChannel
         binder.bind(DataChannel.class).toProvider(DataDomainProvider.class);
 
@@ -73,16 +104,16 @@
         binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class).in(
                 Scopes.SINGLETON);
 
+        // a service to load DataSourceFactories
+        binder.bind(DataSourceFactoryLoader.class).to(
+                DefaultDataSourceFactoryLoader.class).in(Scopes.SINGLETON);
+
         // a default SchemaUpdateStrategy (used when no explicit strategy is specified in
         // XML)
-        binder.bind(SchemaUpdateStrategy.class).to(SkipSchemaUpdateStrategy.class);
-
-        // a default DBAdapter (used when no explicit adapter is set in XML)
-
-        // TODO: andrus 11.30.2009: missing dependencies: DataSource, DbAdapterFactory
-        binder.bind(DbAdapter.class).to(AutoAdapter.class);
+        binder.bind(SchemaUpdateStrategy.class).to(SkipSchemaUpdateStrategy.class).in(
+                Scopes.SINGLETON);
 
-        // a service to find or create DataSources
-        binder.bind(DataSourceFactory.class).to(DriverDataSourceFactory.class);
+        // a default DBAdapterFactory used to load custom and automatic DbAdapters
+        binder.bind(DbAdapterFactory.class).to(DefaultDbAdapterFactory.class);
     }
 }

Copied: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataSourceFactory.java (from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataSourceFactory.java?p2=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataSourceFactory.java&p1=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java&r1=887666&r2=887667&rev=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataSourceFactory.java Sun Dec  6 11:22:19 2009
@@ -16,21 +16,18 @@
  *  specific language governing permissions and limitations
  *  under the License.
  ****************************************************************/
-package org.apache.cayenne.runtime;
+package org.apache.cayenne.configuration;
 
 import javax.sql.DataSource;
 
-import org.apache.cayenne.configuration.DataNodeDescriptor;
-
 /**
- * Provides instances of {@link DataSource} for DataNodes.
- * 
  * @since 3.1
  */
 public interface DataSourceFactory {
 
     /**
-     * Returns a DataSource for a given {@link DataNodeDescriptor} configuration object.
+     * Returns DataSource object based on the configuration provided in the
+     * "nodeDescriptor".
      */
-    DataSource getDataSource(DataNodeDescriptor nodeDescriptor);
+    DataSource getDataSource(DataNodeDescriptor nodeDescriptor) throws Exception;
 }

Copied: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataSourceFactoryLoader.java (from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataSourceFactoryLoader.java?p2=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataSourceFactoryLoader.java&p1=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java&r1=887666&r2=887667&rev=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataSourceFactoryLoader.java Sun Dec  6 11:22:19 2009
@@ -16,21 +16,19 @@
  *  specific language governing permissions and limitations
  *  under the License.
  ****************************************************************/
-package org.apache.cayenne.runtime;
-
-import javax.sql.DataSource;
-
-import org.apache.cayenne.configuration.DataNodeDescriptor;
+package org.apache.cayenne.configuration;
 
 /**
- * Provides instances of {@link DataSource} for DataNodes.
+ * Provides instances of {@link DataSourceFactory} for DataNodes.
  * 
  * @since 3.1
  */
-public interface DataSourceFactory {
+public interface DataSourceFactoryLoader {
 
     /**
-     * Returns a DataSource for a given {@link DataNodeDescriptor} configuration object.
+     * Returns a DataSourceFactory for a given {@link DataNodeDescriptor} configuration
+     * object. The factory should be specified in the node descriptor explicitly by the
+     * user. Cayenne will inject dependencies in all user-provided factories.
      */
-    DataSource getDataSource(DataNodeDescriptor nodeDescriptor);
+    DataSourceFactory getDataSourceFactory(DataNodeDescriptor nodeDescriptor);
 }

Copied: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DbAdapterDetector.java (from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactory.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DbAdapterDetector.java?p2=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DbAdapterDetector.java&p1=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactory.java&r1=887666&r2=887667&rev=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DbAdapterDetector.java Sun Dec  6 11:22:19 2009
@@ -16,25 +16,26 @@
  *  specific language governing permissions and limitations
  *  under the License.
  ****************************************************************/
-
-package org.apache.cayenne.dba;
+package org.apache.cayenne.configuration;
 
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+import org.apache.cayenne.dba.DbAdapter;
+
 /**
- * Defines a conditional factory for a specific DbAdapter. Note that the factory can
- * potentially return different (or differently configured) DbAdapters for the same
- * database based on version information and other metadata.
+ * A factory interface providing DbAdapter based on JDBC metadata. It allows custom
+ * DbAdapters to contribute database detection algorithms to
+ * {@link DefaultDbAdapterFactory}.
  * 
- * @since 1.2
+ * @since 3.1
  */
-public interface DbAdapterFactory {
+public interface DbAdapterDetector {
 
     /**
      * Returns an instance of DbAdapter if the factory detects that it knows how to handle
-     * the database. Returns null if the database is not known to the factory, thus
-     * allowing multiple factories to be chained.
+     * the database or null if the database is not known to the factory, thus allowing
+     * multiple factories to be chained.
      */
     DbAdapter createAdapter(DatabaseMetaData md) throws SQLException;
 }

Copied: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DbAdapterFactory.java (from r887666, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DbAdapterFactory.java?p2=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DbAdapterFactory.java&p1=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java&r1=887666&r2=887667&rev=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataSourceFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DbAdapterFactory.java Sun Dec  6 11:22:19 2009
@@ -16,21 +16,21 @@
  *  specific language governing permissions and limitations
  *  under the License.
  ****************************************************************/
-package org.apache.cayenne.runtime;
+package org.apache.cayenne.configuration;
 
 import javax.sql.DataSource;
 
-import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.dba.DbAdapter;
 
 /**
- * Provides instances of {@link DataSource} for DataNodes.
- * 
  * @since 3.1
  */
-public interface DataSourceFactory {
+public interface DbAdapterFactory {
 
     /**
-     * Returns a DataSource for a given {@link DataNodeDescriptor} configuration object.
+     * Returns an instance of DbAdapter if the factory detects that it knows how to handle
+     * the database.
      */
-    DataSource getDataSource(DataNodeDescriptor nodeDescriptor);
+    DbAdapter createAdapter(DataNodeDescriptor nodeDescriptor, DataSource dataSource)
+            throws Exception;
 }

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultAdhocObjectFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultAdhocObjectFactory.java?rev=887667&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultAdhocObjectFactory.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultAdhocObjectFactory.java Sun Dec  6 11:22:19 2009
@@ -0,0 +1,83 @@
+/*****************************************************************
+ *   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.configuration;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.util.Util;
+
+/**
+ * A default implementation of {@link AdhocObjectFactory} that creates objects using
+ * default no-arg constructor and injects dependencies into annotated fields. Note that
+ * constructor injection is not supported by this factory.
+ * 
+ * @since 3.1
+ */
+public class DefaultAdhocObjectFactory implements AdhocObjectFactory {
+
+    @Inject
+    protected Injector injector;
+
+    public <T> T newInstance(Class<? super T> superType, String className) {
+
+        if (superType == null) {
+            throw new NullPointerException("Null superType");
+        }
+
+        if (className == null) {
+            throw new NullPointerException("Null className");
+        }
+
+        Class<T> type;
+        try {
+            type = (Class<T>) Util.getJavaClass(className);
+        }
+        catch (ClassNotFoundException e) {
+            throw new CayenneRuntimeException(
+                    "Invalid class %s of type %s",
+                    e,
+                    className,
+                    superType.getName());
+        }
+
+        if (!superType.isAssignableFrom(type)) {
+            throw new CayenneRuntimeException(
+                    "Class %s is not assignable to %s",
+                    className,
+                    superType.getName());
+        }
+
+        T instance;
+        try {
+            instance = type.newInstance();
+        }
+        catch (Exception e) {
+            throw new CayenneRuntimeException(
+                    "Error creating instance of class %s of type %s",
+                    e,
+                    className,
+                    superType.getName());
+        }
+
+        injector.injectMembers(instance);
+        return instance;
+    }
+
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultDataSourceFactoryLoader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultDataSourceFactoryLoader.java?rev=887667&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultDataSourceFactoryLoader.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultDataSourceFactoryLoader.java Sun Dec  6 11:22:19 2009
@@ -0,0 +1,55 @@
+/*****************************************************************
+ *   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.configuration;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.di.Inject;
+
+/**
+ * A {@link DataSourceFactoryLoader} that loads factories explicitly configured in the
+ * {@link DataNodeDescriptor}. If the factory class is not explicitly configured, and the
+ * descriptor has a configuration resource attached to it, {@link XMLPoolingDataSourceFactory}
+ * is returned.
+ * 
+ * @since 3.1
+ */
+public class DefaultDataSourceFactoryLoader implements DataSourceFactoryLoader {
+
+    @Inject
+    protected AdhocObjectFactory objectFactory;
+
+    public DataSourceFactory getDataSourceFactory(DataNodeDescriptor nodeDescriptor) {
+        String typeName = nodeDescriptor.getDataSourceFactoryType();
+
+        if (typeName == null) {
+            if (nodeDescriptor.getConfigurationResource() != null) {
+                return objectFactory.newInstance(
+                        DataSourceFactory.class,
+                        XMLPoolingDataSourceFactory.class.getName());
+            }
+            else {
+                throw new CayenneRuntimeException(
+                        "DataNodeDescriptor '%s' has no explicit DataSourceFactoryType set and has no configuration resource",
+                        nodeDescriptor.getName());
+            }
+        }
+
+        return objectFactory.newInstance(DataSourceFactory.class, typeName);
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultDbAdapterFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultDbAdapterFactory.java?rev=887667&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultDbAdapterFactory.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DefaultDbAdapterFactory.java Sun Dec  6 11:22:19 2009
@@ -0,0 +1,125 @@
+/*****************************************************************
+ *   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.configuration;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+import java.util.List;
+
+import javax.sql.DataSource;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.access.QueryLogger;
+import org.apache.cayenne.dba.AutoAdapter;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.di.DIException;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Provider;
+
+/**
+ * A factory of DbAdapters that either loads user-provided adapter or guesses the adapter
+ * type from the database metadata.
+ * 
+ * @since 3.1
+ */
+public class DefaultDbAdapterFactory implements DbAdapterFactory {
+
+    @Inject
+    protected AdhocObjectFactory objectFactory;
+    protected List<DbAdapterDetector> detectors;
+
+    public DefaultDbAdapterFactory(@Inject List<DbAdapterDetector> detectors) {
+        if (detectors == null) {
+            throw new NullPointerException("Null detectors list");
+        }
+
+        this.detectors = detectors;
+    }
+
+    public DbAdapter createAdapter(
+            final DataNodeDescriptor nodeDescriptor,
+            final DataSource dataSource) throws Exception {
+
+        String adapterType = nodeDescriptor.getAdapterType();
+        if (adapterType != null) {
+            return objectFactory.newInstance(DbAdapter.class, adapterType);
+        }
+        else {
+            return new AutoAdapter(new Provider<DbAdapter>() {
+
+                public DbAdapter get() throws DIException {
+                    return detectAdapter(nodeDescriptor, dataSource);
+                }
+            });
+        }
+    }
+
+    protected DbAdapter detectAdapter(
+            DataNodeDescriptor nodeDescriptor,
+            DataSource dataSource) {
+
+        if (detectors.isEmpty()) {
+            return defaultAdapter();
+        }
+
+        try {
+            Connection c = dataSource.getConnection();
+
+            try {
+                return detectAdapter(c.getMetaData());
+            }
+            finally {
+                try {
+                    c.close();
+                }
+                catch (SQLException e) {
+                    // ignore...
+                }
+            }
+        }
+        catch (SQLException e) {
+            throw new CayenneRuntimeException("Error detecting database type: "
+                    + e.getLocalizedMessage(), e);
+        }
+    }
+
+    protected DbAdapter detectAdapter(DatabaseMetaData metaData) throws SQLException {
+        // iterate in reverse order to allow custom factories to take precedence over the
+        // default ones configured in constructor
+        for (int i = detectors.size() - 1; i >= 0; i--) {
+            DbAdapterDetector detector = detectors.get(i);
+            DbAdapter adapter = detector.createAdapter(metaData);
+
+            if (adapter != null) {
+                QueryLogger.log("Detected and installed adapter: "
+                        + adapter.getClass().getName());
+                return adapter;
+            }
+        }
+
+        return defaultAdapter();
+    }
+
+    protected DbAdapter defaultAdapter() {
+        QueryLogger.log("Failed to detect database type, using generic adapter");
+        return new JdbcAdapter();
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/XMLPoolingDataSourceFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/XMLPoolingDataSourceFactory.java?rev=887667&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/XMLPoolingDataSourceFactory.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/XMLPoolingDataSourceFactory.java Sun Dec  6 11:22:19 2009
@@ -0,0 +1,324 @@
+/*****************************************************************
+ *   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.configuration;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collection;
+
+import javax.sql.DataSource;
+
+import org.apache.cayenne.ConfigurationException;
+import org.apache.cayenne.access.ConnectionLogger;
+import org.apache.cayenne.access.QueryLogger;
+import org.apache.cayenne.conf.PasswordEncoding;
+import org.apache.cayenne.conn.DataSourceInfo;
+import org.apache.cayenne.conn.PoolManager;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.resource.Resource;
+import org.apache.cayenne.resource.ResourceLocator;
+import org.apache.cayenne.util.Util;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+/**
+ * A {@link DataSourceFactory} that loads JDBC connection information from an XML resource
+ * associated with the DataNodeDescriptor, returning a DataSource with simple connection
+ * pooling.
+ * 
+ * @since 3.1
+ */
+public class XMLPoolingDataSourceFactory implements DataSourceFactory {
+
+    private static final Log logger = LogFactory
+            .getLog(XMLPoolingDataSourceFactory.class);
+
+    @Inject
+    protected ResourceLocator resourceLocator;
+
+    public DataSource getDataSource(DataNodeDescriptor nodeDescriptor) throws Exception {
+
+        logger.info("loading driver information from '"
+                + nodeDescriptor.getLocation()
+                + "'.");
+
+        Resource resource = nodeDescriptor.getConfigurationResource();
+
+        if (resource == null) {
+            logger.info("Null configuration resource for node descriptor with location '"
+                    + nodeDescriptor.getLocation()
+                    + "'");
+            throw new ConfigurationException(
+                    "Null configuration resource for node descriptor with location '%s'",
+                    nodeDescriptor.getLocation());
+        }
+
+        DataSourceInfo dataSourceDescriptor = new DataSourceInfo();
+
+        XMLReader parser = Util.createXmlReader();
+
+        DriverHandler handler = new DriverHandler(dataSourceDescriptor, parser);
+        parser.setContentHandler(handler);
+        parser.setErrorHandler(handler);
+        parser.parse(new InputSource(resource.getURL().openStream()));
+
+        return createDataSource(dataSourceDescriptor);
+    }
+
+    /**
+     * Returns an instance of {@link PoolManager}.
+     */
+    protected DataSource createDataSource(DataSourceInfo dataSourceDescriptor)
+            throws Exception {
+
+        ConnectionLogger logger = new ConnectionLogger();
+        try {
+            return new PoolManager(
+                    dataSourceDescriptor.getJdbcDriver(),
+                    dataSourceDescriptor.getDataSourceUrl(),
+                    dataSourceDescriptor.getMinConnections(),
+                    dataSourceDescriptor.getMaxConnections(),
+                    dataSourceDescriptor.getUserName(),
+                    dataSourceDescriptor.getPassword(),
+                    logger);
+        }
+        catch (Exception e) {
+            QueryLogger.logConnectFailure(e);
+            throw e;
+        }
+    }
+
+    private static String passwordFromURL(URL url) {
+        InputStream inputStream = null;
+        String password = null;
+
+        try {
+            inputStream = url.openStream();
+            password = passwordFromInputStream(inputStream);
+        }
+        catch (IOException exception) {
+            // Log the error while trying to open the stream. A null
+            // password will be returned as a result.
+            logger.warn(exception);
+        }
+
+        return password;
+    }
+
+    private static String passwordFromInputStream(InputStream inputStream) {
+        BufferedReader bufferedReader = null;
+        String password = null;
+
+        try {
+            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+            password = bufferedReader.readLine();
+        }
+        catch (IOException exception) {
+            logger.warn(exception);
+        }
+        finally {
+            try {
+                if (bufferedReader != null) {
+                    bufferedReader.close();
+                }
+            }
+            catch (Exception exception) {
+            }
+
+            try {
+                inputStream.close();
+            }
+            catch (IOException exception) {
+            }
+        }
+
+        return password;
+    }
+
+    private class DriverHandler extends SAXNestedTagHandler {
+
+        private DataSourceInfo dataSourceDescriptor;
+
+        DriverHandler(DataSourceInfo dataSourceDescriptor, XMLReader parser) {
+            super(parser, null);
+            this.dataSourceDescriptor = dataSourceDescriptor;
+        }
+
+        @Override
+        protected ContentHandler createChildTagHandler(
+                String namespaceURI,
+                String localName,
+                String name,
+                Attributes attributes) {
+
+            if (localName.equals("driver")) {
+                String className = attributes.getValue("", "class");
+                logger.info("loading driver " + className);
+                dataSourceDescriptor.setJdbcDriver(className);
+                return new DriverChildrenHandler(parser, this);
+            }
+
+            return super.createChildTagHandler(namespaceURI, localName, name, attributes);
+        }
+    }
+
+    private class DriverChildrenHandler extends SAXNestedTagHandler {
+
+        private DataSourceInfo dataSourceDescriptor;
+
+        DriverChildrenHandler(XMLReader parser, DriverHandler parentHandler) {
+            super(parser, parentHandler);
+            this.dataSourceDescriptor = parentHandler.dataSourceDescriptor;
+        }
+
+        @Override
+        protected ContentHandler createChildTagHandler(
+                String namespaceURI,
+                String localName,
+                String name,
+                Attributes attributes) {
+
+            if (localName.equals("login")) {
+
+                logger.info("loading user name and password.");
+
+                String encoderClass = attributes.getValue("encoderClass");
+
+                String encoderKey = attributes.getValue("encoderKey");
+                if (encoderKey == null) {
+                    encoderKey = attributes.getValue("encoderSalt");
+                }
+
+                String password = attributes.getValue("password");
+                String passwordLocation = attributes.getValue("passwordLocation");
+                String passwordSource = attributes.getValue("passwordSource");
+                if (passwordSource == null) {
+                    passwordSource = DataSourceInfo.PASSWORD_LOCATION_MODEL;
+                }
+
+                String username = attributes.getValue("userName");
+
+                dataSourceDescriptor.setPasswordEncoderClass(encoderClass);
+                dataSourceDescriptor.setPasswordEncoderKey(encoderKey);
+                dataSourceDescriptor.setPasswordLocation(passwordLocation);
+                dataSourceDescriptor.setPasswordSource(passwordSource);
+                dataSourceDescriptor.setUserName(username);
+
+                // Replace {} in passwordSource with encoderSalt -- useful for EXECUTABLE
+                // & URL options
+                if (encoderKey != null) {
+                    passwordSource = passwordSource.replaceAll("\\{\\}", encoderKey);
+                }
+
+                PasswordEncoding passwordEncoder = dataSourceDescriptor
+                        .getPasswordEncoder();
+
+                if (passwordLocation != null) {
+                    if (passwordLocation
+                            .equals(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH)) {
+                        Collection<Resource> urls = resourceLocator
+                                .findResources(passwordLocation);
+                        if (urls.size() > 0) {
+                            password = passwordFromURL(urls.iterator().next().getURL());
+                        }
+                        else {
+                            logger.error("Could not find resource in CLASSPATH: "
+                                    + passwordSource);
+                        }
+                    }
+                    else if (passwordLocation
+                            .equals(DataSourceInfo.PASSWORD_LOCATION_URL)) {
+                        try {
+                            password = passwordFromURL(new URL(passwordSource));
+                        }
+                        catch (MalformedURLException exception) {
+                            logger.warn(exception);
+                        }
+                    }
+                    else if (passwordLocation
+                            .equals(DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE)) {
+                        if (passwordSource != null) {
+                            try {
+                                Process process = Runtime.getRuntime().exec(
+                                        passwordSource);
+                                password = passwordFromInputStream(process
+                                        .getInputStream());
+                                process.waitFor();
+                            }
+                            catch (IOException exception) {
+                                logger.warn(exception);
+                            }
+                            catch (InterruptedException exception) {
+                                logger.warn(exception);
+                            }
+                        }
+                    }
+                }
+
+                if (password != null && passwordEncoder != null) {
+                    dataSourceDescriptor.setPassword(passwordEncoder.decodePassword(
+                            password,
+                            encoderKey));
+                }
+            }
+            else if (localName.equals("url")) {
+                dataSourceDescriptor.setDataSourceUrl(attributes.getValue("value"));
+            }
+            else if (localName.equals("connectionPool")) {
+                String min = attributes.getValue("min");
+                if (min != null) {
+                    try {
+                        dataSourceDescriptor.setMinConnections(Integer.parseInt(min));
+                    }
+                    catch (NumberFormatException nfex) {
+                        logger.info("Non-numeric 'min' attribute", nfex);
+                        throw new ConfigurationException(
+                                "Non-numeric 'min' attribute '%s'",
+                                nfex,
+                                min);
+                    }
+                }
+
+                String max = attributes.getValue("max");
+                if (max != null) {
+                    try {
+                        dataSourceDescriptor.setMaxConnections(Integer.parseInt(max));
+                    }
+                    catch (NumberFormatException nfex) {
+                        logger.info("Non-numeric 'max' attribute", nfex);
+                        throw new ConfigurationException(
+                                "Non-numeric 'max' attribute '%s'",
+                                nfex,
+                                max);
+                    }
+                }
+            }
+
+            return super.createChildTagHandler(namespaceURI, localName, name, attributes);
+        }
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/AutoAdapter.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/AutoAdapter.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/AutoAdapter.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/AutoAdapter.java Sun Dec  6 11:22:19 2009
@@ -48,7 +48,8 @@
 import org.apache.cayenne.dba.sqlite.SQLiteSniffer;
 import org.apache.cayenne.dba.sqlserver.SQLServerSniffer;
 import org.apache.cayenne.dba.sybase.SybaseSniffer;
-import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.DIException;
+import org.apache.cayenne.di.Provider;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.DbRelationship;
@@ -68,8 +69,15 @@
     final static String DEFAULT_QUOTE_SQL_IDENTIFIERS_CHAR_START = "\"";
     final static String DEFAULT_QUOTE_SQL_IDENTIFIERS_CHAR_END = "\"";
 
+    /**
+     * @deprecated since 3.1 in favor of
+     *             {@link org.apache.cayenne.configuration.DbAdapterFactory} configured
+     *             via dependency injection.
+     */
     static final List<DbAdapterFactory> defaultFactories;
+
     static {
+
         defaultFactories = new ArrayList<DbAdapterFactory>();
 
         // hardcoded factories for adapters that we know how to auto-detect
@@ -93,6 +101,9 @@
      * Allows application code to add a sniffer to detect a custom adapter.
      * 
      * @since 3.0
+     * @deprecated since 3.1 in favor of
+     *             {@link org.apache.cayenne.configuration.DbAdapterFactory} configured
+     *             via dependency injection.
      */
     public static void addFactory(DbAdapterFactory factory) {
         defaultFactories.add(factory);
@@ -101,47 +112,114 @@
     /**
      * Returns a DbAdapterFactory configured to detect all databases officially supported
      * by Cayenne.
+     * 
+     * @deprecated since 3.1 in favor of
+     *             {@link org.apache.cayenne.configuration.DbAdapterFactory} configured
+     *             via dependency injection.
      */
     public static DbAdapterFactory getDefaultFactory() {
         return new DbAdapterFactoryChain(defaultFactories);
     }
 
-    protected DbAdapterFactory adapterFactory;
-    protected DataSource dataSource;
+    protected Provider<DbAdapter> adapterProvider;
     protected PkGenerator pkGenerator;
 
     /**
-     * The actual adapter that is delegated method execution.
+     * The actual adapter that is delegated methods execution.
      */
-    DbAdapter adapter;
+    volatile DbAdapter adapter;
 
     /**
      * Creates an AutoAdapter that can detect adapters known to Cayenne.
+     * 
+     * @deprecated since 3.1 as {@link org.apache.cayenne.configuration.DbAdapterFactory}
+     *             parameter is required.
      */
     public AutoAdapter(DataSource dataSource) {
-        this(null, dataSource);
+        this((DbAdapterFactory) null, dataSource);
     }
 
     /**
      * Creates an AutoAdapter with specified adapter factory and DataSource. If
      * adapterFactory is null, default factory is used.
+     * 
+     * @deprecated since 3.1 in favor of
+     *             {@link org.apache.cayenne.configuration.DbAdapterFactory} configured
+     *             via dependency injection.
      */
-    public AutoAdapter(@Inject DbAdapterFactory adapterFactory,
-            @Inject DataSource dataSource) {
+    public AutoAdapter(DbAdapterFactory adapterFactory, final DataSource dataSource) {
         // sanity check
         if (dataSource == null) {
             throw new CayenneRuntimeException("Null dataSource");
         }
 
-        this.adapterFactory = adapterFactory != null
+        final DbAdapterFactory deprecatedFactory = adapterFactory != null
                 ? adapterFactory
                 : createDefaultFactory();
-        this.dataSource = dataSource;
+
+        this.adapterProvider = new Provider<DbAdapter>() {
+
+            public DbAdapter get() throws DIException {
+                DbAdapter adapter;
+
+                try {
+                    Connection c = dataSource.getConnection();
+
+                    try {
+                        adapter = deprecatedFactory.createAdapter(c.getMetaData());
+                    }
+                    finally {
+                        try {
+                            c.close();
+                        }
+                        catch (SQLException e) {
+                            // ignore...
+                        }
+                    }
+                }
+                catch (SQLException e) {
+                    throw new CayenneRuntimeException("Error detecting database type: "
+                            + e.getLocalizedMessage(), e);
+                }
+
+                if (adapter == null) {
+                    QueryLogger
+                            .log("Failed to detect database type, using default adapter");
+                    adapter = new JdbcAdapter();
+                }
+                else {
+                    QueryLogger.log("Detected and installed adapter: "
+                            + adapter.getClass().getName());
+                }
+
+                return adapter;
+            }
+        };
+
+    }
+
+    /**
+     * Creates an {@link AutoAdapter} based on a delegate adapter obtained via
+     * "adapterProvider".
+     * 
+     * @since 3.1
+     */
+    public AutoAdapter(Provider<DbAdapter> adapterProvider) {
+
+        if (adapterProvider == null) {
+            throw new CayenneRuntimeException("Null adapterProvider");
+        }
+
+        this.adapterProvider = adapterProvider;
     }
 
     /**
      * Called from constructor to initialize factory in case no factory was specified by
      * the object creator.
+     * 
+     * @deprecated since 3.1 in favor of
+     *             {@link org.apache.cayenne.configuration.DbAdapterFactory} configured
+     *             via dependency injection.
      */
     protected DbAdapterFactory createDefaultFactory() {
         return getDefaultFactory();
@@ -163,41 +241,10 @@
     }
 
     /**
-     * Opens a connection, retrieves JDBC metadata and attempts to guess adapter form it.
+     * Loads underlying DbAdapter delegate.
      */
     protected DbAdapter loadAdapter() {
-        DbAdapter adapter = null;
-
-        try {
-            Connection c = dataSource.getConnection();
-
-            try {
-                adapter = adapterFactory.createAdapter(c.getMetaData());
-            }
-            finally {
-                try {
-                    c.close();
-                }
-                catch (SQLException e) {
-                    // ignore...
-                }
-            }
-        }
-        catch (SQLException e) {
-            throw new CayenneRuntimeException("Error detecting database type: "
-                    + e.getLocalizedMessage(), e);
-        }
-
-        if (adapter == null) {
-            QueryLogger.log("Failed to detect database type, using default adapter");
-            adapter = new JdbcAdapter();
-        }
-        else {
-            QueryLogger.log("Detected and installed adapter: "
-                    + adapter.getClass().getName());
-        }
-
-        return adapter;
+        return adapterProvider.get();
     }
 
     // ---- DbAdapter methods ----
@@ -307,9 +354,6 @@
         getAdapter().createTableAppendColumn(sqlBuffer, column);
     }
 
-    public void setDefaultQuoteSqlIdentifiersChars(boolean isQuoteSqlIdentifiers) {
-    }
-
     public String getIdentifiersStartQuote() {
         return DEFAULT_QUOTE_SQL_IDENTIFIERS_CHAR_START;
     }
@@ -321,5 +365,4 @@
     public QuotingStrategy getQuotingStrategy(boolean isQuoteStrategy) {
         return getAdapter().getQuotingStrategy(isQuoteStrategy);
     }
-
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactory.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactory.java Sun Dec  6 11:22:19 2009
@@ -28,6 +28,9 @@
  * database based on version information and other metadata.
  * 
  * @since 1.2
+ * @deprecated since 3.1 in favor of
+ *             {@link org.apache.cayenne.configuration.DbAdapterFactory} configured via
+ *             dependency injection.
  */
 public interface DbAdapterFactory {
 

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactoryChain.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactoryChain.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactoryChain.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/DbAdapterFactoryChain.java Sun Dec  6 11:22:19 2009
@@ -30,10 +30,10 @@
  * adapters known to Cayenne or can work with custom factories.
  * 
  * @since 1.2
+ * @deprecated since 3.1 in favor of
+ *             {@link org.apache.cayenne.configuration.DbAdapterFactory} configured via
+ *             dependency injection.
  */
-// TODO, Andrus 11/01/2005, how can custom adapters be auto-detected? I.e. is there a way
-// to plug a custom factory into configuration loading process? Of course users can simply
-// specify the adapter class in the modeler, so this may be a non-issue.
 class DbAdapterFactoryChain implements DbAdapterFactory {
 
     List<DbAdapterFactory> factories;

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/db2/DB2Sniffer.java Sun Dec  6 11:22:19 2009
@@ -22,13 +22,14 @@
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+import org.apache.cayenne.configuration.DbAdapterDetector;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.DbAdapterFactory;
 
 /**
  * @since 1.2
  */
-public class DB2Sniffer implements DbAdapterFactory {
+public class DB2Sniffer implements DbAdapterFactory, DbAdapterDetector {
 
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/derby/DerbySniffer.java Sun Dec  6 11:22:19 2009
@@ -22,6 +22,7 @@
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+import org.apache.cayenne.configuration.DbAdapterDetector;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.DbAdapterFactory;
 
@@ -30,7 +31,7 @@
  * 
  * @since 1.2
  */
-public class DerbySniffer implements DbAdapterFactory {
+public class DerbySniffer implements DbAdapterFactory, DbAdapterDetector {
 
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/frontbase/FrontBaseSniffer.java Sun Dec  6 11:22:19 2009
@@ -22,13 +22,14 @@
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+import org.apache.cayenne.configuration.DbAdapterDetector;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.DbAdapterFactory;
 
 /**
  * @since 1.2
  */
-public class FrontBaseSniffer implements DbAdapterFactory {
+public class FrontBaseSniffer implements DbAdapterFactory, DbAdapterDetector {
 
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/h2/H2Sniffer.java Sun Dec  6 11:22:19 2009
@@ -21,13 +21,15 @@
 
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
+
+import org.apache.cayenne.configuration.DbAdapterDetector;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.DbAdapterFactory;
 
 /**
  * @since 3.0
  */
-public class H2Sniffer implements DbAdapterFactory {
+public class H2Sniffer implements DbAdapterFactory, DbAdapterDetector {
 
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBSniffer.java Sun Dec  6 11:22:19 2009
@@ -22,6 +22,7 @@
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+import org.apache.cayenne.configuration.DbAdapterDetector;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.DbAdapterFactory;
 
@@ -30,7 +31,7 @@
  * 
  * @since 1.2
  */
-public class HSQLDBSniffer implements DbAdapterFactory {
+public class HSQLDBSniffer implements DbAdapterFactory, DbAdapterDetector {
 
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/ingres/IngresSniffer.java Sun Dec  6 11:22:19 2009
@@ -22,6 +22,7 @@
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+import org.apache.cayenne.configuration.DbAdapterDetector;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.DbAdapterFactory;
 
@@ -30,7 +31,7 @@
  * 
  * @since 1.2
  */
-public class IngresSniffer implements DbAdapterFactory {
+public class IngresSniffer implements DbAdapterFactory, DbAdapterDetector {
 
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/mysql/MySQLSniffer.java Sun Dec  6 11:22:19 2009
@@ -24,6 +24,7 @@
 import java.sql.SQLException;
 import java.sql.Statement;
 
+import org.apache.cayenne.configuration.DbAdapterDetector;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.DbAdapterFactory;
 
@@ -32,7 +33,7 @@
  * 
  * @since 1.2
  */
-public class MySQLSniffer implements DbAdapterFactory {
+public class MySQLSniffer implements DbAdapterFactory, DbAdapterDetector {
 
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/openbase/OpenBaseSniffer.java Sun Dec  6 11:22:19 2009
@@ -22,6 +22,7 @@
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+import org.apache.cayenne.configuration.DbAdapterDetector;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.DbAdapterFactory;
 
@@ -30,7 +31,7 @@
  * 
  * @since 1.2
  */
-public class OpenBaseSniffer implements DbAdapterFactory {
+public class OpenBaseSniffer implements DbAdapterFactory, DbAdapterDetector {
 
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/oracle/OracleSniffer.java Sun Dec  6 11:22:19 2009
@@ -22,13 +22,14 @@
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+import org.apache.cayenne.configuration.DbAdapterDetector;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.DbAdapterFactory;
 
 /**
  * @since 1.2
  */
-public class OracleSniffer implements DbAdapterFactory {
+public class OracleSniffer implements DbAdapterFactory, DbAdapterDetector {
 
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/postgres/PostgresSniffer.java Sun Dec  6 11:22:19 2009
@@ -22,13 +22,14 @@
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+import org.apache.cayenne.configuration.DbAdapterDetector;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.DbAdapterFactory;
 
 /**
  * @since 1.2
  */
-public class PostgresSniffer implements DbAdapterFactory {
+public class PostgresSniffer implements DbAdapterFactory, DbAdapterDetector {
 
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sqlite/SQLiteSniffer.java Sun Dec  6 11:22:19 2009
@@ -21,6 +21,7 @@
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+import org.apache.cayenne.configuration.DbAdapterDetector;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.DbAdapterFactory;
 
@@ -29,7 +30,7 @@
  * 
  * @since 3.0
  */
-public class SQLiteSniffer implements DbAdapterFactory {
+public class SQLiteSniffer implements DbAdapterFactory, DbAdapterDetector {
 
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerSniffer.java Sun Dec  6 11:22:19 2009
@@ -22,6 +22,7 @@
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+import org.apache.cayenne.configuration.DbAdapterDetector;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.DbAdapterFactory;
 
@@ -30,7 +31,7 @@
  * 
  * @since 1.2
  */
-public class SQLServerSniffer implements DbAdapterFactory {
+public class SQLServerSniffer implements DbAdapterFactory, DbAdapterDetector {
 
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
         String dbName = md.getDatabaseProductName();

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/dba/sybase/SybaseSniffer.java Sun Dec  6 11:22:19 2009
@@ -22,6 +22,7 @@
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+import org.apache.cayenne.configuration.DbAdapterDetector;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.DbAdapterFactory;
 
@@ -30,7 +31,7 @@
  * 
  * @since 1.2
  */
-public class SybaseSniffer implements DbAdapterFactory {
+public class SybaseSniffer implements DbAdapterFactory, DbAdapterDetector {
 
     public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {    	
     	// JTDS driver returns "sql server" for Sybase, so need to handle it differently

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataDomainProvider.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataDomainProvider.java?rev=887667&r1=887666&r2=887667&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataDomainProvider.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/runtime/DataDomainProvider.java Sun Dec  6 11:22:19 2009
@@ -18,22 +18,24 @@
  ****************************************************************/
 package org.apache.cayenne.runtime;
 
-import org.apache.cayenne.CayenneRuntimeException;
+import javax.sql.DataSource;
+
 import org.apache.cayenne.DataChannel;
 import org.apache.cayenne.access.DataDomain;
 import org.apache.cayenne.access.DataNode;
 import org.apache.cayenne.access.dbsync.SchemaUpdateStrategy;
+import org.apache.cayenne.configuration.AdhocObjectFactory;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.configuration.DataSourceFactory;
+import org.apache.cayenne.configuration.DataSourceFactoryLoader;
+import org.apache.cayenne.configuration.DbAdapterFactory;
 import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.di.DIException;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.di.Provider;
 import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.util.Util;
 
 /**
  * A {@link DataChannel} provider that provides a single instance of DataDomain configured
@@ -53,13 +55,13 @@
     protected SchemaUpdateStrategy defaultSchemaUpdateStrategy;
 
     @Inject
-    protected DbAdapter defaultAdapter;
+    protected DbAdapterFactory adapterFactory;
 
     @Inject
-    protected DataSourceFactory defaultDataSourceFactory;
+    protected DataSourceFactoryLoader dataSourceFactoryLoader;
 
     @Inject
-    protected Injector injector;
+    protected AdhocObjectFactory objectFactory;
 
     protected volatile DataChannel dataChannel;
 
@@ -68,7 +70,17 @@
         if (dataChannel == null) {
             synchronized (this) {
                 if (dataChannel == null) {
-                    createDataChannel();
+
+                    try {
+                        createDataChannel();
+                    }
+                    catch (DIException e) {
+                        throw e;
+                    }
+                    catch (Exception e) {
+                        throw new DIException("Error loading DataChannel: '%s'", e, e
+                                .getMessage());
+                    }
                 }
             }
         }
@@ -76,7 +88,7 @@
         return dataChannel;
     }
 
-    protected void createDataChannel() {
+    protected void createDataChannel() throws Exception {
         String runtimeName = configurationProperties
                 .get(RuntimeProperties.CAYENNE_RUNTIME_NAME);
         DataChannelDescriptor descriptor = loader.load(runtimeName);
@@ -94,21 +106,13 @@
 
             dataNode.setDataSourceLocation(nodeDescriptor.getLocation());
 
-            String dataSourceFactoryType = nodeDescriptor.getDataSourceFactoryType();
-            if (dataSourceFactoryType == null) {
-                dataNode.setDataSourceFactory(defaultDataSourceFactory
-                        .getClass()
-                        .getName());
-                dataNode.setDataSource(defaultDataSourceFactory
-                        .getDataSource(nodeDescriptor));
-            }
-            else {
-                dataNode.setDataSourceFactory(dataSourceFactoryType);
-                DataSourceFactory factory = newInstance(
-                        DataSourceFactory.class,
-                        dataSourceFactoryType);
-                dataNode.setDataSource(factory.getDataSource(nodeDescriptor));
-            }
+            DataSourceFactory dataSourceFactory = dataSourceFactoryLoader
+                    .getDataSourceFactory(nodeDescriptor);
+
+            DataSource dataSource = dataSourceFactory.getDataSource(nodeDescriptor);
+
+            dataNode.setDataSourceFactory(nodeDescriptor.getDataSourceFactoryType());
+            dataNode.setDataSource(dataSource);
 
             // schema update strategy
             String schemaUpdateStrategyType = nodeDescriptor
@@ -121,20 +125,16 @@
                         .getName());
             }
             else {
-                dataNode.setSchemaUpdateStrategyName(schemaUpdateStrategyType);
-                dataNode.setSchemaUpdateStrategy(newInstance(
+
+                SchemaUpdateStrategy strategy = objectFactory.newInstance(
                         SchemaUpdateStrategy.class,
-                        schemaUpdateStrategyType));
+                        schemaUpdateStrategyType);
+                dataNode.setSchemaUpdateStrategyName(schemaUpdateStrategyType);
+                dataNode.setSchemaUpdateStrategy(strategy);
             }
 
             // DbAdapter
-            String adapterType = nodeDescriptor.getAdapterType();
-            if (adapterType == null) {
-                dataNode.setAdapter(defaultAdapter);
-            }
-            else {
-                dataNode.setAdapter(newInstance(DbAdapter.class, adapterType));
-            }
+            dataNode.setAdapter(adapterFactory.createAdapter(nodeDescriptor, dataSource));
 
             // DataMaps
             for (String dataMapName : nodeDescriptor.getDataMapNames()) {
@@ -147,32 +147,4 @@
         this.dataChannel = dataChannel;
     }
 
-    private <T> T newInstance(Class<? extends T> interfaceType, String className) {
-
-        Class<? extends T> type;
-        try {
-            type = (Class<? extends T>) Util.getJavaClass(className);
-        }
-        catch (ClassNotFoundException e) {
-            throw new CayenneRuntimeException(
-                    "Invalid class %s of type %s",
-                    e,
-                    className,
-                    interfaceType.getName());
-        }
-        T instance;
-        try {
-            instance = type.newInstance();
-        }
-        catch (Exception e) {
-            throw new CayenneRuntimeException(
-                    "Error creating instance of class %s of type %s",
-                    e,
-                    className,
-                    interfaceType.getName());
-        }
-
-        injector.injectMembers(instance);
-        return instance;
-    }
 }