You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by kn...@apache.org on 2009/05/22 01:11:42 UTC

svn commit: r777313 [5/5] - in /jackrabbit/sandbox/JCR-1456: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/ jackr...

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/version/simple/RestoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/version/simple/RestoreTest.java?rev=777313&r1=777312&r2=777313&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/version/simple/RestoreTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/version/simple/RestoreTest.java Thu May 21 23:11:22 2009
@@ -23,10 +23,7 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
 import javax.jcr.nodetype.NodeDefinition;
-import javax.jcr.version.OnParentVersionAction;
-import javax.jcr.version.Version;
-import javax.jcr.version.VersionException;
-import javax.jcr.version.VersionIterator;
+import javax.jcr.version.*;
 
 import org.apache.jackrabbit.test.NotExecutableException;
 
@@ -46,6 +43,8 @@
  */
 public class RestoreTest extends AbstractVersionTest {
 
+    VersionManager versionManager;
+
     Version version;
     Version version2;
     Version rootVersion;
@@ -57,17 +56,19 @@
 
     protected void setUp() throws Exception {
         super.setUp();
+        versionManager = versionableNode.getSession().getWorkspace().getVersionManager();
+        String path = versionableNode.getPath();
         propertyValue1 = getProperty("propertyValue1");
-        propertyValue2 = getProperty("propertyValue1");
+        propertyValue2 = getProperty("propertyValue2");
         versionableNode.setProperty(propertyName1, propertyValue1);
-        versionableNode.save();
-        version = versionableNode.checkin();
-        versionableNode.checkout();
+        versionableNode.getSession().save();
+        version = versionManager.checkin(path);
+        versionManager.checkout(path);
         versionableNode.setProperty(propertyName1, propertyValue2);
-        versionableNode.save();
-        version2 = versionableNode.checkin();
-        versionableNode.checkout();
-        rootVersion = versionableNode.getVersionHistory().getRootVersion();
+        versionableNode.getSession().save();
+        version2 = versionManager.checkin(path);
+        versionManager.checkout(path);
+        rootVersion = versionManager.getVersionHistory(path).getRootVersion();
 
         // build a second versionable node below the testroot
         try {
@@ -80,7 +81,7 @@
     protected void tearDown() throws Exception {
         try {
             versionableNode2.remove();
-            testRootNode.save();
+            testRootNode.getSession().save();
         } finally {
             version = null;
             version2 = null;
@@ -105,6 +106,20 @@
     }
 
     /**
+     * Test if restoring the root version fails.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreRootVersionFailJcr2() throws RepositoryException {
+        try {
+            versionManager.restore(rootVersion, true);
+            fail("Restore of jcr:rootVersion must throw VersionException.");
+        } catch (VersionException e) {
+            // success
+        }
+    }
+
+    /**
      * Test if restoring a node works on checked-in node.
      *
      * @throws RepositoryException
@@ -115,6 +130,46 @@
     }
 
     /**
+     * Test if restoring a node works on checked-in node.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreOnCheckedInNodeJcr2_1() throws RepositoryException {
+        versionManager.checkin(versionableNode.getPath());
+        versionManager.restore(version, true);
+    }
+
+    /**
+     * Test if restoring a node works on checked-in node.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreOnCheckedInNodeJcr2_2() throws RepositoryException {
+        versionManager.checkin(versionableNode.getPath());
+        versionManager.restore(versionableNode.getPath(), version, true);
+    }
+
+    /**
+     * Test if restoring a node works on checked-in node.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreOnCheckedInNodeJcr2_3() throws RepositoryException {
+        versionManager.checkin(versionableNode.getPath());
+        versionManager.restore(versionableNode.getPath(), version.getName(), true);
+    }
+
+    /**
+     * Test if restoring a node works on checked-in node.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreOnCheckedInNodeJcr2_4() throws RepositoryException {
+        versionManager.checkin(versionableNode.getPath());
+        versionManager.restore(new Version[] {version}, true);
+    }
+
+    /**
      * Test if restoring a node works on checked-out node.
      *
      * @throws RepositoryException
@@ -124,28 +179,147 @@
     }
 
     /**
+     * Test if restoring a node works on checked-out node.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreOnCheckedOutNodeJcr2() throws RepositoryException {
+        versionManager.restore(version, true);
+    }
+
+    /**
+     * Test if restoring a node works on checked-out node.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreOnCheckedOutNodeJcr2_2() throws RepositoryException {
+        versionManager.restore(versionableNode.getPath(), version, true);
+    }
+
+    /**
+     * Test if restoring a node works on checked-out node.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreOnCheckedOutNodeJcr2_3() throws RepositoryException {
+        versionManager.restore(versionableNode.getPath(), version.getName(), true);
+    }
+
+    /**
+     * Test if restoring a node works on checked-out node.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreOnCheckedOutNodeJcr2_4() throws RepositoryException {
+        versionManager.restore(new Version[] {version}, true);
+    }
+
+    /**
      * Restoring a node set the jcr:isCheckedOut property to false.
      *
      * @throws RepositoryException
      */
     public void testRestoreSetsIsCheckedOutToFalse() throws RepositoryException {
         versionableNode.restore(version, true);
-
         assertFalse("Restoring a node sets the jcr:isCheckedOut property to false", versionableNode.isCheckedOut());
     }
 
     /**
+     * Restoring a node set the jcr:isCheckedOut property to false.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreSetsIsCheckedOutToFalseJcr2() throws RepositoryException {
+        versionManager.restore(version, true);
+        assertFalse("Restoring a node sets the jcr:isCheckedOut property to false", versionManager.isCheckedOut(versionableNode.getPath()));
+    }
+
+    /**
+     * Restoring a node set the jcr:isCheckedOut property to false.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreSetsIsCheckedOutToFalseJcr2_2() throws RepositoryException {
+        versionManager.restore(versionableNode.getPath(), version, true);
+        assertFalse("Restoring a node sets the jcr:isCheckedOut property to false", versionManager.isCheckedOut(versionableNode.getPath()));
+    }
+
+    /**
+     * Restoring a node set the jcr:isCheckedOut property to false.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreSetsIsCheckedOutToFalseJcr3() throws RepositoryException {
+        versionManager.restore(versionableNode.getPath(), version.getName(), true);
+        assertFalse("Restoring a node sets the jcr:isCheckedOut property to false", versionManager.isCheckedOut(versionableNode.getPath()));
+    }
+
+    /**
+     * Restoring a node set the jcr:isCheckedOut property to false.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreSetsIsCheckedOutToFalseJcr2_4() throws RepositoryException {
+        versionManager.restore(new Version[] {version}, true);
+        assertFalse("Restoring a node sets the jcr:isCheckedOut property to false", versionManager.isCheckedOut(versionableNode.getPath()));
+    }
+
+    /**
      * Test if restoring a node restores the correct property
      *
      * @throws RepositoryException
      */
-    public void testRestoreCorrectVersion() throws RepositoryException {
+    public void testRestoreCorrectProperty() throws RepositoryException {
         versionableNode.restore(version, true);
         String value = versionableNode.getProperty(propertyName1).getString();
         assertEquals("Restoring a node must set the correct property.", propertyValue1, value);
     }
 
     /**
+     * Test if restoring a node restores the correct property
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreCorrectPropertyJcr2() throws RepositoryException {
+        versionManager.restore(version, true);
+        String value = versionableNode.getProperty(propertyName1).getString();
+        assertEquals("Restoring a node must set the correct property.", propertyValue1, value);
+    }
+
+    /**
+     * Test if restoring a node restores the correct property
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreCorrectPropertyJcr2_2() throws RepositoryException {
+        versionManager.restore(versionableNode.getPath(), version, true);
+        String value = versionableNode.getProperty(propertyName1).getString();
+        assertEquals("Restoring a node must set the correct property.", propertyValue1, value);
+    }
+
+    /**
+     * Test if restoring a node restores the correct property
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreCorrectPropertyJcr2_3() throws RepositoryException {
+        versionManager.restore(versionableNode.getPath(), version.getName(), true);
+        String value = versionableNode.getProperty(propertyName1).getString();
+        assertEquals("Restoring a node must set the correct property.", propertyValue1, value);
+    }
+
+    /**
+     * Test if restoring a node restores the correct property
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreCorrectPropertyJcr2_4() throws RepositoryException {
+        versionManager.restore(new Version[] {version}, true);
+        String value = versionableNode.getProperty(propertyName1).getString();
+        assertEquals("Restoring a node must set the correct property.", propertyValue1, value);
+    }
+
+    /**
      * Test if InvalidItemStateException is thrown if the node has pending changes.
      *
      * @throws RepositoryException
@@ -163,6 +337,74 @@
     }
 
     /**
+     * Test if InvalidItemStateException is thrown if the node has pending changes.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreWithPendingChangesJcr2() throws RepositoryException {
+        // modify node without calling save()
+        try {
+            versionableNode.setProperty(propertyName1, propertyValue);
+            versionManager.restore(version, true);
+
+            fail("InvalidItemStateException must be thrown on attempt to restore a node having any unsaved changes pending.");
+        } catch (InvalidItemStateException e) {
+            // ok
+        }
+    }
+
+    /**
+     * Test if InvalidItemStateException is thrown if the node has pending changes.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreWithPendingChangesJcr2_2() throws RepositoryException {
+        // modify node without calling save()
+        try {
+            versionableNode.setProperty(propertyName1, propertyValue);
+            versionManager.restore(versionableNode.getPath(), version, true);
+
+            fail("InvalidItemStateException must be thrown on attempt to restore a node having any unsaved changes pending.");
+        } catch (InvalidItemStateException e) {
+            // ok
+        }
+    }
+
+    /**
+     * Test if InvalidItemStateException is thrown if the node has pending changes.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreWithPendingChangesJcr2_3() throws RepositoryException {
+        // modify node without calling save()
+        try {
+            versionableNode.setProperty(propertyName1, propertyValue);
+            versionManager.restore(versionableNode.getPath(), version.getName(), true);
+
+            fail("InvalidItemStateException must be thrown on attempt to restore a node having any unsaved changes pending.");
+        } catch (InvalidItemStateException e) {
+            // ok
+        }
+    }
+
+    /**
+     * Test if InvalidItemStateException is thrown if the node has pending changes.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreWithPendingChangesJcr2_4() throws RepositoryException {
+        // modify node without calling save()
+        try {
+            versionableNode.setProperty(propertyName1, propertyValue);
+            versionManager.restore(new Version[] {version}, true);
+
+            fail("InvalidItemStateException must be thrown on attempt to restore a node having any unsaved changes pending.");
+        } catch (InvalidItemStateException e) {
+            // ok
+        }
+    }
+
+    /**
      * VersionException expected on Node.restore(Version, boolean) if the
      * specified version is not part of this node's version history.
      *
@@ -180,6 +422,23 @@
     }
 
     /**
+     * VersionException expected on restore if the
+     * specified version is not part of this node's version history.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreInvalidVersionJcr2() throws RepositoryException {
+        Version vNode2 = versionManager.checkin(versionableNode2.getPath());
+        try {
+            versionManager.restore(versionableNode.getPath(), vNode2, true);
+
+            fail("VersionException expected on Node.restore(Version, boolean) if the specified version is not part of this node's version history.");
+        } catch (VersionException e) {
+            // ok
+        }
+    }
+
+    /**
      * VersionException expected on Node.restore(String, boolean) if the specified version is not part of this node's version history.
      *
      * @throws RepositoryException
@@ -206,6 +465,32 @@
     }
 
     /**
+     * VersionException expected on Node.restore(String, boolean) if the specified version is not part of this node's version history.
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreInvalidVersion2Jcr2() throws RepositoryException {
+        String invalidName;
+        do {
+            invalidName = createRandomString(3);
+            for (VersionIterator it = versionManager.getVersionHistory(versionableNode.getPath()).getAllVersions(); it.hasNext();) {
+                Version v = it.nextVersion();
+                if (invalidName.equals(v.getName())) {
+                    invalidName = null;
+                    break;
+                }
+            }
+        } while (invalidName == null);
+
+        try {
+            versionManager.restore(versionableNode.getPath(), invalidName, true);
+            fail("VersionException expected on Node.restore(String, boolean) if the specified version is not part of this node's version history.");
+        } catch (VersionException e) {
+            // ok
+        }
+    }
+
+    /**
      * Test calling Node.restore(String, boolean) on a non-versionable node.
      *
      * @throws RepositoryException
@@ -221,6 +506,36 @@
     }
 
     /**
+     * Test restoring on a non-versionable node.
+     *
+     * @throws RepositoryException
+     * @see Node#restore(String, boolean)
+     */
+    public void testRestoreNonVersionableNodeJcr2() throws RepositoryException {
+        try {
+            versionManager.restore(nonVersionableNode.getPath(), version, true);
+            fail("trying to restore on a non versionable node must throw UnsupportedRepositoryOperationException");
+        } catch (UnsupportedRepositoryOperationException e) {
+            //success
+        }
+    }
+
+    /**
+     * Test restoring on a non-versionable node.
+     *
+     * @throws RepositoryException
+     * @see Node#restore(String, boolean)
+     */
+    public void testRestoreNonVersionableNodeJcr2_2() throws RepositoryException {
+        try {
+            versionManager.restore(nonVersionableNode.getPath(), "foo", true);
+            fail("trying to restore on a non versionable node must throw UnsupportedRepositoryOperationException");
+        } catch (UnsupportedRepositoryOperationException e) {
+            //success
+        }
+    }
+
+    /**
      * Test calling Node.restore(Version, String, boolean) on a non-versionable node.
      *
      * @throws RepositoryException
@@ -253,7 +568,37 @@
     }
 
     /**
-     * Test if restoring a node with an invalid Version throws a VersionException
+     * Test restoring on a non-versionable node.
+     *
+     * @throws RepositoryException
+     * @see Node#restore(Version, boolean)
+     */
+    public void testRestoreNonVersionableNode3Jcr2() throws RepositoryException {
+        try {
+            versionManager.restore(nonVersionableNode.getPath(), version, true);
+            fail("Node.restore(Version, boolean) on a non versionable node must throw UnsupportedRepositoryOperationException");
+        } catch (UnsupportedRepositoryOperationException e) {
+            //success
+        }
+    }
+
+    /**
+     * Test restoring on a non-versionable node.
+     *
+     * @throws RepositoryException
+     * @see Node#restore(Version, boolean)
+     */
+    public void testRestoreNonVersionableNode3Jcr2_2() throws RepositoryException {
+        try {
+            versionManager.restore(nonVersionableNode.getPath(), version.getName(), true);
+            fail("Node.restore(Version, boolean) on a non versionable node must throw UnsupportedRepositoryOperationException");
+        } catch (UnsupportedRepositoryOperationException e) {
+            //success
+        }
+    }
+
+    /**
+     * Test if restoring a node with an invalid Version throws a VersionException
      *
      * @throws RepositoryException
      */
@@ -268,6 +613,21 @@
     }
 
     /**
+     * Test if restoring a node with an invalid Version throws a VersionException
+     *
+     * @throws RepositoryException
+     */
+    public void testRestoreWithInvalidVersionJcr2() throws RepositoryException {
+        Version invalidVersion = versionManager.checkin(versionableNode2.getPath());
+        try {
+            versionManager.restore(versionableNode.getPath(), invalidVersion, true);
+            fail("Node.restore(Version, boolean): A VersionException must be thrown if the specified version does not exists in this node's version history.");
+        } catch (VersionException e) {
+            // success
+        }
+    }
+
+    /**
      * Tests if restoring the <code>Version</code> of an existing node throws an
      * <code>ItemExistsException</code> if removeExisting is set to FALSE.
      */
@@ -292,9 +652,109 @@
         }
     }
 
+    /**
+     * Tests if restoring the <code>Version</code> of an existing node throws an
+     * <code>ItemExistsException</code> if removeExisting is set to FALSE.
+     */
+    public void testRestoreWithUUIDConflictJcr2() throws RepositoryException, NotExecutableException {
+        try {
+            Node naa = createVersionableNode(versionableNode, nodeName4, versionableNodeType);
+            // Verify that nodes used for the test have proper opv behaviour
+            NodeDefinition nd = naa.getDefinition();
+            if (nd.getOnParentVersion() != OnParentVersionAction.COPY && nd.getOnParentVersion() != OnParentVersionAction.VERSION) {
+                throw new NotExecutableException("Child nodes must have OPV COPY or VERSION in order to be able to test Node.restore with uuid conflict.");
+            }
+
+            Version v = versionManager.checkin(versionableNode.getPath());
+            versionManager.checkout(versionableNode.getPath());
+            superuser.move(naa.getPath(), versionableNode2.getPath() + "/" + naa.getName());
+            superuser.save();
+            versionManager.restore(v, false);
+
+            fail("Node.restore( Version, boolean ): An ItemExistsException must be thrown if the node to be restored already exsits and removeExisting was set to false.");
+        } catch (ItemExistsException e) {
+            // success
+        }
+    }
+
+    /**
+     * Tests if restoring the <code>Version</code> of an existing node throws an
+     * <code>ItemExistsException</code> if removeExisting is set to FALSE.
+     */
+    public void testRestoreWithUUIDConflictJcr2_2() throws RepositoryException, NotExecutableException {
+        try {
+            Node naa = createVersionableNode(versionableNode, nodeName4, versionableNodeType);
+            // Verify that nodes used for the test have proper opv behaviour
+            NodeDefinition nd = naa.getDefinition();
+            if (nd.getOnParentVersion() != OnParentVersionAction.COPY && nd.getOnParentVersion() != OnParentVersionAction.VERSION) {
+                throw new NotExecutableException("Child nodes must have OPV COPY or VERSION in order to be able to test Node.restore with uuid conflict.");
+            }
+
+            Version v = versionManager.checkin(versionableNode.getPath());
+            versionManager.checkout(versionableNode.getPath());
+            superuser.move(naa.getPath(), versionableNode2.getPath() + "/" + naa.getName());
+            superuser.save();
+            versionManager.restore(versionableNode.getPath(), v, false);
+
+            fail("Node.restore( Version, boolean ): An ItemExistsException must be thrown if the node to be restored already exsits and removeExisting was set to false.");
+        } catch (ItemExistsException e) {
+            // success
+        }
+    }
+
+    /**
+     * Tests if restoring the <code>Version</code> of an existing node throws an
+     * <code>ItemExistsException</code> if removeExisting is set to FALSE.
+     */
+    public void testRestoreWithUUIDConflictJcr2_3() throws RepositoryException, NotExecutableException {
+        try {
+            Node naa = createVersionableNode(versionableNode, nodeName4, versionableNodeType);
+            // Verify that nodes used for the test have proper opv behaviour
+            NodeDefinition nd = naa.getDefinition();
+            if (nd.getOnParentVersion() != OnParentVersionAction.COPY && nd.getOnParentVersion() != OnParentVersionAction.VERSION) {
+                throw new NotExecutableException("Child nodes must have OPV COPY or VERSION in order to be able to test Node.restore with uuid conflict.");
+            }
+
+            Version v = versionManager.checkin(versionableNode.getPath());
+            versionManager.checkout(versionableNode.getPath());
+            superuser.move(naa.getPath(), versionableNode2.getPath() + "/" + naa.getName());
+            superuser.save();
+            versionManager.restore(versionableNode.getPath(), v.getName(), false);
+
+            fail("Node.restore( Version, boolean ): An ItemExistsException must be thrown if the node to be restored already exsits and removeExisting was set to false.");
+        } catch (ItemExistsException e) {
+            // success
+        }
+    }
+
+    /**
+     * Tests if restoring the <code>Version</code> of an existing node throws an
+     * <code>ItemExistsException</code> if removeExisting is set to FALSE.
+     */
+    public void testRestoreWithUUIDConflictJcr2_4() throws RepositoryException, NotExecutableException {
+        try {
+            Node naa = createVersionableNode(versionableNode, nodeName4, versionableNodeType);
+            // Verify that nodes used for the test have proper opv behaviour
+            NodeDefinition nd = naa.getDefinition();
+            if (nd.getOnParentVersion() != OnParentVersionAction.COPY && nd.getOnParentVersion() != OnParentVersionAction.VERSION) {
+                throw new NotExecutableException("Child nodes must have OPV COPY or VERSION in order to be able to test Node.restore with uuid conflict.");
+            }
+
+            Version v = versionManager.checkin(versionableNode.getPath());
+            versionManager.checkout(versionableNode.getPath());
+            superuser.move(naa.getPath(), versionableNode2.getPath() + "/" + naa.getName());
+            superuser.save();
+            versionManager.restore(new Version[] {v}, false);
+
+            fail("Node.restore( Version, boolean ): An ItemExistsException must be thrown if the node to be restored already exsits and removeExisting was set to false.");
+        } catch (ItemExistsException e) {
+            // success
+        }
+    }
+
     public void testRestoreChild1() throws RepositoryException {
         versionableNode.addNode("child1");
-        versionableNode.save();
+        versionableNode.getSession().save();
         Version v1 = versionableNode.checkin();
         versionableNode.checkout();
         Version v2 = versionableNode.checkin();
@@ -312,6 +772,86 @@
         }
     }
 
+    public void testRestoreChild1Jcr2() throws RepositoryException {
+        versionableNode.addNode("child1");
+        versionableNode.getSession().save();
+        Version v1 = versionManager.checkin(versionableNode.getPath());
+        versionManager.checkout(versionableNode.getPath());
+        Version v2 = versionManager.checkin(versionableNode.getPath());
+
+        versionManager.restore(v1, true);
+        assertTrue("Node.restore('1.2') must not remove child node.", versionableNode.hasNode("child1"));
+
+        versionManager.restore(version, true);
+        assertFalse("Node.restore('1.0') must remove child node.", versionableNode.hasNode("child1"));
+
+        try {
+            versionManager.restore(v2, true);
+        } catch (RepositoryException e) {
+            fail("Node.restore('1.3') must fail.");
+        }
+    }
+
+    public void testRestoreChild1Jcr2_2() throws RepositoryException {
+        versionableNode.addNode("child1");
+        versionableNode.getSession().save();
+        Version v1 = versionManager.checkin(versionableNode.getPath());
+        versionManager.checkout(versionableNode.getPath());
+        Version v2 = versionManager.checkin(versionableNode.getPath());
+
+        versionManager.restore(versionableNode.getPath(), v1, true);
+        assertTrue("Node.restore('1.2') must not remove child node.", versionableNode.hasNode("child1"));
+
+        versionManager.restore(versionableNode.getPath(), version, true);
+        assertFalse("Node.restore('1.0') must remove child node.", versionableNode.hasNode("child1"));
+
+        try {
+            versionManager.restore(versionableNode.getPath(), v2, true);
+        } catch (RepositoryException e) {
+            fail("Node.restore('1.3') must fail.");
+        }
+    }
+
+    public void testRestoreChild1Jcr2_3() throws RepositoryException {
+        versionableNode.addNode("child1");
+        versionableNode.getSession().save();
+        Version v1 = versionManager.checkin(versionableNode.getPath());
+        versionManager.checkout(versionableNode.getPath());
+        Version v2 = versionManager.checkin(versionableNode.getPath());
+
+        versionManager.restore(versionableNode.getPath(), v1.getName(), true);
+        assertTrue("Node.restore('1.2') must not remove child node.", versionableNode.hasNode("child1"));
+
+        versionManager.restore(versionableNode.getPath(), version.getName(), true);
+        assertFalse("Node.restore('1.0') must remove child node.", versionableNode.hasNode("child1"));
+
+        try {
+            versionManager.restore(versionableNode.getPath(), v2.getName(), true);
+        } catch (RepositoryException e) {
+            fail("Node.restore('1.3') must fail.");
+        }
+    }
+
+    public void testRestoreChild1Jcr2_4() throws RepositoryException {
+        versionableNode.addNode("child1");
+        versionableNode.getSession().save();
+        Version v1 = versionManager.checkin(versionableNode.getPath());
+        versionManager.checkout(versionableNode.getPath());
+        Version v2 = versionManager.checkin(versionableNode.getPath());
+
+        versionManager.restore(new Version[] {v1}, true);
+        assertTrue("Node.restore('1.2') must not remove child node.", versionableNode.hasNode("child1"));
+
+        versionManager.restore(new Version[] {version}, true);
+        assertFalse("Node.restore('1.0') must remove child node.", versionableNode.hasNode("child1"));
+
+        try {
+            versionManager.restore(new Version[] {v2}, true);
+        } catch (RepositoryException e) {
+            fail("Node.restore('1.3') must fail.");
+        }
+    }
+
     /**
      * Test the restore of a versionable node using a label.
      * @throws RepositoryException
@@ -327,6 +867,20 @@
     }
 
     /**
+     * Test the restore of a versionable node using a label.
+     * @throws RepositoryException
+     */
+    public void testRestoreLabelJcr2() throws RepositoryException {
+        // mark V1 with label test1
+        versionManager.getVersionHistory(versionableNode.getPath()).addVersionLabel(version.getName(), "test", true);
+
+        // restore V1 via label.
+        versionManager.restoreByLabel(versionableNode.getPath(), "test", true);
+        String value = versionableNode.getProperty(propertyName1).getString();
+        assertEquals("Node.restore('test') not correctly restored", propertyValue1, value);
+    }
+
+    /**
      * Test the restore of the OPV=Version child nodes.
      * @throws RepositoryException
      */
@@ -336,7 +890,7 @@
         if (!child1.isNodeType(mixVersionable)) {
             child1.addMixin(mixVersionable);
         }
-        versionableNode.save();
+        versionableNode.getSession().save();
         // create v1.0 of child
         Version v1Child = child1.checkin();
 
@@ -368,6 +922,47 @@
     }
 
     /**
+     * Test the restore of the OPV=Version child nodes.
+     * @throws RepositoryException
+     */
+    public void testRestoreNameJcr2() throws RepositoryException {
+        // V1.0 of versionableNode has no child
+        Node child1 = versionableNode.addNode(nodeName4);
+        if (!child1.isNodeType(mixVersionable)) {
+            child1.addMixin(mixVersionable);
+        }
+        versionableNode.getSession().save();
+        // create v1.0 of child
+        Version v1Child = child1.checkin();
+
+        // V1 of versionable node has child1
+        String v1 = versionManager.checkin(versionableNode.getPath()).getName();
+
+        // create V1.1 of child
+        versionManager.checkout(child1.getPath());
+        Version v11Child = versionManager.checkin(child1.getPath());
+
+        // V2 of versionable node has child1
+        versionManager.checkout(versionableNode.getPath());
+        String v2 = versionManager.checkin(versionableNode.getPath()).getName();
+
+        // restore 1.0 of versionable node --> no child
+        versionManager.restore(version, true);
+        assertFalse("restore must remove child node.", versionableNode.hasNode(nodeName4));
+
+        // restore V1 via name. since child was checkin first, 1.0 should be restored
+        versionManager.restore(versionableNode.getPath(), v1, true);
+        assertTrue("restore must restore child node.", versionableNode.hasNode(nodeName4));
+        child1 = versionableNode.getNode(nodeName4);
+        assertEquals("restore must restore child node version 1.0.", v1Child.getName(), versionManager.getBaseVersion(child1.getPath()).getName());
+
+        // restore V2 via name. child should be 1.1
+        versionManager.restore(versionableNode.getPath(), v2, true);
+        child1 = versionableNode.getNode(nodeName4);
+        assertEquals("Node.restore('foo') must restore child node version 1.1.", v11Child.getName(), versionManager.getBaseVersion(child1.getPath()).getName());
+    }
+
+    /**
      * Test the child ordering of restored nodes.
      * @throws RepositoryException
      */
