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/16 05:11:58 UTC

svn commit: r891118 - in /cayenne/main/trunk/framework: cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/ cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/ cayenne-project-unpublished/src/main/java/...

Author: aadamchik
Date: Wed Dec 16 04:11:57 2009
New Revision: 891118

URL: http://svn.apache.org/viewvc?rev=891118&view=rev
Log:
CAY-1329 DI-based cayenne-project module

* project upgrade framework - in progress
* some cleanup and refactoring of the project package

Added:
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java
      - copied, changed from r890629, cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataChananelDescriptorLoader_V3_0_0_1.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataSourceInfoLoader_V3_0_0_1.java
Removed:
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataChananelDescriptorLoader_V3_0_0_1.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/BaseUpgradeHandler.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/UpgradeHandler_V6.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/unit/Project2Case.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/upgrade/v6/ProjectUpgrader_V6Test.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/resources/org/apache/cayenne/project2/upgrade/v6/3_0_0_1a/d1NodeDriver.driver.xml

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java?rev=891118&r1=891117&r2=891118&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java Wed Dec 16 04:11:57 2009
@@ -24,8 +24,6 @@
 import java.io.InputStreamReader;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
 
 import org.apache.cayenne.ConfigurationException;
 import org.apache.cayenne.conf.PasswordEncoding;
@@ -55,21 +53,6 @@
     static final String MAP_REF_TAG = "map-ref";
     static final String DATA_SOURCE_TAG = "data-source";
 
-    private static final Map<String, String> dataSourceFactoryLegacyNameMapping;
-
-    static {
-        dataSourceFactoryLegacyNameMapping = new HashMap<String, String>();
-        dataSourceFactoryLegacyNameMapping.put(
-                "org.apache.cayenne.conf.DriverDataSourceFactory",
-                XMLPoolingDataSourceFactory.class.getName());
-        dataSourceFactoryLegacyNameMapping.put(
-                "org.apache.cayenne.conf.JNDIDataSourceFactory",
-                JNDIDataSourceFactory.class.getName());
-        dataSourceFactoryLegacyNameMapping.put(
-                "org.apache.cayenne.conf.DBCPDataSourceFactory",
-                DBCPDataSourceFactory.class.getName());
-    }
-
     /**
      * @deprecated the caller should use password resolving strategy instead of resolving
      *             the password on the spot. For one thing this can be used in the Modeler
@@ -183,20 +166,6 @@
         return descriptor;
     }
 
-    /**
-     * Converts the names of standard Cayenne-supplied DataSourceFactories from the legacy
-     * names to the current names.
-     */
-    private String convertDataSourceFactory(String dataSourceFactory) {
-
-        if (dataSourceFactory == null) {
-            return null;
-        }
-
-        String converted = dataSourceFactoryLegacyNameMapping.get(dataSourceFactory);
-        return converted != null ? converted : dataSourceFactory;
-    }
-
     final class DataChannelHandler extends SAXNestedTagHandler {
 
         private DataChannelDescriptor descriptor;
@@ -283,8 +252,7 @@
                 nodeDescriptor.setParameters(parameters);
 
                 String dataSourceFactory = attributes.getValue("", "factory");
-                nodeDescriptor
-                        .setDataSourceFactoryType(convertDataSourceFactory(dataSourceFactory));
+                nodeDescriptor.setDataSourceFactoryType(dataSourceFactory);
                 nodeDescriptor.setSchemaUpdateStrategyType(attributes.getValue(
                         "",
                         "schema-update-strategy"));

Modified: cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/BaseUpgradeHandler.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/BaseUpgradeHandler.java?rev=891118&r1=891117&r2=891118&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/BaseUpgradeHandler.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/BaseUpgradeHandler.java Wed Dec 16 04:11:57 2009
@@ -76,14 +76,21 @@
                 throw new ConfigurationException(
                         "Upgrade can not be performed - intermediate version upgrade needed");
             case UPGRADE_NEEDED:
-                return performNeededUpgrade();
+                return doPerformUpgrade();
             default:
                 return getProjectSource();
         }
     }
 
-    protected abstract Resource performNeededUpgrade() throws ConfigurationException;
+    /**
+     * Does the actual project upgrade, assuming the caller already verified that the
+     * upgrade is possible.
+     */
+    protected abstract Resource doPerformUpgrade() throws ConfigurationException;
 
