/* * 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.jackrabbit.test.api.version; import org.apache.jackrabbit.test.NotExecutableException; import javax.jcr.nodetype.NodeDefinition; import javax.jcr.version.Version; import javax.jcr.version.VersionException; import javax.jcr.version.OnParentVersionAction; import javax.jcr.version.VersionManager; import javax.jcr.Session; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.ItemNotFoundException; import javax.jcr.InvalidItemStateException; import javax.jcr.ItemExistsException; /** * <code>WorkspaceRestoreTest</code> provides test methods for the {@link javax.jcr.Workspace#restore(javax.jcr.version.Version[], boolean)} * method. * */ public class WorkspaceRestoreTest extends AbstractVersionTest { Session wSuperuser; Version version; Version version2; Version rootVersion; Node versionableNode2; Node wTestRoot; Node wVersionableNode; Node wVersionableNode2; Node wVersionableChildNode; Version wChildVersion; protected void setUp() throws Exception { super.setUp(); VersionManager versionManager = versionableNode.getSession().getWorkspace().getVersionManager(); String path = versionableNode.getPath(); version = versionManager.checkin(path); versionManager.checkout(path); version2 = versionManager.checkin(path); versionManager.checkout(path); rootVersion = versionManager.getVersionHistory(path).getRootVersion(); // build a second versionable node below the testroot try { versionableNode2 = createVersionableNode(testRootNode, nodeName2, versionableNodeType); } catch (RepositoryException e) { fail("Failed to create a second versionable node: " + e.getMessage()); } try { wSuperuser = getHelper().getSuperuserSession(workspaceName); } catch (RepositoryException e) { fail("Failed to retrieve superuser session for second workspace '" + workspaceName + "': " + e.getMessage()); } // test if the required nodes exist in the second workspace if not try to clone them try { testRootNode.getCorrespondingNodePath(workspaceName); } catch (ItemNotFoundException e) { // clone testRoot wSuperuser.getWorkspace().clone(superuser.getWorkspace().getName(), testRoot, testRoot, true); } try { versionableNode.getCorrespondingNodePath(workspaceName); } catch (ItemNotFoundException e) { // clone versionable node wSuperuser.getWorkspace().clone(superuser.getWorkspace().getName(), versionableNode.getPath(), versionableNode.getPath(), true); } try { versionableNode2.getCorrespondingNodePath(workspaceName); } catch (ItemNotFoundException e) { // clone second versionable node wSuperuser.getWorkspace().clone(superuser.getWorkspace().getName(), versionableNode2.getPath(), versionableNode2.getPath(), true); } try { // set node-fields (wTestRoot, wVersionableNode, wVersionableNode2) // and check versionable nodes out. wTestRoot = (Node) wSuperuser.getItem(testRootNode.getPath()); wVersionableNode = wSuperuser.getNodeByIdentifier(versionableNode.getIdentifier()); wVersionableNode.getSession().getWorkspace().getVersionManager().checkout(wVersionableNode.getPath()); wVersionableNode2 = wSuperuser.getNodeByIdentifier(versionableNode2.getIdentifier()); wVersionableNode2.getSession().getWorkspace().getVersionManager().checkout(wVersionableNode2.getPath()); } catch (RepositoryException e) { fail("Failed to setup test environment in workspace: " + e.toString()); } // create persistent versionable CHILD-node below wVersionableNode in workspace 2 // that is not present in the default workspace. try { wVersionableChildNode = createVersionableNode(wVersionableNode, nodeName4, versionableNodeType); } catch (RepositoryException e) { fail("Failed to create versionable child node in second workspace: " + e.getMessage()); } // create a version of the versionable child node VersionManager wVersionManager = wVersionableChildNode.getSession().getWorkspace().getVersionManager(); String wPath = wVersionableChildNode.getPath(); wVersionManager.checkout(wPath); wChildVersion = wVersionManager.checkin(wPath); wVersionManager.checkout(wPath); } protected void tearDown() throws Exception { try { // remove all versionable nodes below the test versionableNode2.remove(); wVersionableNode.remove(); wVersionableNode2.remove(); wTestRoot.save(); } finally { if (wSuperuser != null) { wSuperuser.logout(); wSuperuser = null; } version = null; version2 = null; rootVersion = null; versionableNode2 = null; wTestRoot = null; wVersionableNode = null; wVersionableNode2 = null; wVersionableChildNode = null; wChildVersion = null; super.tearDown(); } } /** * Test if InvalidItemStateException is thrown if the session affected by * Workspace.restore(Version[], boolean) has pending changes. */ @SuppressWarnings("deprecation") public void testWorkspaceRestoreWithPendingChanges() throws RepositoryException { versionableNode.checkout(); try { // modify node without calling save() versionableNode.setProperty(propertyName1, propertyValue); // create version in second workspace Version v = wVersionableNode.checkin(); // try to restore that version superuser.getWorkspace().restore(new Version[]{v}, false); fail("InvalidItemStateException must be thrown on attempt to call Workspace.restore(Version[], boolean) in a session having any unsaved changes pending."); } catch (InvalidItemStateException e) { // success } } /** * Test if InvalidItemStateException is thrown if the session affected by * VersionManager.restore(Version[], boolean) has pending changes. */ public void testWorkspaceRestoreWithPendingChangesJcr2() throws RepositoryException { versionableNode.getSession().getWorkspace().getVersionManager().checkout(versionableNode.getPath()); try { // modify node without calling save() versionableNode.setProperty(propertyName1, propertyValue); // create version in second workspace Version v = wVersionableNode.getSession().getWorkspace().getVersionManager().checkin(wVersionableNode.getPath()); // try to restore that version superuser.getWorkspace().getVersionManager().restore(new Version[]{v}, false); fail("InvalidItemStateException must be thrown on attempt to call Workspace.restore(Version[], boolean) in a session having any unsaved changes pending."); } catch (InvalidItemStateException e) { // success } } /** * Test if VersionException is thrown if the specified version array does * not contain a version that has a corresponding node in this workspace. */ @SuppressWarnings("deprecation") public void testWorkspaceRestoreHasCorrespondingNode() throws RepositoryException { try { superuser.getWorkspace().restore(new Version[]{wChildVersion}, false); fail("Workspace.restore(Version[], boolean) must throw VersionException if non of the specified versions has a corresponding node in the workspace."); } catch (VersionException e) { // success } } /** * Test if VersionException is thrown if the specified version array does * not contain a version that has a corresponding node in this workspace. */ public void testWorkspaceRestoreHasCorrespondingNodeJcr2() throws RepositoryException { try { superuser.getWorkspace().getVersionManager().restore(new Version[]{wChildVersion}, false); fail("Workspace.restore(Version[], boolean) must throw VersionException if non of the specified versions has a corresponding node in the workspace."); } catch (VersionException e) { // success } } /** * Test if Workspace.restore(Version[], boolean) succeeds if the following two * preconditions are fulfilled:<ul> * <li>For every version V in S that corresponds to a missing node in the workspace, * there must also be a parent of V in S.</li> * <li>S must contain at least one version that corresponds to an existing * node in the workspace.</li> * </ul> */ @SuppressWarnings("deprecation") public void testWorkspaceRestoreWithParent() throws RepositoryException { try { Version parentV = wVersionableNode.checkin(); superuser.getWorkspace().restore(new Version[]{parentV, wChildVersion}, false); } catch (RepositoryException e) { fail("Workspace.restore(Version[], boolean) with a version that has no corresponding node must succeed if a version of a parent with correspondance is present in the version array."); } } /** * Test if VersionManager.restore(Version[], boolean) succeeds if the following two * preconditions are fulfilled:<ul> * <li>For every version V in S that corresponds to a missing node in the workspace, * there must also be a parent of V in S.</li> * <li>S must contain at least one version that corresponds to an existing * node in the workspace.</li> * </ul> */ public void testWorkspaceRestoreWithParentJcr2() throws RepositoryException { try { Version parentV = wVersionableNode.getSession().getWorkspace().getVersionManager().checkin(wVersionableNode.getPath()); superuser.getWorkspace().getVersionManager().restore(new Version[]{parentV, wChildVersion}, false); } catch (RepositoryException e) { fail("Workspace.restore(Version[], boolean) with a version that has no corresponding node must succeed if a version of a parent with correspondance is present in the version array."); } } /** * Test if the removeExisting-flag removes an existing node in case of uuid conflict. */ @SuppressWarnings("deprecation") public void testWorkspaceRestoreWithRemoveExisting() throws NotExecutableException, RepositoryException { // create version for parentNode of childNode superuser.getWorkspace().clone(workspaceName, wVersionableChildNode.getPath(), wVersionableChildNode.getPath(), false); Version parentV = versionableNode.checkin(); // move child node in order to produce the uuid conflict String newChildPath = wVersionableNode2.getPath() + "/" + wVersionableChildNode.getName(); wSuperuser.move(wVersionableChildNode.getPath(), newChildPath); wSuperuser.save(); // restore the parent with removeExisting == true >> moved child node // must be removed. wSuperuser.getWorkspace().restore(new Version[]{parentV}, true); if (wSuperuser.itemExists(newChildPath)) { fail("Workspace.restore(Version[], boolean) with the boolean flag set to true, must remove the existing node in case of Uuid conflict."); } } /** * Test if the removeExisting-flag removes an existing node in case of uuid conflict. */ public void testWorkspaceRestoreWithRemoveExistingJcr2() throws NotExecutableException, RepositoryException { // create version for parentNode of childNode superuser.getWorkspace().clone(workspaceName, wVersionableChildNode.getPath(), wVersionableChildNode.getPath(), false); Version parentV = versionableNode.getSession().getWorkspace().getVersionManager().checkin(versionableNode.getPath()); // move child node in order to produce the uuid conflict String newChildPath = wVersionableNode2.getPath() + "/" + wVersionableChildNode.getName(); wSuperuser.move(wVersionableChildNode.getPath(), newChildPath); wSuperuser.save(); // restore the parent with removeExisting == true >> moved child node // must be removed. wSuperuser.getWorkspace().getVersionManager().restore(new Version[]{parentV}, true); if (wSuperuser.itemExists(newChildPath)) { fail("Workspace.restore(Version[], boolean) with the boolean flag set to true, must remove the existing node in case of Uuid conflict."); } } /** * Tests if restoring the <code>Version</code> of an existing node throws an * <code>ItemExistsException</code> if removeExisting is set to FALSE. */ @SuppressWarnings("deprecation") public void testWorkspaceRestoreWithUUIDConflict() throws RepositoryException, NotExecutableException { try { // Verify that nodes used for the test are indeed versionable NodeDefinition nd = wVersionableNode.getDefinition(); if (nd.getOnParentVersion() != OnParentVersionAction.COPY && nd.getOnParentVersion() != OnParentVersionAction.VERSION) { throw new NotExecutableException("Nodes must be versionable in order to run this test."); } Version v = wVersionableNode.checkin(); wVersionableNode.checkout(); wSuperuser.move(wVersionableChildNode.getPath(), wVersionableNode2.getPath() + "/" + wVersionableChildNode.getName()); wSuperuser.save(); wSuperuser.getWorkspace().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 } } /** * Tests if restoring the <code>Version</code> of an existing node throws an * <code>ItemExistsException</code> if removeExisting is set to FALSE. */ public void testWorkspaceRestoreWithUUIDConflictJcr2() throws RepositoryException, NotExecutableException { try { // Verify that nodes used for the test are indeed versionable NodeDefinition nd = wVersionableNode.getDefinition(); if (nd.getOnParentVersion() != OnParentVersionAction.COPY && nd.getOnParentVersion() != OnParentVersionAction.VERSION) { throw new NotExecutableException("Nodes must be versionable in order to run this test."); } VersionManager versionManager = wVersionableNode.getSession().getWorkspace().getVersionManager(); String path = wVersionableNode.getPath(); Version v = versionManager.checkin(path); versionManager.checkout(path); wSuperuser.move(wVersionableChildNode.getPath(), wVersionableNode2.getPath() + "/" + wVersionableChildNode.getName()); wSuperuser.save(); wSuperuser.getWorkspace().getVersionManager().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 } } /** * Test if workspace-restoring a node works on checked-in node. */ @SuppressWarnings("deprecation") public void testWorkspaceRestoreOnCheckedInNode() throws RepositoryException { if (versionableNode.isCheckedOut()) { versionableNode.checkin(); } superuser.getWorkspace().restore(new Version[]{version}, true); } /** * Test if workspace-restoring a node works on checked-in node. */ public void testWorkspaceRestoreOnCheckedInNodeJcr2() throws RepositoryException { VersionManager versionManager = versionableNode.getSession().getWorkspace().getVersionManager(); String path = versionableNode.getPath(); if (versionManager.isCheckedOut(path)) { versionManager.checkin(path); } superuser.getWorkspace().getVersionManager().restore(new Version[]{version}, true); } /** * Test if workspace-restoring a node works on checked-out node. */ @SuppressWarnings("deprecation") public void testWorkspaceRestoreOnCheckedOutNode() throws RepositoryException { if (!versionableNode.isCheckedOut()) { versionableNode.checkout(); } superuser.getWorkspace().restore(new Version[]{version}, true); } /** * Test if workspace-restoring a node works on checked-out node. */ public void testWorkspaceRestoreOnCheckedOutNodeJcr2() throws RepositoryException { VersionManager versionManager = versionableNode.getSession().getWorkspace().getVersionManager(); String path = versionableNode.getPath(); if (!versionManager.isCheckedOut(path)) { versionManager.checkout(path); } superuser.getWorkspace().getVersionManager().restore(new Version[]{version}, true); } }