@@ -375,7 +970,7 @@
         // create a test-root that has orderable child nodes
         Node testRoot = versionableNode.addNode(nodeName4, "nt:unstructured");
         testRoot.addMixin(mixVersionable);
-        versionableNode.save();
+        versionableNode.getSession().save();
 
         // create children of vNode and checkin
         Node child1 = testRoot.addNode(nodeName1);
@@ -386,7 +981,7 @@
         if (!child2.isNodeType(mixVersionable)) {
             child2.addMixin(mixVersionable);
         }
-        testRoot.save();
+        testRoot.getSession().save();
         child1.checkin();
         child2.checkin();
         Version v1 = testRoot.checkin();
@@ -394,7 +989,7 @@
         // remove node 1
         testRoot.checkout();
         child1.remove();
-        testRoot.save();
+        testRoot.getSession().save();
         testRoot.checkin();
 
         // restore version 1.0
@@ -415,11 +1010,11 @@
      * Test the child ordering of restored nodes.
      * @throws RepositoryException
      */
-    public void testRestoreOrder2() throws RepositoryException {
+    public void testRestoreOrderJcr2() throws RepositoryException {
         // create a test-root that has orderable child nodes
         Node testRoot = versionableNode.addNode(nodeName4, "nt:unstructured");
         testRoot.addMixin(mixVersionable);
-        versionableNode.save();
+        versionableNode.getSession().save();
 
         // create children of vNode and checkin
         Node child1 = testRoot.addNode(nodeName1);
@@ -430,19 +1025,19 @@
         if (!child2.isNodeType(mixVersionable)) {
             child2.addMixin(mixVersionable);
         }
-        testRoot.save();
-        child1.checkin();
-        child2.checkin();
-        Version v1 = testRoot.checkin();
+        testRoot.getSession().save();
+        versionManager.checkin(child1.getPath());
+        versionManager.checkin(child2.getPath());
+        Version v1 = versionManager.checkin(testRoot.getPath());
 
-        // reoder nodes
-        testRoot.checkout();
-        testRoot.orderBefore(nodeName2, nodeName1);
-        testRoot.save();
-        testRoot.checkin();
+        // remove node 1
+        versionManager.checkout(testRoot.getPath());
+        child1.remove();
+        testRoot.getSession().save();
+        versionManager.checkout(testRoot.getPath());
 
         // restore version 1.0
-        testRoot.restore(v1, true);
+        versionManager.restore(v1, true);
 
         // check order
         NodeIterator iter = testRoot.getNodes();
@@ -456,23 +1051,479 @@
     }
 
     /**
-     * Tests if restore on simple versioning creates a new version that is
-     * in the correct linear order.
+     * Test the child ordering of restored nodes.
+     * @throws RepositoryException
      */
-    public void testLinearVersions() throws Exception {
-        // first get all linear versions
-        VersionIterator iter = versionableNode.getVersionHistory().getAllLinearVersions();
-        StringBuffer expected = new StringBuffer();
-        while (iter.hasNext()) {
-            expected.append(iter.nextVersion().getName()).append(",");
+    public void testRestoreOrderJcr2_2() throws RepositoryException {
+        // create a test-root that has orderable child nodes
+        Node testRoot = versionableNode.addNode(nodeName4, "nt:unstructured");
+        testRoot.addMixin(mixVersionable);
+        versionableNode.getSession().save();
+
+        // create children of vNode and checkin
+        Node child1 = testRoot.addNode(nodeName1);
+        if (!child1.isNodeType(mixVersionable)) {
+            child1.addMixin(mixVersionable);
         }
-        // restore version
-        versionableNode.restore(version, true);
-        // append new base version
-        expected.append(versionableNode.getBaseVersion().getName()).append(",");
+        Node child2 = testRoot.addNode(nodeName2);
+        if (!child2.isNodeType(mixVersionable)) {
+            child2.addMixin(mixVersionable);
+        }
+        testRoot.getSession().save();
+        versionManager.checkin(child1.getPath());
+        versionManager.checkin(child2.getPath());
+        Version v1 = versionManager.checkin(testRoot.getPath());
 
-        // get the version names again
-        iter = versionableNode.getVersionHistory().getAllLinearVersions();
+        // remove node 1
+        versionManager.checkout(testRoot.getPath());
+        child1.remove();
+        testRoot.getSession().save();
+        versionManager.checkout(testRoot.getPath());
+
+        // restore version 1.0
+        versionManager.restore(testRoot.getPath(), v1, true);
+
+        // check order
+        NodeIterator iter = testRoot.getNodes();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n1 = iter.nextNode();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n2 = iter.nextNode();
+        String orderOk = nodeName1 + ", " + nodeName2;
+        String order = n1.getName() + ", " + n2.getName();
+        assertEquals("Invalid child node ordering", orderOk, order);
+    }
+
+    /**
+     * Test the child ordering of restored nodes.
+     * @throws RepositoryException
+     */
+    public void testRestoreOrderJcr2_3() throws RepositoryException {
+        // create a test-root that has orderable child nodes
+        Node testRoot = versionableNode.addNode(nodeName4, "nt:unstructured");
+        testRoot.addMixin(mixVersionable);
+        versionableNode.getSession().save();
+
+        // create children of vNode and checkin
+        Node child1 = testRoot.addNode(nodeName1);
+        if (!child1.isNodeType(mixVersionable)) {
+            child1.addMixin(mixVersionable);
+        }
+        Node child2 = testRoot.addNode(nodeName2);
+        if (!child2.isNodeType(mixVersionable)) {
+            child2.addMixin(mixVersionable);
+        }
+        testRoot.getSession().save();
+        versionManager.checkin(child1.getPath());
+        versionManager.checkin(child2.getPath());
+        Version v1 = versionManager.checkin(testRoot.getPath());
+
+        // remove node 1
+        versionManager.checkout(testRoot.getPath());
+        child1.remove();
+        testRoot.getSession().save();
+        versionManager.checkout(testRoot.getPath());
+
+        // restore version 1.0
+        versionManager.restore(testRoot.getPath(), v1.getName(), true);
+
+        // check order
+        NodeIterator iter = testRoot.getNodes();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n1 = iter.nextNode();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n2 = iter.nextNode();
+        String orderOk = nodeName1 + ", " + nodeName2;
+        String order = n1.getName() + ", " + n2.getName();
+        assertEquals("Invalid child node ordering", orderOk, order);
+    }
+
+    /**
+     * Test the child ordering of restored nodes.
+     * @throws RepositoryException
+     */
+    public void testRestoreOrderJcr2_4() throws RepositoryException {
+        // create a test-root that has orderable child nodes
+        Node testRoot = versionableNode.addNode(nodeName4, "nt:unstructured");
+        testRoot.addMixin(mixVersionable);
+        versionableNode.getSession().save();
+
+        // create children of vNode and checkin
+        Node child1 = testRoot.addNode(nodeName1);
+        if (!child1.isNodeType(mixVersionable)) {
+            child1.addMixin(mixVersionable);
+        }
+        Node child2 = testRoot.addNode(nodeName2);
+        if (!child2.isNodeType(mixVersionable)) {
+            child2.addMixin(mixVersionable);
+        }
+        testRoot.getSession().save();
+        versionManager.checkin(child1.getPath());
+        versionManager.checkin(child2.getPath());
+        Version v1 = versionManager.checkin(testRoot.getPath());
+
+        // remove node 1
+        versionManager.checkout(testRoot.getPath());
+        child1.remove();
+        testRoot.getSession().save();
+        versionManager.checkout(testRoot.getPath());
+
+        // restore version 1.0
+        versionManager.restore(new Version[] {v1}, true);
+
+        // check order
+        NodeIterator iter = testRoot.getNodes();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n1 = iter.nextNode();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n2 = iter.nextNode();
+        String orderOk = nodeName1 + ", " + nodeName2;
+        String order = n1.getName() + ", " + n2.getName();
+        assertEquals("Invalid child node ordering", orderOk, order);
+    }
+
+    /**
+     * Test the child ordering of restored nodes.
+     * @throws RepositoryException
+     */
+    public void testRestoreOrder2() throws RepositoryException {
+        // create a test-root that has orderable child nodes
+        Node testRoot = versionableNode.addNode(nodeName4, "nt:unstructured");
+        testRoot.addMixin(mixVersionable);
+        versionableNode.getSession().save();
+
+        // create children of vNode and checkin
+        Node child1 = testRoot.addNode(nodeName1);
+        if (!child1.isNodeType(mixVersionable)) {
+            child1.addMixin(mixVersionable);
+        }
+        Node child2 = testRoot.addNode(nodeName2);
+        if (!child2.isNodeType(mixVersionable)) {
+            child2.addMixin(mixVersionable);
+        }
+        testRoot.getSession().save();
+        child1.checkin();
+        child2.checkin();
+        Version v1 = testRoot.checkin();
+
+        // reoder nodes
+        testRoot.checkout();
+        testRoot.orderBefore(nodeName2, nodeName1);
+        testRoot.getSession().save();
+        testRoot.checkin();
+
+        // restore version 1.0
+        testRoot.restore(v1, true);
+
+        // check order
+        NodeIterator iter = testRoot.getNodes();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n1 = iter.nextNode();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n2 = iter.nextNode();
+        String orderOk = nodeName1 + ", " + nodeName2;
+        String order = n1.getName() + ", " + n2.getName();
+        assertEquals("Invalid child node ordering", orderOk, order);
+    }
+
+    /**
+     * Test the child ordering of restored nodes.
+     * @throws RepositoryException
+     */
+    public void testRestoreOrder2Jcr2() throws RepositoryException {
+        // create a test-root that has orderable child nodes
+        Node testRoot = versionableNode.addNode(nodeName4, "nt:unstructured");
+        testRoot.addMixin(mixVersionable);
+        versionableNode.getSession().save();
+
+        // create children of vNode and checkin
+        Node child1 = testRoot.addNode(nodeName1);
+        if (!child1.isNodeType(mixVersionable)) {
+            child1.addMixin(mixVersionable);
+        }
+        Node child2 = testRoot.addNode(nodeName2);
+        if (!child2.isNodeType(mixVersionable)) {
+            child2.addMixin(mixVersionable);
+        }
+        testRoot.getSession().save();
+        versionManager.checkin(child1.getPath());
+        versionManager.checkin(child2.getPath());
+        Version v1 =  versionManager.checkin(testRoot.getPath());
+
+        // reoder nodes
+        versionManager.checkout(testRoot.getPath());
+        testRoot.orderBefore(nodeName2, nodeName1);
+        testRoot.getSession().save();
+        versionManager.checkin(testRoot.getPath());
+
+        // restore version 1.0
+        versionManager.restore(v1, true);
+
+        // check order
+        NodeIterator iter = testRoot.getNodes();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n1 = iter.nextNode();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n2 = iter.nextNode();
+        String orderOk = nodeName1 + ", " + nodeName2;
+        String order = n1.getName() + ", " + n2.getName();
+        assertEquals("Invalid child node ordering", orderOk, order);
+    }
+
+    /**
+     * Test the child ordering of restored nodes.
+     * @throws RepositoryException
+     */
+    public void testRestoreOrder2Jcr2_2() throws RepositoryException {
+        // create a test-root that has orderable child nodes
+        Node testRoot = versionableNode.addNode(nodeName4, "nt:unstructured");
+        testRoot.addMixin(mixVersionable);
+        versionableNode.getSession().save();
+
+        // create children of vNode and checkin
+        Node child1 = testRoot.addNode(nodeName1);
+        if (!child1.isNodeType(mixVersionable)) {
+            child1.addMixin(mixVersionable);
+        }
+        Node child2 = testRoot.addNode(nodeName2);
+        if (!child2.isNodeType(mixVersionable)) {
+            child2.addMixin(mixVersionable);
+        }
+        testRoot.getSession().save();
+        versionManager.checkin(child1.getPath());
+        versionManager.checkin(child2.getPath());
+        Version v1 =  versionManager.checkin(testRoot.getPath());
+
+        // reoder nodes
+        versionManager.checkout(testRoot.getPath());
+        testRoot.orderBefore(nodeName2, nodeName1);
+        testRoot.getSession().save();
+        versionManager.checkin(testRoot.getPath());
+
+        // restore version 1.0
+        versionManager.restore(testRoot.getPath(), v1, true);
+
+        // check order
+        NodeIterator iter = testRoot.getNodes();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n1 = iter.nextNode();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n2 = iter.nextNode();
+        String orderOk = nodeName1 + ", " + nodeName2;
+        String order = n1.getName() + ", " + n2.getName();
+        assertEquals("Invalid child node ordering", orderOk, order);
+    }
+
+    /**
+     * Test the child ordering of restored nodes.
+     * @throws RepositoryException
+     */
+    public void testRestoreOrder2Jcr2_3() throws RepositoryException {
+        // create a test-root that has orderable child nodes
+        Node testRoot = versionableNode.addNode(nodeName4, "nt:unstructured");
+        testRoot.addMixin(mixVersionable);
+        versionableNode.getSession().save();
+
+        // create children of vNode and checkin
+        Node child1 = testRoot.addNode(nodeName1);
+        if (!child1.isNodeType(mixVersionable)) {
+            child1.addMixin(mixVersionable);
+        }
+        Node child2 = testRoot.addNode(nodeName2);
+        if (!child2.isNodeType(mixVersionable)) {
+            child2.addMixin(mixVersionable);
+        }
+        testRoot.getSession().save();
+        versionManager.checkin(child1.getPath());
+        versionManager.checkin(child2.getPath());
+        Version v1 =  versionManager.checkin(testRoot.getPath());
+
+        // reoder nodes
+        versionManager.checkout(testRoot.getPath());
+        testRoot.orderBefore(nodeName2, nodeName1);
+        testRoot.getSession().save();
+        versionManager.checkin(testRoot.getPath());
+
+        // restore version 1.0
+        versionManager.restore(testRoot.getPath(), v1, true);
+
+        // check order
+        NodeIterator iter = testRoot.getNodes();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n1 = iter.nextNode();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n2 = iter.nextNode();
+        String orderOk = nodeName1 + ", " + nodeName2;
+        String order = n1.getName() + ", " + n2.getName();
+        assertEquals("Invalid child node ordering", orderOk, order);
+    }
+
+    /**
+     * Test the child ordering of restored nodes.
+     * @throws RepositoryException
+     */
+    public void testRestoreOrder2Jcr2_4() throws RepositoryException {
+        // create a test-root that has orderable child nodes
+        Node testRoot = versionableNode.addNode(nodeName4, "nt:unstructured");
+        testRoot.addMixin(mixVersionable);
+        versionableNode.getSession().save();
+
+        // create children of vNode and checkin
+        Node child1 = testRoot.addNode(nodeName1);
+        if (!child1.isNodeType(mixVersionable)) {
+            child1.addMixin(mixVersionable);
+        }
+        Node child2 = testRoot.addNode(nodeName2);
+        if (!child2.isNodeType(mixVersionable)) {
+            child2.addMixin(mixVersionable);
+        }
+        testRoot.getSession().save();
+        versionManager.checkin(child1.getPath());
+        versionManager.checkin(child2.getPath());
+        Version v1 =  versionManager.checkin(testRoot.getPath());
+
+        // reoder nodes
+        versionManager.checkout(testRoot.getPath());
+        testRoot.orderBefore(nodeName2, nodeName1);
+        testRoot.getSession().save();
+        versionManager.checkin(testRoot.getPath());
+
+        // restore version 1.0
+        versionManager.restore(new Version[] {v1}, true);
+
+        // check order
+        NodeIterator iter = testRoot.getNodes();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n1 = iter.nextNode();
+        assertTrue(testRoot.getName() + " should have 2 child nodes.", iter.hasNext());
+        Node n2 = iter.nextNode();
+        String orderOk = nodeName1 + ", " + nodeName2;
+        String order = n1.getName() + ", " + n2.getName();
+        assertEquals("Invalid child node ordering", orderOk, order);
+    }
+
+    /**
+     * Tests if restore on simple versioning creates a new version that is
+     * in the correct linear order.
+     */
+    public void testLinearVersions() throws Exception {
+        // first get all linear versions
+        VersionIterator iter = versionableNode.getVersionHistory().getAllLinearVersions();
+        StringBuffer expected = new StringBuffer();
+        while (iter.hasNext()) {
+            expected.append(iter.nextVersion().getName()).append(",");
+        }
+        // restore version
+        versionableNode.restore(version, true);
+        // append new base version
+        expected.append(versionableNode.getBaseVersion().getName()).append(",");
+
+        // get the version names again
+        iter = versionableNode.getVersionHistory().getAllLinearVersions();
+        StringBuffer actual = new StringBuffer();
+        while (iter.hasNext()) {
+            actual.append(iter.nextVersion().getName()).append(",");
+        }
+        assertEquals("Node.restore() on simple versioning must create a new version.",
+                expected.toString(), actual.toString());
+    }
+
+    /**
+     * Tests if restore on simple versioning creates a new version that is
+     * in the correct linear order.
+     */
+    public void testLinearVersionsJcr2() throws Exception {
+        // first get all linear versions
+        VersionIterator iter = versionManager.getVersionHistory(versionableNode.getPath()).getAllLinearVersions();
+        StringBuffer expected = new StringBuffer();
+        while (iter.hasNext()) {
+            expected.append(iter.nextVersion().getName()).append(",");
+        }
+        // restore version
+        versionManager.restore(version, true);
+        // append new base version
+        expected.append(versionManager.getBaseVersion(versionableNode.getPath()).getName()).append(",");
+
+        // get the version names again
+        iter = versionManager.getVersionHistory(versionableNode.getPath()).getAllLinearVersions();
+        StringBuffer actual = new StringBuffer();
+        while (iter.hasNext()) {
+            actual.append(iter.nextVersion().getName()).append(",");
+        }
+        assertEquals("Node.restore() on simple versioning must create a new version.",
+                expected.toString(), actual.toString());
+    }
+
+    /**
+     * Tests if restore on simple versioning creates a new version that is
+     * in the correct linear order.
+     */
+    public void testLinearVersionsJcr2_2() throws Exception {
+        // first get all linear versions
+        VersionIterator iter = versionManager.getVersionHistory(versionableNode.getPath()).getAllLinearVersions();
+        StringBuffer expected = new StringBuffer();
+        while (iter.hasNext()) {
+            expected.append(iter.nextVersion().getName()).append(",");
+        }
+        // restore version
+        versionManager.restore(versionableNode.getPath(), version, true);
+        // append new base version
+        expected.append(versionManager.getBaseVersion(versionableNode.getPath()).getName()).append(",");
+
+        // get the version names again
+        iter = versionManager.getVersionHistory(versionableNode.getPath()).getAllLinearVersions();
+        StringBuffer actual = new StringBuffer();
+        while (iter.hasNext()) {
+            actual.append(iter.nextVersion().getName()).append(",");
+        }
+        assertEquals("Node.restore() on simple versioning must create a new version.",
+                expected.toString(), actual.toString());
+    }
+
+    /**
+     * Tests if restore on simple versioning creates a new version that is
+     * in the correct linear order.
+     */
+    public void testLinearVersionsJcr2_3() throws Exception {
+        // first get all linear versions
+        VersionIterator iter = versionManager.getVersionHistory(versionableNode.getPath()).getAllLinearVersions();
+        StringBuffer expected = new StringBuffer();
+        while (iter.hasNext()) {
+            expected.append(iter.nextVersion().getName()).append(",");
+        }
+        // restore version
+        versionManager.restore(versionableNode.getPath(), version.getName(), true);
+        // append new base version
+        expected.append(versionManager.getBaseVersion(versionableNode.getPath()).getName()).append(",");
+
+        // get the version names again
+        iter = versionManager.getVersionHistory(versionableNode.getPath()).getAllLinearVersions();
+        StringBuffer actual = new StringBuffer();
+        while (iter.hasNext()) {
+            actual.append(iter.nextVersion().getName()).append(",");
+        }
+        assertEquals("Node.restore() on simple versioning must create a new version.",
+                expected.toString(), actual.toString());
+    }
+
+    /**
+     * Tests if restore on simple versioning creates a new version that is
+     * in the correct linear order.
+     */
+    public void testLinearVersionsJcr2_4() throws Exception {
+        // first get all linear versions
+        VersionIterator iter = versionManager.getVersionHistory(versionableNode.getPath()).getAllLinearVersions();
+        StringBuffer expected = new StringBuffer();
+        while (iter.hasNext()) {
+            expected.append(iter.nextVersion().getName()).append(",");
+        }
+        // restore version
+        versionManager.restore(new Version[] {version}, true);
+        // append new base version
+        expected.append(versionManager.getBaseVersion(versionableNode.getPath()).getName()).append(",");
+
+        // get the version names again
+        iter = versionManager.getVersionHistory(versionableNode.getPath()).getAllLinearVersions();
         StringBuffer actual = new StringBuffer();
         while (iter.hasNext()) {
             actual.append(iter.nextVersion().getName()).append(",");

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValue.java?rev=777313&r1=777312&r2=777313&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValue.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/AbstractQValue.java Thu May 21 23:11:22 2009
@@ -28,6 +28,8 @@
 import javax.jcr.ValueFormatException;
 import java.util.Calendar;
 import java.util.TimeZone;
+import java.math.BigDecimal;
+import java.net.URI;
 
 /**
  * <code>AbstractQValue</code>...
@@ -143,6 +145,28 @@
         this(value, PropertyType.PATH);
     }
 
+    /**
+     * Create a new <code>AbstractQValue</code>.
+     *
+     * @param value
+     * @throws IllegalArgumentException if the passed <code>value</code>
+     * is <code>null</code>.
+     */
+    protected AbstractQValue(BigDecimal value) {
+        this(value, PropertyType.DECIMAL);
+    }
+
+    /**
+     * Create a new <code>AbstractQValue</code>.
+     *
+     * @param value
+     * @throws IllegalArgumentException if the passed <code>value</code>
+     * is <code>null</code>.
+     */
+    protected AbstractQValue(URI value) {
+        this(value, PropertyType.URI);
+    }
+
     //---------------------------------------------------------< QValue >---
     /**
      * @see QValue#getType()
@@ -187,6 +211,10 @@
             Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+00:00"));
             cal.setTimeInMillis(((Long) val).longValue());
             return cal;
+        } else if (type == PropertyType.DECIMAL) {
+            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+00:00"));
+            cal.setTimeInMillis(((BigDecimal) val).longValue());
+            return cal;
         } else {
             Calendar cal = ISO8601.parse(getString());
             if (cal == null) {
@@ -198,6 +226,36 @@
     }
 
     /**
+     * @see QValue#getDecimal()
+     */
+    public BigDecimal getDecimal() throws RepositoryException {
+        if (type == PropertyType.DECIMAL) {
+            return (BigDecimal) val;
+        } else {
+            try {
+                return new BigDecimal(getString());
+            } catch (NumberFormatException e) {
+                throw new ValueFormatException("not a valid decimal string: " + getString(), e);
+            }
+        }
+    }
+
+    /**
+     * @see QValue#getURI()
+     */
+    public URI getURI() throws RepositoryException {
+        if (type == PropertyType.URI) {
+            return (URI) val;
+        } else {
+            try {
+                return URI.create(getString());
+            } catch (IllegalArgumentException e) {
+                throw new ValueFormatException("not a valid uri: " + getString(), e);
+            }
+        }
+    }
+
+    /**
      * @see QValue#getDouble()
      */
     public double getDouble() throws RepositoryException {
@@ -205,6 +263,8 @@
             return ((Double) val).doubleValue();
         } else if (type == PropertyType.DATE) {
             return ((Calendar) val).getTimeInMillis();
+        } else if (type == PropertyType.DECIMAL) {
+            return ((BigDecimal) val).doubleValue();
         } else {
             try {
                 return Double.parseDouble(getString());
@@ -222,6 +282,8 @@
             return ((Long) val).longValue();
         } else if (type == PropertyType.DOUBLE) {
             return ((Double) val).longValue();
+        } else if (type == PropertyType.DECIMAL) {
+            return ((BigDecimal) val).longValue();
         } else if (type == PropertyType.DATE) {
             return ((Calendar) val).getTimeInMillis();
         } else {

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueFactoryImpl.java?rev=777313&r1=777312&r2=777313&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueFactoryImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/value/QValueFactoryImpl.java Thu May 21 23:11:22 2009
@@ -41,6 +41,9 @@
 import java.io.UnsupportedEncodingException;
 import java.util.Arrays;
 import java.util.Calendar;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.net.URISyntaxException;
 
 /**
  * <code>QValueFactoryImpl</code>...
@@ -583,6 +586,28 @@
         }
 
         /**
+         * @see QValue#getDecimal()
+         */
+        public BigDecimal getDecimal() throws RepositoryException {
+            try {
+                return new BigDecimal(getString());
+            } catch (NumberFormatException ex) {
+                throw new ValueFormatException(ex);
+            }
+        }
+
+        /**
+         * @see QValue#getURI()
+         */
+        public URI getURI() throws RepositoryException {
+            try {
+                return new URI(getString());
+            } catch (URISyntaxException ex) {
+                throw new ValueFormatException(ex);
+            }
+        }
+
+        /**
          * Frees temporarily allocated resources such as temporary file, buffer, etc.
          * If this <code>BinaryQValue</code> is backed by a persistent resource
          * calling this method will have no effect.

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/QValue.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/QValue.java?rev=777313&r1=777312&r2=777313&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/QValue.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/QValue.java Thu May 21 23:11:22 2009
@@ -18,6 +18,8 @@
 
 import java.io.InputStream;
 import java.util.Calendar;
+import java.math.BigDecimal;
+import java.net.URI;
 
 import javax.jcr.Property;
 import javax.jcr.PropertyType;
@@ -76,7 +78,7 @@
     public String getString() throws RepositoryException;
 
     /**
-     * Returns a <code>InputStream</code> representation of this <code>QValue</code>
+     * Returns an <code>InputStream</code> representation of this <code>QValue</code>
      * object.
      *
      * @return A stream representation of this value.
@@ -93,6 +95,14 @@
     public Calendar getCalendar() throws RepositoryException;
 
     /**
+     * Returns a <code>BigDecimal</code> representation of this value.
+     *
+     * @return A <code>BigDecimal</code> representation of this value.
+     * @throws RepositoryException if an error occurs.
+     */
+    public BigDecimal getDecimal() throws RepositoryException;
+
+    /**
      * Returns a <code>double</code> representation of this value.
      *
      * @return A <code>double</code> representation of this value.
@@ -134,6 +144,14 @@
     public Path getPath() throws RepositoryException;
 
     /**
+     * Returns an <code>URI</code> representation of this value.
+     *
+     * @return A <code>URI</code> representation of this value.
+     * @throws RepositoryException if an error occurs.
+     */
+    public URI getURI() throws RepositoryException;
+
+    /**
      * Frees temporarily allocated resources such as temporary file, buffer, etc.
      */
     public void discard();

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-spi2dav/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-spi2dav/pom.xml?rev=777313&r1=777312&r2=777313&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-spi2dav/pom.xml (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-spi2dav/pom.xml Thu May 21 23:11:22 2009
@@ -48,14 +48,6 @@
   <build>
     <plugins>
       <plugin>
-        <inherited>true</inherited>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <configuration>
-          <target>1.4</target>
-          <source>1.4</source>
-        </configuration>
-      </plugin>
-      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/QValueFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/QValueFactoryImpl.java?rev=777313&r1=777312&r2=777313&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/QValueFactoryImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/QValueFactoryImpl.java Thu May 21 23:11:22 2009
@@ -58,6 +58,9 @@
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.TimeZone;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.net.URISyntaxException;
 
 /**
  * <code>ValueFactoryImpl</code>...
@@ -745,6 +748,28 @@
         }
 
         /**
+         * @see QValue#getDecimal()
+         */
+        public BigDecimal getDecimal() throws RepositoryException {
+            try {
+                return new BigDecimal(getString());
+            } catch (NumberFormatException ex) {
+                throw new ValueFormatException(ex);
+            }
+        }
+
+        /**
+         * @see QValue#getURI()
+         */
+        public URI getURI() throws RepositoryException {
+            try {
+                return new URI(getString());
+            } catch (URISyntaxException ex) {
+                throw new ValueFormatException(ex);
+            }
+        }
+
+        /**
          * Frees temporarily allocated resources such as temporary file, buffer, etc.
          * If this <code>BinaryQValue</code> is backed by a persistent resource
          * calling this method will have no effect.

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-spi2jcr/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-spi2jcr/pom.xml?rev=777313&r1=777312&r2=777313&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-spi2jcr/pom.xml (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-spi2jcr/pom.xml Thu May 21 23:11:22 2009
@@ -78,6 +78,7 @@
                 org.apache.jackrabbit.test.api.observation.NodeMovedTest
                 org.apache.jackrabbit.test.api.observation.NodeReorderTest
                 org.apache.jackrabbit.test.api.observation.EventJournalTest
+                org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreNameJcr2
               </value>
             </property>
           </systemProperties>

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-standalone/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-standalone/pom.xml?rev=777313&r1=777312&r2=777313&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-standalone/pom.xml (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-standalone/pom.xml Thu May 21 23:11:22 2009
@@ -77,7 +77,6 @@
     <dependency>
       <groupId>javax.jcr</groupId>
       <artifactId>jcr</artifactId>
-      <version>1.0</version>
       <scope>compile</scope>
     </dependency>
     <dependency>

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-standalone/src/main/java/org/apache/jackrabbit/standalone/Main.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-standalone/src/main/java/org/apache/jackrabbit/standalone/Main.java?rev=777313&r1=777312&r2=777313&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-standalone/src/main/java/org/apache/jackrabbit/standalone/Main.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-standalone/src/main/java/org/apache/jackrabbit/standalone/Main.java Thu May 21 23:11:22 2009
@@ -19,7 +19,6 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.BindException;
 import java.net.URL;
 
 import org.apache.commons.cli.CommandLine;
@@ -28,6 +27,8 @@
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
 import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.core.RepositoryCopier;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
 import org.apache.jackrabbit.servlet.jackrabbit.JackrabbitRepositoryServlet;
 import org.apache.log4j.FileAppender;
 import org.apache.log4j.Layout;
@@ -70,6 +71,8 @@
         options.addOption("?", "help", false, "print this message");
         options.addOption("n", "notice", false, "print copyright notices");
         options.addOption("l", "license", false, "print license information");
+        options.addOption(
+                "b", "backup", false, "create a backup of the repository");
 
         options.addOption("q", "quiet", false, "disable console output");
         options.addOption("d", "debug", false, "enable debug logging");
@@ -79,6 +82,12 @@
         options.addOption("f", "file", true, "location of this jar file");
         options.addOption("r", "repo", true, "repository directory (jackrabbit)");
         options.addOption("c", "conf", true, "repository configuration file");
+        options.addOption(
+                "R", "backup-repo", true,
+                "backup repository directory (jackrabbit-backupN)");
+        options.addOption(
+                "C", "backup-conf", true,
+                "backup repository configuration file");
 
         command = new GnuParser().parse(options, args);
     }
@@ -118,32 +127,71 @@
             message("Writing log messages to " + log);
             prepareServerLog(log);
 
-            message("Starting the server...");
-            prepareWebapp(file, repository, tmp);
-            accessLog.setHandler(webapp);
-            prepareAccessLog(log);
-            server.setHandler(accessLog);
-            prepareConnector();
-            server.addConnector(connector);
-            prepareShutdown();
-
-            try {
-                server.start();
-
-                String host = connector.getHost();
-                if (host == null) {
-                    host = "localhost";
+            if (command.hasOption("backup")) {
+                backup(repository);
+            } else {
+                message("Starting the server...");
+                prepareWebapp(file, repository, tmp);
+                accessLog.setHandler(webapp);
+                prepareAccessLog(log);
+                server.setHandler(accessLog);
+                prepareConnector();
+                server.addConnector(connector);
+                prepareShutdown();
+
+                try {
+                    server.start();
+
+                    String host = connector.getHost();
+                    if (host == null) {
+                        host = "localhost";
+                    }
+                    message("Apache Jackrabbit is now running at "
+                            +"http://" + host + ":" + connector.getPort() + "/");
+                } catch (Throwable t) {
+                    System.err.println(
+                            "Unable to start the server: " + t.getMessage());
+                    System.exit(1);
                 }
-                message("Apache Jackrabbit is now running at "
-                        +"http://" + host + ":" + connector.getPort() + "/");
-            } catch (Throwable t) {
-                System.err.println(
-                        "Unable to start the server: " + t.getMessage());
-                System.exit(1);
             }
         }
     }
 
+    private void backup(File sourceDir) throws Exception {
+        RepositoryConfig source;
+        if (command.hasOption("conf")) {
+            source = RepositoryConfig.create(
+                    new File(command.getOptionValue("conf")), sourceDir);
+        } else {
+            source = RepositoryConfig.create(sourceDir);
+        }
+
+        File targetDir;
+        if (command.hasOption("backup-repo")) {
+            targetDir = new File(command.getOptionValue("backup-repo"));
+        } else {
+            int i = 1;
+            do {
+                targetDir = new File("jackrabbit-backup" + i++);
+            } while (targetDir.exists());
+        }
+
+        RepositoryConfig target;
+        if (command.hasOption("backup-conf")) {
+            target = RepositoryConfig.install(
+                    new File(command.getOptionValue("backup-conf")), targetDir);
+        } else {
+            target = RepositoryConfig.install(targetDir);
+        }
+
+        message("Creating a repository copy in " + targetDir);
+
+        RepositoryCopier copier = new RepositoryCopier(source, target);
+        copier.copy();
+
+        message("The repository has been successfully copied.");
+    }
+
     private void prepareServerLog(File log)
             throws IOException {
         Layout layout =