/* * Copyright (C) 2009 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.services.jcr.api.version; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.version.Version; import javax.jcr.version.VersionException; import javax.jcr.version.VersionHistory; import javax.jcr.version.VersionIterator; /** * Created by The eXo Platform SAS 07.05.2006 * * @author <a href="mailto:peter.nedonosko@exoplatform.com.ua">Peter * Nedonosko</a> * @version $Id: TestVersionHistory.java 11907 2008-03-13 15:36:21Z ksm $ */ public class TestVersionHistory extends BaseVersionTest { private Node testRoot = null; private Node testVersionable = null; public void setUp() throws Exception { super.setUp(); testRoot = root.addNode("testRoot"); testVersionable = testRoot.addNode("testVersionable", "nt:unstructured"); testVersionable.addMixin("mix:versionable"); root.save(); } protected void tearDown() throws Exception { try { testVersionable.checkout(); testRoot.remove(); root.save(); } catch (RepositoryException e) { log.error("tear down error: " + e, e); } super.tearDown(); } /** * Scenario (script): Creating nodes: n1, n2 making: ver.1 Creating nodes: * n1[2], n1[3], n1[4], n3 making: ver.2 Creating node: n4 making: ver.3 * Creating node: n5 making: ver.4 Removing nodes: n2, n4 Restoring ver.1: * (n1, n2) Creating node: n6 making: ver.1.1 Removing nodes: n1, n6 Restoring * ver.3: (n1, n1[2], n1[3], n1[4], n2, n3, n4) Creating node: n2[2] making: * ver.3.1 making: ver.3.1.1 Restoring ver.2 (n1, n1[2], n1[3], n1[4], n2, n3) * Creating node: n2[2] again!!! making: ver.2.1 * ------------------------------------------------- [PN] 08.05.06 Play in * same play as above. There are some problems in CMS Web UI ('Manage Version' * menu) if we will look on the version history of the /testVersionable node. * After ver.3 was restored we create n2 (n2[2]) and make a new version * ver.3.1. Then we go to 'Manage Version' menu item and will not see the base * version (ver.3.1, name is '6'). Same case history if we restore ver.1.1 * (named '5'), then add a node in the /testVersionable and make checkin. */ public void testVersionHistoryTree() throws Exception { // testVersionable = versionableNode; // it's nt:folder VersionHistory vHistory = testVersionable.getVersionHistory(); // Creating nodes: n1, n2 Node n1 = testVersionable.addNode("n1"); Node n2 = testVersionable.addNode("n2"); testVersionable.save(); Version ver1 = testVersionable.checkin(); // v1 vHistory.addVersionLabel(ver1.getName(), "ver.1", false); testVersionable.checkout(); // sameNameSibs nodes // Creating nodes: n1[2], n1[3], n1[4] Node snsN1_2 = testVersionable.addNode("n1"); Node snsN1_3 = testVersionable.addNode("n1"); Node snsN1_4 = testVersionable.addNode("n1"); // Creating node: n3 Node n3 = testVersionable.addNode("n3"); testVersionable.save(); Version ver2 = testVersionable.checkin(); // v2 vHistory.addVersionLabel(ver2.getName(), "ver.2", false); testVersionable.checkout(); // Creating node: n4 Node n4 = testVersionable.addNode("n4"); testVersionable.save(); Version ver3 = testVersionable.checkin(); // v3 vHistory.addVersionLabel(ver3.getName(), "ver.3", false); vHistory.addVersionLabel(ver3.getName(), "version 3.0", false); testVersionable.checkout(); // Creating node: n5 Node n5 = testVersionable.addNode("n5"); testVersionable.save(); Version ver4 = testVersionable.checkin(); // v4 vHistory.addVersionLabel(ver4.getName(), "ver.4", false); testVersionable.checkout(); if (log.isDebugEnabled()) log.debug("===== init ====="); checkItemsExisted(new String[]{n1.getPath(), snsN1_2.getPath(), snsN1_3.getPath(), snsN1_4.getPath(), n2.getPath(), n3.getPath(), n4.getPath(), n5.getPath()}, null); checkVersionHistory(testVersionable, 4); // removing nodes: n2, n4 n2.remove(); n4.remove(); testVersionable.save(); if (log.isDebugEnabled()) log.debug("===== ver.1 before restore ====="); checkItemsExisted(new String[]{n1.getPath(), snsN1_2.getPath(), snsN1_3.getPath(), snsN1_4.getPath(), n3.getPath(), n5.getPath()}, new String[]{n2.getPath(), n4.getPath()}); checkVersionHistory(testVersionable, 4); // RESTORE ver.1 and n1, n2 will be restored testVersionable.restore(ver1, true); if (log.isDebugEnabled()) log.debug("===== ver.1 after restore ====="); checkItemsExisted(new String[]{n1.getPath(), n2.getPath()}, new String[]{snsN1_2.getPath(), snsN1_3.getPath(), snsN1_4.getPath(), n3.getPath(), n4.getPath(), n5.getPath()}); checkVersionHistory(testVersionable, 4); testVersionable.checkout(); // adding nodes: n6 Node n6 = testVersionable.addNode("n6"); testVersionable.save(); Version ver11 = testVersionable.checkin(); // v1.1 vHistory.addVersionLabel(ver11.getName(), "ver.1.1", false); if (log.isDebugEnabled()) log.debug("===== ver.1.1 ====="); checkItemsExisted(new String[]{n1.getPath(), n2.getPath(), n6.getPath()}, new String[]{snsN1_2.getPath(), snsN1_3.getPath(), snsN1_4.getPath(), n3.getPath(), n4.getPath(), n5.getPath()}); checkVersionHistory(testVersionable, 5); // has five versions in history testVersionable.checkout(); // removing nodes: n1, n6 n1.remove(); n6.remove(); testVersionable.save(); if (log.isDebugEnabled()) log.debug("===== ver.3 before restore ====="); checkItemsExisted(new String[]{n2.getPath()}, new String[]{n1.getPath(), snsN1_2.getPath(), snsN1_3.getPath(), snsN1_4.getPath(), n2.getPath(), n3.getPath(), n4.getPath(), n5.getPath(), n6.getPath()}); checkVersionHistory(testVersionable, 5); // RESTORE ver.3 and n1, n1_2, n1_3, n1_4, n2, n3, n4 will be restored testVersionable.restore(ver3, true); if (log.isDebugEnabled()) log.debug("===== ver.3 after restore ====="); checkItemsExisted(new String[]{n1.getPath(), snsN1_2.getPath(), snsN1_3.getPath(), snsN1_4.getPath(), n2.getPath(), n3.getPath(), n4.getPath()}, new String[]{n5.getPath(), n6.getPath()}); checkVersionHistory(testVersionable, 5); testVersionable.checkout(); // adding node: n2[2] Node snsN2_2 = testVersionable.addNode("n2"); testVersionable.save(); Version ver31 = testVersionable.checkin(); // v3.1 vHistory.addVersionLabel(ver31.getName(), "ver.3.1", false); if (log.isDebugEnabled()) log.debug("===== ver.3.1 ====="); checkItemsExisted(new String[]{n1.getPath(), snsN1_2.getPath(), snsN1_3.getPath(), snsN1_4.getPath(), n2.getPath(), snsN2_2.getPath(), n3.getPath(), n4.getPath()}, new String[]{n5.getPath(), n6.getPath()}); checkVersionHistory(testVersionable, 6); testVersionable.checkout(); Version ver311 = testVersionable.checkin(); // v3.1.1 vHistory.addVersionLabel(ver311.getName(), "ver.3.1.1", false); if (log.isDebugEnabled()) log.debug("===== ver.2 before restore ====="); checkItemsExisted(new String[]{n1.getPath(), snsN1_2.getPath(), snsN1_3.getPath(), snsN1_4.getPath(), n2.getPath(), snsN2_2.getPath(), n3.getPath(), n4.getPath()}, new String[]{n5.getPath(), n6.getPath()}); checkVersionHistory(testVersionable, 7); // RESTORE ver.2 and n1, n1_2, n1_3, n1_4, n2, n3 will be restored testVersionable.restore(ver2, true); if (log.isDebugEnabled()) log.debug("===== ver.2 after restore ====="); // the node snsN2_2 points to a node with index 1 (result of reindex), i.e. // n2 (n2[1]) checkItemsExisted(new String[]{n1.getPath(), snsN1_2.getPath(), snsN1_3.getPath(), snsN1_4.getPath(), n2.getPath(), n3.getPath()}, new String[]{testVersionable.getPath() + "/n2[2]", n4.getPath(), n5.getPath(), n6.getPath()}); checkVersionHistory(testVersionable, 7); if (log.isDebugEnabled()) log.debug("===== ver.2.1 ====="); testVersionable.checkout(); // adding node: n2[2] again Node snsN2_2_Other = testVersionable.addNode("n2"); // testVersionable. // getNodes() snsN1_3.refresh(true); snsN1_3.remove(); // testVersionable.getNode(snsN1_3.getName() + "[3]").remove(); testVersionable.save(); // reindex: n1[4] -> n1[3] Version ver21 = testVersionable.checkin(); // v2.1 vHistory.addVersionLabel(ver21.getName(), "ver.2.1", false); // The node snsN2_2 has no actual node in the repository, it's phantom node // with old state. // But node with same path already created (snsN2_2_Other)! // // The node snsN1_3 has no actual node in the repository, it's phantom node // with old state. // But reindex done: n1[4] -> n1[3] and n1[3] already exists // checkItemsExisted(new String[]{n1.getPath(), snsN1_2.getPath(), snsN1_3.getPath(), n2.getPath(), snsN2_2_Other.getPath(), n3.getPath()}, new String[]{n4.getPath(), n5.getPath(), n6.getPath()}); checkVersionHistory(testVersionable, 8); } public void testRemoveBaseVersion() throws Exception { Node testRemove = testRoot.addNode("testRemove", "nt:unstructured"); testRemove.setProperty("exo:test","V0"); testRemove.addMixin("mix:versionable"); root.save(); VersionHistory vHistory = testRemove.getVersionHistory(); VersionIterator versionIterator = vHistory.getAllVersions(); Version rootVersion = vHistory.getRootVersion(); assertEquals(1, versionIterator.getSize()); assertEquals(rootVersion.getName(), versionIterator.nextVersion().getName()); Version ver1 = testRemove.checkin(); vHistory.addVersionLabel(ver1.getName(), "v1", false); testRemove.checkout(); versionIterator= vHistory.getAllVersions(); assertEquals(2, versionIterator.getSize()); Version ver2 = testRemove.checkin(); vHistory.addVersionLabel(ver2.getName(), "v2", false); testRemove.checkout(); versionIterator= vHistory.getAllVersions(); assertEquals(3, versionIterator.getSize()); Version baseVersion = testRemove.getBaseVersion(); assertEquals(baseVersion.getName(),vHistory.getVersionByLabel("v2").getName()); try { vHistory.removeVersion(vHistory.getVersionByLabel("v2").getName()); } catch (Exception e) { fail(); } baseVersion = testRemove.getBaseVersion(); assertEquals(baseVersion.getName(),vHistory.getVersionByLabel("v1").getName()); versionIterator= vHistory.getAllVersions(); assertEquals(2, versionIterator.getSize()); try { vHistory.removeVersion(vHistory.getVersionByLabel("v1").getName()); } catch (Exception e) { fail(); } baseVersion = testRemove.getBaseVersion(); assertEquals(baseVersion.getName(), rootVersion.getName()); versionIterator= vHistory.getAllVersions(); assertEquals(1, versionIterator.getSize()); } public void testRemoveBaseVersion1() throws Exception { Node testRemove = testRoot.addNode("testRemove", "nt:unstructured"); testRemove.setProperty("exo:test1","V0"); testRemove.addMixin("mix:versionable"); testRemove.addMixin("mix:lockable"); root.save(); VersionHistory vHistory = testRemove.getVersionHistory(); VersionIterator versionIterator = vHistory.getAllVersions(); assertEquals(1, versionIterator.getSize()); Version ver1 = testRemove.checkin(); vHistory.addVersionLabel(ver1.getName(), "v1", false); testRemove.checkout(); versionIterator= vHistory.getAllVersions(); assertEquals(2, versionIterator.getSize()); Version ver2 = testRemove.checkin(); vHistory.addVersionLabel(ver2.getName(), "v2", false); testRemove.checkout(); versionIterator= vHistory.getAllVersions(); assertEquals(3, versionIterator.getSize()); Version ver3 = testRemove.checkin(); vHistory.addVersionLabel(ver3.getName(), "v3", false); testRemove.checkout(); try { vHistory.removeVersion(vHistory.getVersionByLabel("v3").getName()); //Expected } catch (Exception e) { fail(); } Version baseVersion = testRemove.getBaseVersion(); assertEquals(baseVersion.getName(), vHistory.getVersionByLabel("v2").getName()); testRemove.restore(vHistory.getVersionByLabel("v1").getName(),true); baseVersion = testRemove.getBaseVersion(); assertEquals(baseVersion.getName(), vHistory.getVersionByLabel("v1").getName()); vHistory.removeVersion(vHistory.getVersionByLabel("v1").getName()); baseVersion = testRemove.getBaseVersion(); assertEquals(baseVersion.getName(), vHistory.getRootVersion().getName()); testRemove.restore(vHistory.getVersionByLabel("v2").getName(),true); baseVersion = testRemove.getBaseVersion(); assertEquals(baseVersion.getName(), vHistory.getVersionByLabel("v2").getName()); try { vHistory.removeVersion(vHistory.getVersionByLabel("v2").getName()); //Expected } catch (Exception e) { fail(); } baseVersion = testRemove.getBaseVersion(); assertEquals(baseVersion.getName(), vHistory.getRootVersion().getName()); try { vHistory.removeVersion(vHistory.getRootVersion().getName()); fail(); } catch (Exception e) { //Expected } } private VersionHistory prepareHistory() throws Exception { VersionHistory vHistory = testVersionable.getVersionHistory(); if (log.isDebugEnabled()) log.debug("===== prepare ====="); showVersionable(testVersionable); // Creating nodes: n1, n2 Node n1 = testVersionable.addNode("n1"); Node n2 = testVersionable.addNode("n2"); testVersionable.save(); Version ver1 = testVersionable.checkin(); // v1 vHistory.addVersionLabel(ver1.getName(), "ver.1", false); if (log.isDebugEnabled()) log.debug("===== ver.1 checkin ====="); showVersionable(testVersionable); testVersionable.checkout(); if (log.isDebugEnabled()) log.debug("===== ver.1 checkout ====="); showVersionable(testVersionable); // sameNameSibs nodes // Creating nodes: n1[2], n1[3], n1[4] Node snsN1_2 = testVersionable.addNode("n1"); Node snsN1_3 = testVersionable.addNode("n1"); Node snsN1_4 = testVersionable.addNode("n1"); // Creating node: n3 Node n3 = testVersionable.addNode("n3"); testVersionable.save(); Version ver2 = testVersionable.checkin(); // v2 vHistory.addVersionLabel(ver2.getName(), "ver.2", false); if (log.isDebugEnabled()) log.debug("===== ver.2 checkin ====="); showVersionable(testVersionable); testVersionable.checkout(); if (log.isDebugEnabled()) log.debug("===== ver.2 checkout ====="); showVersionable(testVersionable); // Creating node: n4 Node n4 = testVersionable.addNode("n4"); testVersionable.save(); Version ver3 = testVersionable.checkin(); // v3 vHistory.addVersionLabel(ver3.getName(), "ver.3", false); vHistory.addVersionLabel(ver3.getName(), "version 3.0", false); if (log.isDebugEnabled()) log.debug("===== ver.3 checkin ====="); showVersionable(testVersionable); testVersionable.checkout(); if (log.isDebugEnabled()) log.debug("===== ver.3 checkout ====="); showVersionable(testVersionable); // Creating node: n5 Node n5 = testVersionable.addNode("n5"); testVersionable.save(); Version ver4 = testVersionable.checkin(); // v4 vHistory.addVersionLabel(ver4.getName(), "ver.4", false); if (log.isDebugEnabled()) log.debug("===== ver.4 checkin ====="); showVersionable(testVersionable); testVersionable.checkout(); if (log.isDebugEnabled()) log.debug("===== ver.4 checkout ====="); showVersionable(testVersionable); return vHistory; } public void testVersionRemove() throws Exception { // -------- prepare the case -------- VersionHistory vHistory = prepareHistory(); if (log.isDebugEnabled()) log.debug("===== init ====="); checkItemsExisted(new String[]{"/testRoot/testVersionable/n1", "/testRoot/testVersionable/n1[2]", "/testRoot/testVersionable/n1[3]", "/testRoot/testVersionable/n1[4]", "/testRoot/testVersionable/n2", "/testRoot/testVersionable/n3", "/testRoot/testVersionable/n4", "/testRoot/testVersionable/n5"}, null); showVersionable(testVersionable); checkVersionHistory(testVersionable, 4); // -------- play with version remove -------- // we have v4 as base version, REMOVE v1 from history vHistory.removeVersion(vHistory.getVersionByLabel("ver.1").getName()); if (log.isDebugEnabled()) log.debug("===== ver.1 removed ====="); showVersionable(testVersionable); checkVersionHistory(testVersionable, 3); try { vHistory.getVersion("1"); fail("ver.1 must be not existed"); } catch (VersionException e) { // ok } // removing nodes: n2, n4 testVersionable.getNode("n2").remove(); testVersionable.getNode("n4").remove(); testVersionable.save(); if (log.isDebugEnabled()) log.debug("===== ver.3 before restore ====="); checkItemsExisted(new String[]{"/testRoot/testVersionable/n1", "/testRoot/testVersionable/n1[2]", "/testRoot/testVersionable/n1[3]", "/testRoot/testVersionable/n1[4]", "/testRoot/testVersionable/n3", "/testRoot/testVersionable/n5"}, new String[]{"/testRoot/testVersionable/n2", "/testRoot/testVersionable/n4"}); showVersionable(testVersionable); checkVersionHistory(testVersionable, 3); // RESTORE ver.3 and n1, n4 will be restored testVersionable.restore(vHistory.getVersionByLabel("ver.3"), true); if (log.isDebugEnabled()) log.debug("===== ver.3 after restore ====="); checkItemsExisted(new String[]{"/testRoot/testVersionable/n1", "/testRoot/testVersionable/n1[2]", "/testRoot/testVersionable/n1[3]", "/testRoot/testVersionable/n1[4]", "/testRoot/testVersionable/n3", "/testRoot/testVersionable/n4"}, new String[]{"/testRoot/testVersionable/n5"}); showVersionable(testVersionable); checkVersionHistory(testVersionable, 3); // testVersionable.checkout(); // // adding nodes: n6 // Node n6 = testVersionable.addNode("n6"); // testVersionable.save(); // Version ver11 = testVersionable.checkin(); // v1.1 // vHistory.addVersionLabel(ver11.getName(), "ver.1.1", false); // // log.info("===== ver.1.1 ====="); // checkItemsExisted(new String[] {n1.getPath(), n2.getPath(), // n6.getPath()}, // new String[] {snsN1_2.getPath(), snsN1_3.getPath(), snsN1_4.getPath(), // n3.getPath(), // n4.getPath(), n5.getPath()}); // checkVersionHistory(testVersionable, 5); // has five versions in history // // testVersionable.checkout(); // // removing nodes: n1, n6 // n1.remove(); // n6.remove(); // testVersionable.save(); // log.info("===== ver.3 before restore ====="); // checkItemsExisted(new String[] {n2.getPath()}, // new String[] {n1.getPath(), snsN1_2.getPath(), snsN1_3.getPath(), // snsN1_4.getPath(), // n2.getPath(), n3.getPath(), n4.getPath(), n5.getPath(), n6.getPath()}); // checkVersionHistory(testVersionable, 5); } private void checkVersionableCopy(Node versionable1, Node versionable2) throws RepositoryException { String v1_VH_UUID = versionable1.getProperty("jcr:versionHistory").getString(); String v1_BV_UUID = versionable1.getProperty("jcr:baseVersion").getString(); try { String v2_VH_UUID = versionable2.getProperty("jcr:versionHistory").getString(); String v2_BV_UUID = versionable2.getProperty("jcr:baseVersion").getString(); assertNotSame("Copied node must has a new version history ", v1_VH_UUID, v2_VH_UUID); assertNotSame("Copied node must has a new base version ", v1_BV_UUID, v2_BV_UUID); // add new version to the source versionable1.checkin(); versionable1.checkout(); v1_BV_UUID = versionable1.getProperty("jcr:baseVersion").getString(); v2_BV_UUID = versionable2.getProperty("jcr:baseVersion").getString(); assertNotSame("Copied node and its source versionable node must has a different version graphs (1) ", v1_BV_UUID, v2_BV_UUID); // add new version to the another versionable versionable2.checkin(); versionable2.checkout(); v2_BV_UUID = versionable2.getProperty("jcr:baseVersion").getString(); assertNotSame("Copied node and its source versionable node must has a different version graphs (2) ", v1_BV_UUID, v2_BV_UUID); } catch (RepositoryException e) { fail("Versionable node was not copied properly. " + e); } } public void testCopyVersionable() throws Exception { // Node source = testRoot.addNode("node1"); session.getWorkspace().copy(testVersionable.getPath(), testRoot.getPath() + "/newVersionable"); checkVersionableCopy(testVersionable, testRoot.getNode("newVersionable")); } public void testCopyVersionableInAnotherWorkspace() throws Exception { Session ws1 = repository.login(credentials, "ws1"); ws1.getWorkspace().copy("ws", testVersionable.getPath(), "/newVersionable"); checkVersionableCopy(testVersionable, ws1.getRootNode().getNode("newVersionable")); } }