/*
* 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);
}
}