+    /**
+     * Creates a metadata object describing the type of upgrade needed.
+     */
     protected abstract UpgradeMetaData loadMetaData();
 
     /**
@@ -106,7 +113,6 @@
         }
         catch (SAXException e) {
             // expected ... handler will terminate as soon as it finds a root tag.
-
         }
         catch (Exception e) {
             throw new ConfigurationException(

Modified: cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/UpgradeHandler_V6.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/UpgradeHandler_V6.java?rev=891118&r1=891117&r2=891118&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/UpgradeHandler_V6.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/UpgradeHandler_V6.java Wed Dec 16 04:11:57 2009
@@ -18,10 +18,14 @@
  ****************************************************************/
 package org.apache.cayenne.project2.upgrade.v6;
 
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 import org.apache.cayenne.ConfigurationException;
 import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.project2.Project;
 import org.apache.cayenne.project2.ProjectSaver;
@@ -29,6 +33,7 @@
 import org.apache.cayenne.project2.upgrade.UpgradeMetaData;
 import org.apache.cayenne.project2.upgrade.UpgradeType;
 import org.apache.cayenne.resource.Resource;
+import org.apache.cayenne.util.Util;
 
 /**
  * @since 3.1
@@ -42,7 +47,7 @@
      * Notice that the loader is statically typed, intentionally not using DI to ensure
      * predictable behavior on legacy upgrades.
      */
-    private XMLDataChananelDescriptorLoader_V3_0_0_1 projectLoader;
+    private XMLDataChannelDescriptorLoader_V3_0_0_1 projectLoader;
 
     /**
      * Unlike loader, saver is injected, so that we can save dynamically with the latest
@@ -53,7 +58,7 @@
 
     UpgradeHandler_V6(Resource source) {
         super(source);
-        this.projectLoader = new XMLDataChananelDescriptorLoader_V3_0_0_1();
+        this.projectLoader = new XMLDataChannelDescriptorLoader_V3_0_0_1();
     }
 
     @Override
@@ -85,7 +90,7 @@
     }
 
     @Override
-    protected Resource performNeededUpgrade() throws ConfigurationException {
+    protected Resource doPerformUpgrade() throws ConfigurationException {
 
         List<DataChannelDescriptor> domains = projectLoader.load(projectSource);
         if (domains.isEmpty()) {
@@ -95,12 +100,38 @@
             domains.add(descriptor);
         }
 
+        // collect resources to delete before the upgrade...
+        Collection<Resource> resourcesToDelete = new ArrayList<Resource>();
         for (DataChannelDescriptor descriptor : domains) {
+            for (DataNodeDescriptor node : descriptor.getNodeDescriptors()) {
+                Resource nodeResource = node.getConfigurationSource();
+                if (nodeResource != null) {
+                    resourcesToDelete.add(nodeResource);
+                }
+            }
+        }
 
+        // save in the new format
+        for (DataChannelDescriptor descriptor : domains) {
             Project project = new Project(descriptor);
+
+            // side effect of that is deletion of the common "cayenne.xml"
             projectSaver.save(project);
         }
 
+        // delete all .driver.xml files
+        for (Resource resource : resourcesToDelete) {
+            try {
+                File file = Util.toFile(resource.getURL());
+                if (file.exists() && file.getName().endsWith(".driver.xml")) {
+                    file.delete();
+                }
+            }
+            catch (Exception e) {
+                // ignore...
+            }
+        }
+
         // returns the first domain configuration out of possibly multiple new
         // configurations...
         return domains.get(0).getConfigurationSource();

Copied: cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java (from r890629, cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataChananelDescriptorLoader_V3_0_0_1.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java?p2=cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java&p1=cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataChananelDescriptorLoader_V3_0_0_1.java&r1=890629&r2=891118&rev=891118&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataChananelDescriptorLoader_V3_0_0_1.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataChannelDescriptorLoader_V3_0_0_1.java Wed Dec 16 04:11:57 2009
@@ -34,6 +34,7 @@
 import org.apache.cayenne.configuration.JNDIDataSourceFactory;
 import org.apache.cayenne.configuration.SAXNestedTagHandler;
 import org.apache.cayenne.configuration.XMLPoolingDataSourceFactory;
+import org.apache.cayenne.conn.DataSourceInfo;
 import org.apache.cayenne.map.DataMap;
 import org.apache.cayenne.resource.Resource;
 import org.apache.cayenne.util.Util;
@@ -47,10 +48,10 @@
 /**
  * A loader of Cayenne projects descriptor for version "3.0.0.1".
  */
