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/15 04:34:22 UTC

svn commit: r890629 - in /cayenne/main/trunk/framework: cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/ cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ cayenne-jdk1.5-unpublished/src/main/java/org/apache/caye...

Author: aadamchik
Date: Tue Dec 15 03:34:21 2009
New Revision: 890629

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

    * project upgrade framework - in progress

Added:
    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/XMLDataMapLoader_V3_0_0_1.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/unit/
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/unit/Project2Case.java
      - copied, changed from r890504, cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/ProjectTest.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoader.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DataMap.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/XMLEncoder.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoaderTest.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/ConfigurationSaver.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/DataChannelProjectLoader.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/FileProjectSaver.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/Project.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/ProjectSaver.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/ProjectUpgrader_V6.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/DataChannelProjectLoaderTest.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/DataChannelProjectSaverTest.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/ProjectTest.java
    cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/upgrade/v6/ProjectUpgrader_V6Test.java

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java?rev=890629&r1=890628&r2=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/configuration/DataChannelDescriptor.java Tue Dec 15 03:34:21 2009
@@ -37,7 +37,6 @@
 public class DataChannelDescriptor implements ConfigurationNode, XMLSerializable {
 
     protected String name;
-    protected String version;
     protected Map<String, String> properties;
     protected Collection<DataMap> dataMaps;
     protected Collection<DataNodeDescriptor> nodeDescriptors;
@@ -53,7 +52,7 @@
 
         encoder.print("<domain");
         encoder.printAttribute("name", name);
-        encoder.printAttribute("project-version", version);
+        encoder.printProjectVersion();
         encoder.println(">");
 
         encoder.indent(1);
@@ -111,14 +110,6 @@
         this.name = name;
     }
 
-    public String getVersion() {
-        return version;
-    }
-
-    public void setVersion(String version) {
-        this.version = version;
-    }
-
     public Map<String, String> getProperties() {
         return properties;
     }

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=890629&r1=890628&r2=890629&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 Tue Dec 15 03:34:21 2009
@@ -214,9 +214,6 @@
                 Attributes attributes) {
 
             if (localName.equals(DOMAIN_TAG)) {
-                String version = attributes.getValue("", "project-version");
-                descriptor.setVersion(version);
-
                 return new DataChannelChildrenHandler(parser, this);
             }
 

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DataMap.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DataMap.java?rev=890629&r1=890628&r2=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DataMap.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DataMap.java Tue Dec 15 03:34:21 2009
@@ -36,7 +36,6 @@
 import org.apache.cayenne.map.event.DbEntityListener;
 import org.apache.cayenne.map.event.EntityEvent;
 import org.apache.cayenne.map.event.ObjEntityListener;
-import org.apache.cayenne.project.Project;
 import org.apache.cayenne.query.NamedQuery;
 import org.apache.cayenne.query.Query;
 import org.apache.cayenne.resource.Resource;
@@ -284,15 +283,17 @@
     public void encodeAsXML(XMLEncoder encoder) {
         encoder
                 .println("<data-map xmlns=\"http://cayenne.apache.org/schema/3.0/modelMap\"");
-        encoder.println("  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
-        encoder.println("  xsi:schemaLocation=\""
+
+        encoder.indent(1);
+        encoder.println(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
+        encoder.println(" xsi:schemaLocation=\""
                 + SCHEMA_XSD
                 + " "
                 + SCHEMA_XSD
                 + ".xsd\"");
-        encoder.println("  project-version=\"" + Project.CURRENT_PROJECT_VERSION + "\">");
 
-        encoder.indent(1);
+        encoder.printProjectVersion();
+        encoder.println(">");
 
         // properties
         if (defaultLockType == ObjEntity.LOCK_TYPE_OPTIMISTIC) {

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/XMLEncoder.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/XMLEncoder.java?rev=890629&r1=890628&r2=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/XMLEncoder.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/XMLEncoder.java Tue Dec 15 03:34:21 2009
@@ -30,6 +30,7 @@
  */
 public class XMLEncoder {
 
+    protected String projectVersion;
     protected String indent;
     protected PrintWriter out;
 
@@ -37,12 +38,20 @@
     protected int indentTimes;
 
     public XMLEncoder(PrintWriter out) {
-        this.out = out;
+        this(out, null, null);
     }
 
     public XMLEncoder(PrintWriter out, String indent) {
+        this(out, indent, null);
+    }
+
+    /**
+     * @since 3.1
+     */
+    public XMLEncoder(PrintWriter out, String indent, String projectVersion) {
         this.indent = indent;
         this.out = out;
+        this.projectVersion = projectVersion;
     }
 
     public PrintWriter getPrintWriter() {
@@ -77,6 +86,16 @@
     }
 
     /**
+     * Inserts an optional project version attribute in the output. If the project version
+     * is not initialized for encoder, will do nothing.
+     * 
+     * @since 3.1
+     */
+    public void printProjectVersion() {
+        printAttribute("project-version", projectVersion);
+    }
+
+    /**
      * Prints an XML attribute. The value is trimmed (so leading and following spaces are
      * lost) and then encoded to be a proper XML attribute value. E.g. "&" becomes
      * "&amp;", etc.

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoaderTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoaderTest.java?rev=890629&r1=890628&r2=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoaderTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/configuration/XMLDataChannelDescriptorLoaderTest.java Tue Dec 15 03:34:21 2009
@@ -155,7 +155,6 @@
         assertNotNull(descriptor);
 
         assertEquals(testConfigName, descriptor.getName());
-        assertEquals("6", descriptor.getVersion());
 
         Collection<DataMap> maps = descriptor.getDataMaps();
         assertEquals(2, maps.size());

Modified: cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/ConfigurationSaver.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/ConfigurationSaver.java?rev=890629&r1=890628&r2=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/ConfigurationSaver.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/ConfigurationSaver.java Tue Dec 15 03:34:21 2009
@@ -31,20 +31,22 @@
 class ConfigurationSaver implements ConfigurationNodeVisitor<Void> {
 
     private PrintWriter printWriter;
+    private String version;
 
-    ConfigurationSaver(PrintWriter printWriter) {
+    ConfigurationSaver(PrintWriter printWriter, String version) {
         this.printWriter = printWriter;
+        this.version = version;
     }
 
     public Void visitDataChannelDescriptor(DataChannelDescriptor node) {
-        XMLEncoder encoder = new XMLEncoder(printWriter, "\t");
+        XMLEncoder encoder = new XMLEncoder(printWriter, "\t", version);
         printXMLHeader(encoder);
         node.encodeAsXML(encoder);
         return null;
     }
 
     public Void visitDataMap(DataMap node) {
-        XMLEncoder encoder = new XMLEncoder(printWriter, "\t");
+        XMLEncoder encoder = new XMLEncoder(printWriter, "\t", version);
         printXMLHeader(encoder);
         node.encodeAsXML(encoder);
         return null;

Modified: cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/DataChannelProjectLoader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/DataChannelProjectLoader.java?rev=890629&r1=890628&r2=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/DataChannelProjectLoader.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/DataChannelProjectLoader.java Tue Dec 15 03:34:21 2009
@@ -35,9 +35,6 @@
 
     public Project loadProject(Resource source) {
         DataChannelDescriptor descriptor = loader.load(source);
-
-        Project project = new Project(descriptor);
-        project.setVersion(descriptor.getVersion());
-        return project;
+        return new Project(descriptor);
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/FileProjectSaver.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/FileProjectSaver.java?rev=890629&r1=890628&r2=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/FileProjectSaver.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/FileProjectSaver.java Tue Dec 15 03:34:21 2009
@@ -61,6 +61,10 @@
         fileEncoding = "UTF-8";
     }
 
+    public String getSupportedVersion() {
+        return "6";
+    }
+
     public void save(Project project) {
 
         Collection<ConfigurationNode> nodes = project.getRootNode().acceptVisitor(
@@ -233,7 +237,8 @@
     }
 
     void saveToTempFile(SaveUnit unit, PrintWriter printWriter) {
-        unit.node.acceptVisitor(new ConfigurationSaver(printWriter));
+        unit.node
+                .acceptVisitor(new ConfigurationSaver(printWriter, getSupportedVersion()));
     }
 
     void saveCommit(Collection<SaveUnit> units) {

Modified: cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/Project.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/Project.java?rev=890629&r1=890628&r2=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/Project.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/Project.java Tue Dec 15 03:34:21 2009
@@ -27,23 +27,17 @@
  * 
  * @since 3.1
  */
+// do we even need a project wrapper around ConfigurationNode, as currently it does
+// nothing?? Maybe in the future make it store configuration Resources for the project
+// nodes to avoid attaching them to descriptors?
 public class Project {
 
-    protected String version;
     protected ConfigurationNode rootNode;
 
     public Project(ConfigurationNode rootNode) {
         this.rootNode = rootNode;
     }
 
-    public String getVersion() {
-        return version;
-    }
-
-    public void setVersion(String version) {
-        this.version = version;
-    }
-
     public ConfigurationNode getRootNode() {
         return rootNode;
     }

Modified: cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/ProjectSaver.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/ProjectSaver.java?rev=890629&r1=890628&r2=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/ProjectSaver.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/ProjectSaver.java Tue Dec 15 03:34:21 2009
@@ -28,6 +28,11 @@
 public interface ProjectSaver {
 
     /**
+     * Returns a version of the project configuration supported by the current runtime.
+     */
+    String getSupportedVersion();
+
+    /**
      * Saves project in the location of its current configuration sources. Since resource
      * names are determined using a naming convention based on the project node names, if
      * any of the nodes were renamed, the old locations will be deleted. After saving,

Modified: cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/ProjectUpgrader_V6.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/ProjectUpgrader_V6.java?rev=890629&r1=890628&r2=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/ProjectUpgrader_V6.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/ProjectUpgrader_V6.java Tue Dec 15 03:34:21 2009
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.cayenne.project2.upgrade.v6;
 
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.project2.upgrade.UpgradeHandler;
 import org.apache.cayenne.project2.upgrade.ProjectUpgrader;
 import org.apache.cayenne.resource.Resource;
@@ -29,8 +31,13 @@
  */
 public class ProjectUpgrader_V6 implements ProjectUpgrader {
 
+    @Inject
+    protected Injector injector;
+
     public UpgradeHandler getUpgradeHandler(Resource projectSource) {
-        return new UpgradeHandler_V6(projectSource);
+        UpgradeHandler_V6 handler = new UpgradeHandler_V6(projectSource);
+        injector.injectMembers(handler);
+        return handler;
     }
 
 }

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=890629&r1=890628&r2=890629&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 Tue Dec 15 03:34:21 2009
@@ -18,7 +18,13 @@
  ****************************************************************/
 package org.apache.cayenne.project2.upgrade.v6;
 
+import java.util.List;
+
 import org.apache.cayenne.ConfigurationException;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.project2.Project;
+import org.apache.cayenne.project2.ProjectSaver;
 import org.apache.cayenne.project2.upgrade.BaseUpgradeHandler;
 import org.apache.cayenne.project2.upgrade.UpgradeMetaData;
 import org.apache.cayenne.project2.upgrade.UpgradeType;
@@ -32,8 +38,22 @@
     static final String TO_VERSION = "6";
     static final String MIN_SUPPORTED_VERSION = "3.0.0.1";
 
+    /**
+     * 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;
+
+    /**
+     * Unlike loader, saver is injected, so that we can save dynamically with the latest
+     * version. This may change once this upgrade handler becomes an intermediate handler.
+     */
+    @Inject
+    private ProjectSaver projectSaver;
+
     UpgradeHandler_V6(Resource source) {
         super(source);
+        this.projectLoader = new XMLDataChananelDescriptorLoader_V3_0_0_1();
     }
 
     @Override
@@ -66,7 +86,23 @@
 
     @Override
     protected Resource performNeededUpgrade() throws ConfigurationException {
-        throw new UnsupportedOperationException("TODO");
-    }
 
+        List<DataChannelDescriptor> domains = projectLoader.load(projectSource);
+        if (domains.isEmpty()) {
+            // create a single domain dummy project if a noop config is being upgraded
+            DataChannelDescriptor descriptor = new DataChannelDescriptor();
+            descriptor.setName("DEFAULT");
+            domains.add(descriptor);
+        }
+
+        for (DataChannelDescriptor descriptor : domains) {
+
+            Project project = new Project(descriptor);
+            projectSaver.save(project);
+        }
+
+        // returns the first domain configuration out of possibly multiple new
+        // configurations...
+        return domains.get(0).getConfigurationSource();
+    }
 }

Added: 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/XMLDataChananelDescriptorLoader_V3_0_0_1.java?rev=890629&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataChananelDescriptorLoader_V3_0_0_1.java (added)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataChananelDescriptorLoader_V3_0_0_1.java Tue Dec 15 03:34:21 2009
@@ -0,0 +1,306 @@
+/*****************************************************************
+ *   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.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cayenne.ConfigurationException;
+import org.apache.cayenne.configuration.DBCPDataSourceFactory;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataNodeDescriptor;
+import org.apache.cayenne.configuration.JNDIDataSourceFactory;
+import org.apache.cayenne.configuration.SAXNestedTagHandler;
+import org.apache.cayenne.configuration.XMLPoolingDataSourceFactory;
+import org.apache.cayenne.map.DataMap;
+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;
+
+/**
+ * A loader of Cayenne projects descriptor for version "3.0.0.1".
+ */
+class XMLDataChananelDescriptorLoader_V3_0_0_1 {
+
+    private static Log logger = LogFactory
+            .getLog(XMLDataChananelDescriptorLoader_V3_0_0_1.class);
+
+    static final String DOMAINS_TAG = "domains";
+    static final String DOMAIN_TAG = "domain";
+    static final String MAP_TAG = "map";
+    static final String NODE_TAG = "node";
+    static final String PROPERTY_TAG = "property";
+    static final String MAP_REF_TAG = "map-ref";
+
+    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());
+    }
+
+    // implementation is statically typed and is intentionally not DI-provided
+    protected XMLDataMapLoader_V3_0_0_1 mapLoader;
+
+    XMLDataChananelDescriptorLoader_V3_0_0_1() {
+        this.mapLoader = new XMLDataMapLoader_V3_0_0_1();
+    }
+
+    List<DataChannelDescriptor> load(Resource configurationSource)
+            throws ConfigurationException {
+
+        if (configurationSource == null) {
+            throw new NullPointerException("Null configurationSource");
+        }
+
+        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;
+
+        try {
+            in = configurationURL.openStream();
+            XMLReader parser = Util.createXmlReader();
+
+            DomainsHandler rootHandler = new DomainsHandler(
+                    configurationSource,
+                    domains,
+                    parser);
+            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 domains;
+    }
+
+    /**
+     * 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 DomainsHandler extends SAXNestedTagHandler {
+
+        private Collection<DataChannelDescriptor> domains;
+        private Resource configurationSource;
+
+        DomainsHandler(Resource configurationSource,
+                Collection<DataChannelDescriptor> domains, XMLReader parser) {
+            super(parser, null);
+            this.domains = domains;
+            this.configurationSource = configurationSource;
+        }
+
+        @Override
+        protected ContentHandler createChildTagHandler(
+                String namespaceURI,
+                String localName,
+                String qName,
+                Attributes attributes) {
+
+            if (localName.equals(DOMAINS_TAG)) {
+                return new DomainsChildrenHandler(parser, this);
+            }
+
+            return super
+                    .createChildTagHandler(namespaceURI, localName, qName, attributes);
+        }
+    }
+
+    final class DomainsChildrenHandler extends SAXNestedTagHandler {
+
+        private Collection<DataChannelDescriptor> domains;
+        private Resource configurationSource;
+
+        DomainsChildrenHandler(XMLReader parser, DomainsHandler parent) {
+            super(parser, parent);
+            this.domains = parent.domains;
+            this.configurationSource = parent.configurationSource;
+        }
+
+        @Override
+        protected ContentHandler createChildTagHandler(
+                String namespaceURI,
+                String localName,
+                String name,
+                Attributes attributes) {
+
+            if (localName.equals(DOMAIN_TAG)) {
+
+                String domainName = attributes.getValue("", "name");
+                DataChannelDescriptor descriptor = new DataChannelDescriptor();
+                descriptor.setName(domainName);
+                descriptor.setConfigurationSource(configurationSource);
+
+                domains.add(descriptor);
+                return new DataChannelChildrenHandler(descriptor, parser, this);
+            }
+
+            logger.info(unexpectedTagMessage(localName, DOMAIN_TAG));
+            return super.createChildTagHandler(namespaceURI, localName, name, attributes);
+        }
+    }
+
+    final class DataChannelChildrenHandler extends SAXNestedTagHandler {
+
+        private DataChannelDescriptor descriptor;
+
+        DataChannelChildrenHandler(DataChannelDescriptor descriptor, XMLReader parser,
+                DomainsChildrenHandler parentHandler) {
+            super(parser, parentHandler);
+            this.descriptor = descriptor;
+        }
+
+        @Override
+        protected ContentHandler createChildTagHandler(
+                String namespaceURI,
+                String localName,
+                String name,
+                Attributes attributes) {
+
+            if (localName.equals(PROPERTY_TAG)) {
+
+                String key = attributes.getValue("", "name");
+                String value = attributes.getValue("", "value");
+                if (key != null && value != null) {
+                    descriptor.getProperties().put(key, value);
+                }
+            }
+            else if (localName.equals(MAP_TAG)) {
+
+                String dataMapName = attributes.getValue("", "name");
+                Resource baseResource = descriptor.getConfigurationSource();
+
+                String dataMapLocation = attributes.getValue("", "location");
+                Resource dataMapResource = baseResource
+                        .getRelativeResource(dataMapLocation);
+
+                DataMap dataMap = mapLoader.load(dataMapResource);
+                dataMap.setName(dataMapName);
+                dataMap.setLocation(dataMapLocation);
+                dataMap.setConfigurationSource(dataMapResource);
+
+                descriptor.getDataMaps().add(dataMap);
+            }
+            else if (localName.equals(NODE_TAG)) {
+
+                String nodeName = attributes.getValue("", "name");
+                if (nodeName == null) {
+                    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));
+                nodeDescriptor.setSchemaUpdateStrategyType(attributes.getValue(
+                        "",
+                        "schema-update-strategy"));
+
+                return new DataNodeChildrenHandler(parser, this, nodeDescriptor);
+            }
+
+            return super.createChildTagHandler(namespaceURI, localName, name, attributes);
+        }
+    }
+
+    final class DataNodeChildrenHandler extends SAXNestedTagHandler {
+
+        private DataNodeDescriptor nodeDescriptor;
+
+        DataNodeChildrenHandler(XMLReader parser, SAXNestedTagHandler parentHandler,
+                DataNodeDescriptor nodeDescriptor) {
+            super(parser, parentHandler);
+            this.nodeDescriptor = nodeDescriptor;
+        }
+
+        @Override
+        protected ContentHandler createChildTagHandler(
+                String namespaceURI,
+                String localName,
+                String name,
+                Attributes attributes) {
+
+            if (localName.equals(MAP_REF_TAG)) {
+
+                String mapName = attributes.getValue("", "name");
+                nodeDescriptor.getDataMapNames().add(mapName);
+            }
+
+            return super.createChildTagHandler(namespaceURI, localName, name, attributes);
+        }
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataMapLoader_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/XMLDataMapLoader_V3_0_0_1.java?rev=890629&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java (added)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/main/java/org/apache/cayenne/project2/upgrade/v6/XMLDataMapLoader_V3_0_0_1.java Tue Dec 15 03:34:21 2009
@@ -0,0 +1,76 @@
+/*****************************************************************
+ *   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.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.XMLDataMapLoader;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.MapLoader;
+import org.apache.cayenne.resource.Resource;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.xml.sax.InputSource;
+
+/**
+ * @since 3.1
+ */
+class XMLDataMapLoader_V3_0_0_1 {
+
+    private static Log logger = LogFactory.getLog(XMLDataMapLoader.class);
+
+    public DataMap load(Resource configurationResource) throws CayenneRuntimeException {
+
+        MapLoader mapLoader = new MapLoader();
+        URL url = configurationResource.getURL();
+
+        InputStream in = null;
+
+        DataMap map;
+
+        try {
+            in = url.openStream();
+
+            map = mapLoader.loadDataMap(new InputSource(in));
+        }
+        catch (Exception e) {
+            throw new CayenneRuntimeException(
+                    "Error loading configuration from %s",
+                    e,
+                    url);
+        }
+        finally {
+            try {
+                if (in != null) {
+                    in.close();
+                }
+            }
+            catch (IOException ioex) {
+                logger.info(
+                        "failure closing input stream for " + url + ", ignoring",
+                        ioex);
+            }
+        }
+
+        return map;
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/DataChannelProjectLoaderTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/DataChannelProjectLoaderTest.java?rev=890629&r1=890628&r2=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/DataChannelProjectLoaderTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/DataChannelProjectLoaderTest.java Tue Dec 15 03:34:21 2009
@@ -66,8 +66,6 @@
         Project project = loader.loadProject(rootSource);
         assertNotNull(project);
 
-        assertEquals("6", project.getVersion());
-
         DataChannelDescriptor rootNode = (DataChannelDescriptor) project.getRootNode();
         assertNotNull(rootNode);
         assertSame(rootSource, rootNode.getConfigurationSource());

Modified: cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/DataChannelProjectSaverTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/DataChannelProjectSaverTest.java?rev=890629&r1=890628&r2=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/DataChannelProjectSaverTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/DataChannelProjectSaverTest.java Tue Dec 15 03:34:21 2009
@@ -22,24 +22,22 @@
 import java.io.PrintWriter;
 import java.net.URL;
 
-import junit.framework.TestCase;
-
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.ConfigurationNameMapper;
 import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
 import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
-import org.apache.cayenne.configuration.ConfigurationNameMapper;
 import org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader;
 import org.apache.cayenne.configuration.XMLDataMapLoader;
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.DIBootstrap;
 import org.apache.cayenne.di.Injector;
 import org.apache.cayenne.di.Module;
+import org.apache.cayenne.project2.unit.Project2Case;
 import org.apache.cayenne.resource.Resource;
 import org.apache.cayenne.resource.URLResource;
-import org.apache.cayenne.util.Util;
 
-public class DataChannelProjectSaverTest extends TestCase {
+public class DataChannelProjectSaverTest extends Project2Case {
 
     public void testSaveAs() throws Exception {
 
@@ -133,26 +131,4 @@
 
     }
 
-    protected File setupTestDirectory(String subfolder) {
-        String packagePath = getClass().getPackage().getName().replace('.', '/');
-        String location = "target/testrun/" + packagePath + "/" + subfolder;
-        File testDirectory = new File(location);
-
-        // delete old tests
-        if (testDirectory.exists()) {
-            if (!Util.delete(location, true)) {
-                throw new CayenneRuntimeException(
-                        "Error deleting test directory '%s'",
-                        location);
-            }
-        }
-
-        if (!testDirectory.mkdirs()) {
-            throw new CayenneRuntimeException(
-                    "Error creating test directory '%s'",
-                    location);
-        }
-
-        return testDirectory;
-    }
 }

Modified: cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/ProjectTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/ProjectTest.java?rev=890629&r1=890628&r2=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/ProjectTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/ProjectTest.java Tue Dec 15 03:34:21 2009
@@ -38,19 +38,4 @@
         assertSame(object, project.getRootNode());
     }
 
-    public void testVersion() {
-
-        ConfigurationNode object = new ConfigurationNode() {
-
-            public <T> T acceptVisitor(ConfigurationNodeVisitor<T> visitor) {
-                return null;
-            }
-        };
-
-        Project project = new Project(object);
-
-        assertNull(project.getVersion());
-        project.setVersion("1.1");
-        assertEquals("1.1", project.getVersion());
-    }
 }

Copied: cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/unit/Project2Case.java (from r890504, cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/ProjectTest.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/unit/Project2Case.java?p2=cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/unit/Project2Case.java&p1=cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/ProjectTest.java&r1=890504&r2=890629&rev=890629&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/ProjectTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-project-unpublished/src/test/java/org/apache/cayenne/project2/unit/Project2Case.java Tue Dec 15 03:34:21 2009
@@ -16,41 +16,37 @@
  *  specific language governing permissions and limitations
  *  under the License.
  ****************************************************************/
-package org.apache.cayenne.project2;
+package org.apache.cayenne.project2.unit;
 
-import junit.framework.TestCase;
-
-import org.apache.cayenne.configuration.ConfigurationNode;
-import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
-
-public class ProjectTest extends TestCase {
-
-    public void testRootNode() {
-
-        ConfigurationNode object = new ConfigurationNode() {
+import java.io.File;
 
-            public <T> T acceptVisitor(ConfigurationNodeVisitor<T> visitor) {
-                return null;
-            }
-        };
-
-        Project project = new Project(object);
-        assertSame(object, project.getRootNode());
-    }
+import junit.framework.TestCase;
 
-    public void testVersion() {
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.util.Util;
 
-        ConfigurationNode object = new ConfigurationNode() {
+public class Project2Case extends TestCase {
 
-            public <T> T acceptVisitor(ConfigurationNodeVisitor<T> visitor) {
-                return null;
+    protected File setupTestDirectory(String subfolder) {
+        String packagePath = getClass().getPackage().getName().replace('.', '/');
+        String location = "target/testrun/" + packagePath + "/" + subfolder;
+        File testDirectory = new File(location);
+
+        // delete old tests
+        if (testDirectory.exists()) {
+            if (!Util.delete(location, true)) {
+                throw new CayenneRuntimeException(
+                        "Error deleting test directory '%s'",
+                        location);
             }
-        };
+        }
 
-        Project project = new Project(object);
+        if (!testDirectory.mkdirs()) {
+            throw new CayenneRuntimeException(
+                    "Error creating test directory '%s'",
+                    location);
+        }
 
-        assertNull(project.getVersion());
-        project.setVersion("1.1");
-        assertEquals("1.1", project.getVersion());
+        return testDirectory;
     }
 }

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=890629&r1=890628&r2=890629&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 Tue Dec 15 03:34:21 2009
@@ -18,17 +18,28 @@
  ****************************************************************/
 package org.apache.cayenne.project2.upgrade.v6;
 
+import java.io.File;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
 
-import junit.framework.TestCase;
-
+import org.apache.cayenne.configuration.ConfigurationNameMapper;
+import org.apache.cayenne.configuration.DefaultConfigurationNameMapper;
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.di.Module;
+import org.apache.cayenne.project2.FileProjectSaver;
+import org.apache.cayenne.project2.ProjectSaver;
+import org.apache.cayenne.project2.unit.Project2Case;
 import org.apache.cayenne.project2.upgrade.UpgradeHandler;
 import org.apache.cayenne.project2.upgrade.UpgradeMetaData;
 import org.apache.cayenne.project2.upgrade.UpgradeType;
 import org.apache.cayenne.resource.Resource;
 import org.apache.cayenne.resource.URLResource;
+import org.apache.cayenne.util.Util;
 
-public class ProjectUpgrader_V6Test extends TestCase {
+public class ProjectUpgrader_V6Test extends Project2Case {
 
     public void testMetadata_3_0_0_1() {
 
@@ -37,7 +48,18 @@
                 baseUrl + "/3_0_0_1a/cayenne.xml");
         assertNotNull(url);
 
+        Module testModule = new Module() {
+
+            public void configure(Binder binder) {
+                binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
+                binder.bind(ConfigurationNameMapper.class).to(
+                        DefaultConfigurationNameMapper.class);
+            }
+        };
+
         ProjectUpgrader_V6 upgrader = new ProjectUpgrader_V6();
+        Injector injector = DIBootstrap.createInjector(testModule);
+        injector.injectMembers(upgrader);
 
         Resource source = new URLResource(url);
         UpgradeHandler handler = upgrader.getUpgradeHandler(source);
@@ -59,7 +81,18 @@
         URL url = getClass().getClassLoader().getResource(baseUrl + "/2_0a/cayenne.xml");
         assertNotNull(url);
 
+        Module testModule = new Module() {
+
+            public void configure(Binder binder) {
+                binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
+                binder.bind(ConfigurationNameMapper.class).to(
+                        DefaultConfigurationNameMapper.class);
+            }
+        };
+
         ProjectUpgrader_V6 upgrader = new ProjectUpgrader_V6();
+        Injector injector = DIBootstrap.createInjector(testModule);
+        injector.injectMembers(upgrader);
 
         Resource source = new URLResource(url);
         UpgradeHandler handler = upgrader.getUpgradeHandler(source);
@@ -81,7 +114,18 @@
                 baseUrl + "/6a/cayenne-PROJECT1.xml");
         assertNotNull(url);
 
+        Module testModule = new Module() {
+
+            public void configure(Binder binder) {
+                binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
+                binder.bind(ConfigurationNameMapper.class).to(
+                        DefaultConfigurationNameMapper.class);
+            }
+        };
+
         ProjectUpgrader_V6 upgrader = new ProjectUpgrader_V6();
+        Injector injector = DIBootstrap.createInjector(testModule);
+        injector.injectMembers(upgrader);
 
         Resource source = new URLResource(url);
         UpgradeHandler handler = upgrader.getUpgradeHandler(source);
@@ -96,4 +140,75 @@
         assertEquals("6", md.getProjectVersion());
         assertEquals("6", md.getSupportedVersion());
     }
+
+    public void testPerformUpgrade_3_0_0_1() throws Exception {
+
+        File testFolder = setupTestDirectory("testPerformUpgrade_3_0_0_1");
+        String sourceUrl = getClass().getPackage().getName().replace('.', '/')
+                + "/3_0_0_1a/";
+
+        List<String> sources = new ArrayList<String>();
+
+        sources.add("cayenne.xml");
+        sources.add("d1Map1.map.xml");
+        sources.add("d1Map2.map.xml");
+        sources.add("d1NodeDriver.driver.xml");
+
+        // upgrades are done in-place, so copy it first
+        List<File> targetsBefore = new ArrayList<File>();
+        for (String source : sources) {
+
+            URL url = getClass().getClassLoader().getResource(sourceUrl + source);
+            File target = new File(testFolder, source);
+            assertNotNull(source);
+            Util.copy(url, target);
+            targetsBefore.add(target);
+        }
+
+        Module testModule = new Module() {
+
+            public void configure(Binder binder) {
+                binder.bind(ProjectSaver.class).to(FileProjectSaver.class);
+                binder.bind(ConfigurationNameMapper.class).to(
+                        DefaultConfigurationNameMapper.class);
+            }
+        };
+
+        ProjectUpgrader_V6 upgrader = new ProjectUpgrader_V6();
+        Injector injector = DIBootstrap.createInjector(testModule);
+        injector.injectMembers(upgrader);
+
+        Resource source = new URLResource(targetsBefore.get(0).toURL());
+        UpgradeHandler handler = upgrader.getUpgradeHandler(source);
+
+        Resource upgraded = handler.performUpgrade();
+        assertNotNull(upgraded);
+        assertNotSame(source, upgrader);
+
+        // check that all the new files are created...
+        List<String> targets = new ArrayList<String>();
+
+        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());
+        }
+
+        // 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());
+//            }
+//        }
+    }
 }