-class XMLDataChananelDescriptorLoader_V3_0_0_1 {
+class XMLDataChannelDescriptorLoader_V3_0_0_1 {
 
     private static Log logger = LogFactory
-            .getLog(XMLDataChananelDescriptorLoader_V3_0_0_1.class);
+            .getLog(XMLDataChannelDescriptorLoader_V3_0_0_1.class);
 
     static final String DOMAINS_TAG = "domains";
     static final String DOMAIN_TAG = "domain";
@@ -76,9 +77,11 @@
 
     // implementation is statically typed and is intentionally not DI-provided
     protected XMLDataMapLoader_V3_0_0_1 mapLoader;
+    protected XMLDataSourceInfoLoader_V3_0_0_1 dataSourceInfoLoader;
 
-    XMLDataChananelDescriptorLoader_V3_0_0_1() {
-        this.mapLoader = new XMLDataMapLoader_V3_0_0_1();
+    XMLDataChannelDescriptorLoader_V3_0_0_1() {
+        mapLoader = new XMLDataMapLoader_V3_0_0_1();
+        dataSourceInfoLoader = new XMLDataSourceInfoLoader_V3_0_0_1();
     }
 
     List<DataChannelDescriptor> load(Resource configurationSource)
@@ -90,7 +93,6 @@
 
         URL configurationURL = configurationSource.getURL();
 
-        // using linked map to perform upgrade in the order of domains in the old config
         List<DataChannelDescriptor> domains = new ArrayList<DataChannelDescriptor>();
         InputStream in = null;
 
@@ -249,23 +251,38 @@
 
                 String nodeName = attributes.getValue("", "name");
                 if (nodeName == null) {
+                    // TODO: assign dummy name?
                     throw new ConfigurationException("Error: <node> without 'name'.");
                 }
 
                 DataNodeDescriptor nodeDescriptor = new DataNodeDescriptor();
-                nodeDescriptor
-                        .setConfigurationSource(descriptor.getConfigurationSource());
-                descriptor.getNodeDescriptors().add(nodeDescriptor);
-
                 nodeDescriptor.setName(nodeName);
-                nodeDescriptor.setAdapterType(attributes.getValue("", "adapter"));
-
-                String parameters = attributes.getValue("", "parameters");
-                nodeDescriptor.setParameters(parameters);
 
                 String dataSourceFactory = attributes.getValue("", "factory");
-                nodeDescriptor
-                        .setDataSourceFactoryType(convertDataSourceFactory(dataSourceFactory));
+                String dataSourceFactory6 = convertDataSourceFactory(dataSourceFactory);
+                nodeDescriptor.setDataSourceFactoryType(dataSourceFactory6);
+
+                // depending on the factory, "datasource" attribute is interpreted
+                // differently
+                String datasource = attributes.getValue("", "datasource");
+                if (XMLPoolingDataSourceFactory.class
+                        .getName()
+                        .equals(dataSourceFactory6)) {
+                    Resource baseResource = descriptor.getConfigurationSource();
+                    Resource dataNodeResource = baseResource
+                            .getRelativeResource(datasource);
+                    nodeDescriptor.setConfigurationSource(dataNodeResource);
+
+                    DataSourceInfo dataSourceInfo = dataSourceInfoLoader
+                            .load(dataNodeResource);
+                    nodeDescriptor.setDataSourceDescriptor(dataSourceInfo);
+                }
+                else {
+                    nodeDescriptor.setParameters(datasource);
+                }
+
+                descriptor.getNodeDescriptors().add(nodeDescriptor);
+                nodeDescriptor.setAdapterType(attributes.getValue("", "adapter"));
                 nodeDescriptor.setSchemaUpdateStrategyType(attributes.getValue(
                         "",
                         "schema-update-strategy"));

Added: cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataSourceInfoLoader_V3_0_0_1.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataSourceInfoLoader_V3_0_0_1.java?rev=891118&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataSourceInfoLoader_V3_0_0_1.java (added)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataSourceInfoLoader_V3_0_0_1.java Wed Dec 16 04:11:57 2009
@@ -0,0 +1,302 @@
+/*****************************************************************
+ *   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.project2.upgrade.v6;
+
+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 org.apache.cayenne.ConfigurationException;
+import org.apache.cayenne.conf.PasswordEncoding;
+import org.apache.cayenne.configuration.SAXNestedTagHandler;
+import org.apache.cayenne.conn.DataSourceInfo;
+import org.apache.cayenne.resource.Resource;
+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;
+
+/**
+ * @since 3.1
+ */
+class XMLDataSourceInfoLoader_V3_0_0_1 {
+
+    private static Log logger = LogFactory.getLog(XMLDataSourceInfoLoader_V3_0_0_1.class);
+
+    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;
+    }
+
+    DataSourceInfo load(Resource configurationSource) {
+        if (configurationSource == null) {
+            throw new NullPointerException("Null configurationSource");
+        }
+
+        URL configurationURL = configurationSource.getURL();
+
+        DataSourceInfo dataSourceInfo = new DataSourceInfo();
+
+        InputStream in = null;
+
+        try {
+            in = configurationURL.openStream();
+            XMLReader parser = Util.createXmlReader();
+
+            DriverHandler rootHandler = new DriverHandler(parser, dataSourceInfo);
+            parser.setContentHandler(rootHandler);
+            parser.setErrorHandler(rootHandler);
+            parser.parse(new InputSource(in));
+        }
+        catch (Exception e) {
+            throw new ConfigurationException(
+                    "Error loading configuration from %s",
+                    e,
+                    configurationURL);
+        }
+        finally {
+            try {
+                if (in != null) {
+                    in.close();
+                }
+            }
+            catch (IOException ioex) {
+                logger.info("failure closing input stream for "
+                        + configurationURL
+                        + ", ignoring", ioex);
+            }
+        }
+
+        return dataSourceInfo;
+    }
+
+    final class DriverHandler extends SAXNestedTagHandler {
+
+        private DataSourceInfo dataSourceDescriptor;
+
+        DriverHandler(XMLReader parser, DataSourceInfo dataSourceDescriptor) {
+            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");
+                dataSourceDescriptor.setJdbcDriver(className);
+                
+                return new DataSourceChildrenHandler(parser, this);
+            }
+
+            return super.createChildTagHandler(namespaceURI, localName, name, attributes);
+        }
+    }
+
+    class DataSourceChildrenHandler extends SAXNestedTagHandler {
+
+        private DataSourceInfo dataSourceDescriptor;
+
+        DataSourceChildrenHandler(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)) {
+
+                        ClassLoader classLoader = Thread
+                                .currentThread()
+                                .getContextClassLoader();
+                        URL url = classLoader.getResource(username);
+                        if (url != null) {
+                            password = passwordFromURL(url);
+                        }
+                        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-project-unpublished/src/test/java/org/apache/cayenne/project2/unit/Project2Case.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/unit/Project2Case.java?rev=891118&r1=891117&r2=891118&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/unit/Project2Case.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/unit/Project2Case.java Wed Dec 16 04:11:57 2009
@@ -19,14 +19,47 @@
 package org.apache.cayenne.project2.unit;
 
 import java.io.File;
+import java.io.IOException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
 
 import junit.framework.TestCase;
 
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.util.Util;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
 
 public class Project2Case extends TestCase {
 
+    /**
+     * A helper method returning the contents of an XML source as a DOM Document.
+     * 
+     * @throws IOException
+     * @throws SAXException
+     */
+    protected Document toDOMTree(File file) {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        DocumentBuilder domParser;
+        try {
+            domParser = dbf.newDocumentBuilder();
+        }
+        catch (ParserConfigurationException e) {
+            fail("ParserConfigurationException: " + e.getMessage());
+            throw new RuntimeException();
+        }
+
+        try {
+            return domParser.parse(file);
+        }
+        catch (Exception e) {
+            fail("DOM parsing exception: " + e.getMessage());
+            throw new RuntimeException();
+        }
+    }
+
     protected File setupTestDirectory(String subfolder) {
         String packagePath = getClass().getPackage().getName().replace('.', '/');
         String location = "target/testrun/" + packagePath + "/" + subfolder;

Modified: cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/upgrade/v6/ProjectUpgrader_V6Test.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/upgrade/v6/ProjectUpgrader_V6Test.java?rev=891118&r1=891117&r2=891118&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/upgrade/v6/ProjectUpgrader_V6Test.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/upgrade/v6/ProjectUpgrader_V6Test.java Wed Dec 16 04:11:57 2009
@@ -23,8 +23,13 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
 import org.apache.cayenne.configuration.ConfigurationNameMapper;
 import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
+import org.apache.cayenne.configuration.XMLPoolingDataSourceFactory;
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
@@ -38,6 +43,9 @@
 import org.apache.cayenne.resource.Resource;
 import org.apache.cayenne.resource.URLResource;
 import org.apache.cayenne.util.Util;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 public class ProjectUpgrader_V6Test extends Project2Case {
 
@@ -186,29 +194,88 @@
         assertNotSame(source, upgrader);
 
         // check that all the new files are created...
-        List<String> targets = new ArrayList<String>();
+        String[] targetsAfterNames = new String[] {
+                "cayenne-d1.xml", "cayenne-d2.xml", "d1Map1.map.xml", "d1Map2.map.xml"
+        };
 
-        targets.add("cayenne-d1.xml");
-        targets.add("cayenne-d2.xml");
-        targets.add("d1Map1.map.xml");
-        targets.add("d1Map2.map.xml");
-        for (String targetName : targets) {
-            File target = new File(testFolder, targetName);
-            assertTrue("File was not created: " + target.getAbsolutePath(), target
-                    .exists());
+        File[] targetsAfter = new File[targetsAfterNames.length];
+        for (int i = 0; i < targetsAfter.length; i++) {
+            targetsAfter[i] = new File(testFolder, targetsAfterNames[i]);
+            assertTrue(
+                    "File was not created: " + targetsAfter[i].getAbsolutePath(),
+                    targetsAfter[i].exists());
         }
 
         // DataMap files should remain the same; all others need to be deleted
-//        for (File file : targetsBefore) {
-//            if (file.getName().endsWith(".map.xml")) {
-//                assertTrue("DataMap file disappeared: " + file.getAbsolutePath(), file
-//                        .exists());
-//            }
-//            else {
-//                assertFalse(
-//                        "File expected to be deleted: " + file.getAbsolutePath(),
-//                        file.exists());
-//            }
-//        }
+        for (File file : targetsBefore) {
+            if (file.getName().endsWith(".map.xml")) {
+                assertTrue("DataMap file disappeared: " + file.getAbsolutePath(), file
+                        .exists());
+            }
+            else {
+                assertFalse(
+                        "File expected to be deleted: " + file.getAbsolutePath(),
+                        file.exists());
+            }
+        }
+
+        // assert XML structure of the generated files
+        assertPerformUpgrade_3_0_0_1_cayenne_d1(targetsAfter[0]);
+    }
+
+    private void assertPerformUpgrade_3_0_0_1_cayenne_d1(File file) throws Exception {
+        Document document = toDOMTree(file);
+
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        assertEquals("d1", xpath.evaluate("/domain/@name", document));
+        assertEquals("6", xpath.evaluate("/domain/@project-version", document));
+
+        NodeList maps = (NodeList) xpath.evaluate(
+                "/domain/map",
+                document,
+                XPathConstants.NODESET);
+        assertNotNull(maps);
+        assertEquals(2, maps.getLength());
+
+        Node map1 = maps.item(0);
+        Node map2 = maps.item(1);
+
+        assertEquals("d1Map1", xpath.evaluate("@name", map1));
+        assertEquals("d1Map2", xpath.evaluate("@name", map2));
+
+        NodeList nodes = (NodeList) xpath.evaluate(
+                "/domain/node",
+                document,
+                XPathConstants.NODESET);
+        assertNotNull(nodes);
+        assertEquals(1, nodes.getLength());
+
+        Node node1 = nodes.item(0);
+
+        assertEquals("d1NodeDriver", xpath.evaluate("@name", node1));
+        assertEquals(XMLPoolingDataSourceFactory.class.getName(), xpath.evaluate(
+                "@factory",
+                node1));
+
+        NodeList mapRefs = (NodeList) xpath.evaluate(
+                "map-ref",
+                node1,
+                XPathConstants.NODESET);
+        assertNotNull(mapRefs);
+        assertEquals(2, mapRefs.getLength());
+
+        assertEquals("d1Map1", xpath.evaluate("@name", mapRefs.item(0)));
+        assertEquals("d1Map2", xpath.evaluate("@name", mapRefs.item(1)));
+
+        NodeList dataSources = (NodeList) xpath.evaluate(
+                "data-source",
+                node1,
+                XPathConstants.NODESET);
+        assertNotNull(dataSources);
+        assertEquals(1, dataSources.getLength());
+        
+        Node ds = dataSources.item(0);
+        assertEquals("org.hsqldb.jdbcDriver", xpath.evaluate("driver/@value", ds));
+        assertEquals("jdbc:hsqldb:mem:xdb", xpath.evaluate("url/@value", ds));
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/resources/org/apache/cayenne/project2/upgrade/v6/3_0_0_1a/d1NodeDriver.driver.xml
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/resources/org/apache/cayenne/project2/upgrade/v6/3_0_0_1a/d1NodeDriver.driver.xml?rev=891118&r1=891117&r2=891118&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/resources/org/apache/cayenne/project2/upgrade/v6/3_0_0_1a/d1NodeDriver.driver.xml (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/resources/org/apache/cayenne/project2/upgrade/v6/3_0_0_1a/d1NodeDriver.driver.xml Wed Dec 16 04:11:57 2009
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <driver project-version="3.0.0.1" class="org.hsqldb.jdbcDriver">
 	<url value="jdbc:hsqldb:mem:xdb"/>
-	<connectionPool min="1" max="1"/>
+	<connectionPool min="1" max="5"/>
 	<login userName="user" password="password"/>
 </driver>