/** * This file Copyright (c) 2010-2012 Magnolia International * Ltd. (http://www.magnolia-cms.com). All rights reserved. * * * This file is dual-licensed under both the Magnolia * Network Agreement and the GNU General Public License. * You may elect to use one or the other of these licenses. * * This file is distributed in the hope that it will be * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. * Redistribution, except as permitted by whichever of the GPL * or MNA you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or * modify this file under the terms of the GNU General * Public License, Version 3, as published by the Free Software * Foundation. You should have received a copy of the GNU * General Public License, Version 3 along with this program; * if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * 2. For the Magnolia Network Agreement (MNA), this file * and the accompanying materials are made available under the * terms of the MNA which accompanies this distribution, and * is available at http://www.magnolia-cms.com/mna.html * * Any modifications to this file must keep this entire header * intact. * */ package info.magnolia.cms.core.version; import static org.junit.Assert.*; import static info.magnolia.cms.beans.runtime.FileProperties.PROPERTY_CONTENTTYPE; import static info.magnolia.cms.beans.runtime.FileProperties.PROPERTY_LASTMODIFIED; import static info.magnolia.cms.core.ItemType.CONTENT; import static info.magnolia.cms.core.ItemType.CONTENTNODE; import info.magnolia.cms.core.Content; import info.magnolia.cms.core.HierarchyManager; import info.magnolia.cms.core.NodeData; import info.magnolia.cms.security.MgnlUser; import info.magnolia.cms.util.Rule; import info.magnolia.context.MgnlContext; import info.magnolia.jcr.util.NodeTypes; import info.magnolia.repository.RepositoryConstants; import info.magnolia.test.RepositoryTestCase; import info.magnolia.test.mock.MockContext; import java.io.IOException; import java.util.Calendar; import java.util.Collections; import javax.jcr.RepositoryException; import javax.jcr.version.Version; import org.junit.Before; import org.junit.Test; /** * Tests. */ public class ContentVersionTest extends RepositoryTestCase { private static final String NOT_VERSIONED = "after versioning"; private static final String VERSIONED = "before versioning"; @Override @Before public void setUp() throws Exception { super.setUp(); // context is then cleared automatically on teardown by RepoTestCase(MgnlTestCase) MockContext ctx = (MockContext) MgnlContext.getSystemContext(); ctx.setUser(new MgnlUser("toto","admin",Collections.EMPTY_LIST, Collections.EMPTY_LIST, Collections.EMPTY_MAP, null, null)); } @Test public void testBasics() throws RepositoryException{ final HierarchyManager hm = MgnlContext.getHierarchyManager(RepositoryConstants.WEBSITE); Content page = hm.createContent("/", "page", NodeTypes.Content.NAME); Content parargraph = page.createContent("paragraph", NodeTypes.ContentNode.NAME); Content area = page.createContent("area", NodeTypes.Area.NAME); Content component = page.createContent("component", NodeTypes.Component.NAME); Content subpage = page.createContent("subpage", NodeTypes.Content.NAME); page.setNodeData("nodedata", VERSIONED); parargraph.setNodeData("nodedata", VERSIONED); area.setNodeData("nodedata", VERSIONED); component.setNodeData("nodedata", VERSIONED); subpage.setNodeData("nodedata", VERSIONED); hm.save(); page.addVersion(new Rule(new String[]{NodeTypes.ContentNode.NAME})); subpage.addVersion(new Rule(new String[]{NodeTypes.ContentNode.NAME})); page.setNodeData("nodedata", NOT_VERSIONED); parargraph.setNodeData("nodedata", NOT_VERSIONED); area.setNodeData("nodedata", NOT_VERSIONED); component.setNodeData("nodedata", NOT_VERSIONED); subpage.setNodeData("nodedata", NOT_VERSIONED); page.createContent("new-subpage", NodeTypes.Content.NAME); page.createContent("new-paragraph", NodeTypes.ContentNode.NAME); page.createContent("new-area", NodeTypes.Area.NAME); page.createContent("new-component", NodeTypes.Area.NAME); hm.save(); ContentVersion versionedPage = page.getVersionedContent("1.0"); ContentVersion versionedSubpage = subpage.getVersionedContent("1.0"); // ---------------------------- // Test that content got versioned including paragraphs but without sub pages // ---------------------------- // page and paragraph are versioned together assertEquals(VERSIONED, versionedPage.getNodeData("nodedata").getString()); assertEquals(VERSIONED, versionedPage.getContent("paragraph").getNodeData("nodedata").getString()); assertEquals(VERSIONED, versionedPage.getContent("area").getNodeData("nodedata").getString()); assertEquals(VERSIONED, versionedPage.getContent("component").getNodeData("nodedata").getString()); // navigation to subpage should work, but the subpage should be the current page assertEquals(NOT_VERSIONED, versionedPage.getContent("subpage").getNodeData("nodedata").getString()); // navigation to the parent should work, but the parent should be the current page assertEquals(NOT_VERSIONED, versionedSubpage.getParent().getNodeData("nodedata").getString()); assertEquals(NOT_VERSIONED, versionedSubpage.getParent().getContent("paragraph").getNodeData("nodedata").getString()); assertEquals(NOT_VERSIONED, versionedSubpage.getParent().getContent("area").getNodeData("nodedata").getString()); assertEquals(NOT_VERSIONED, versionedSubpage.getParent().getContent("component").getNodeData("nodedata").getString()); // ---------------------------- // Test that the versioned content returns the same handles as the original content // ---------------------------- // test that the handles are the same as of the current nodes assertEquals(page.getHandle(), versionedPage.getHandle()); assertEquals(page.getContent("paragraph").getHandle(), versionedPage.getContent("paragraph").getHandle()); assertEquals(page.getContent("area").getHandle(), versionedPage.getContent("area").getHandle()); assertEquals(page.getContent("component").getHandle(), versionedPage.getContent("component").getHandle()); assertEquals(page.getNodeData("nodedata").getHandle(), versionedPage.getNodeData("nodedata").getHandle()); assertEquals(page.getContent("paragraph").getNodeData("nodedata").getHandle(), versionedPage.getContent("paragraph").getNodeData("nodedata").getHandle()); assertEquals(page.getContent("area").getNodeData("nodedata").getHandle(), versionedPage.getContent("area").getNodeData("nodedata").getHandle()); assertEquals(page.getContent("component").getNodeData("nodedata").getHandle(), versionedPage.getContent("component").getNodeData("nodedata").getHandle()); assertEquals(page.getContent("subpage").getHandle(), versionedSubpage.getHandle()); assertEquals(page.getHandle(), versionedSubpage.getParent().getHandle()); // ---------------------------- // Test that we get the correct sub content // ---------------------------- // sub pages were not included in the versioning, so they should be transparent assertEquals(2, versionedPage.getChildren(CONTENT).size()); assertTrue(versionedPage.hasContent("new-subpage")); try { versionedPage.getContent("new-subpage"); } catch (Exception e) { fail("new-subpage should be accessable"); } // after versioning we have added a new paragraph, area and component lets test that those are not visible assertEquals(3, versionedPage.getChildren(CONTENTNODE).size()); assertFalse(versionedPage.hasContent("new-paragraph")); assertFalse(versionedPage.hasContent("new-area")); assertFalse(versionedPage.hasContent("new-component")); assertFalse("the new sub pragraph should not be reachable", isContentReachable(versionedPage, "new-paragraph")); assertFalse("the new sub area should not be reachable", isContentReachable(versionedPage, "new-area")); assertFalse("the new sub component should not be reachable", isContentReachable(versionedPage, "new-component")); } private boolean isContentReachable(ContentVersion versionedPage, String content){ try { versionedPage.getContent(content); } catch (Exception e) { return false; } return true; } @Test public void testRetrievingBinariesFromContentVersion() throws RepositoryException, IOException { final HierarchyManager hm = MgnlContext.getHierarchyManager(RepositoryConstants.WEBSITE); // create content with binary Content node = hm.createContent("/", "node", NodeTypes.ContentNode.NAME); final NodeData binaryNodeData = node.setNodeData("binary", getClass().getResourceAsStream("/testresource.txt")); binaryNodeData.setAttribute(PROPERTY_CONTENTTYPE, "text/plain"); binaryNodeData.setAttribute(PROPERTY_LASTMODIFIED, Calendar.getInstance()); hm.save(); // verify that the binary is really there assertNotNull(binaryNodeData.getValue()); // add version node.addVersion(); // get binary from version final ContentVersion versionedContent = node.getVersionedContent("1.0"); final NodeData versionedBinaryNodeData = versionedContent.getNodeData("binary"); // due to http://jira.magnolia-cms.com/browse/MAGNOLIA-3288 the following call to get value returns null. assertNotNull("Expected a non-null binary value to be retrieved from ContentVersion", versionedBinaryNodeData.getValue()); } @Test public void testRestoringBinariesFromContentVersion() throws RepositoryException, IOException { final HierarchyManager hm = MgnlContext.getHierarchyManager(RepositoryConstants.WEBSITE); // create content with binary Content node = hm.createContent("/", "node", NodeTypes.ContentNode.NAME); final NodeData binaryNodeData = node.setNodeData("binary", getClass().getResourceAsStream("/testresource.txt")); binaryNodeData.setAttribute(PROPERTY_CONTENTTYPE, "text/plain"); binaryNodeData.setAttribute(PROPERTY_LASTMODIFIED, Calendar.getInstance()); hm.save(); // verify that the binary is really there assertNotNull(binaryNodeData.getValue()); // add version final Version version = node.addVersion(); // delete binary binaryNodeData.delete(); hm.save(); assertFalse("binary shouldn't exist anymore", node.hasNodeData("binary")); // restore node node.restore(version, true); // get binary from restored node final NodeData restoredBinaryNodeData = node.getNodeData("binary"); assertNotNull("Expected a non-null binary value to be retrieved from the restored version", restoredBinaryNodeData.getValue()); } @Test public void testRetrievingBinariesFromContentVersionsChildNode() throws RepositoryException, IOException { final HierarchyManager hm = MgnlContext.getHierarchyManager(RepositoryConstants.WEBSITE); // create content with binary Content node = hm.createContent("/", "node", NodeTypes.ContentNode.NAME); Content child = node.createContent("child", NodeTypes.ContentNode.NAME); final NodeData binaryNodeData = child.setNodeData("binary", getClass().getResourceAsStream("/testresource.txt")); binaryNodeData.setAttribute(PROPERTY_CONTENTTYPE, "text/plain"); binaryNodeData.setAttribute(PROPERTY_LASTMODIFIED, Calendar.getInstance()); hm.save(); // verify that the binary is really there assertNotNull(binaryNodeData.getValue()); final Rule rule = new Rule(); rule.addAllowType(NodeTypes.ContentNode.NAME); rule.addAllowType(NodeTypes.Resource.NAME); // add version node.addVersion(rule); // get binary from version final ContentVersion versionedContent = node.getVersionedContent("1.0"); final Content versionedChild = versionedContent.getContent("child"); final NodeData versionedBinaryNodeData = versionedChild.getNodeData("binary"); // due to http://jira.magnolia-cms.com/browse/MAGNOLIA-3288 the following call to get value returns null. assertNotNull("Expected a non-null binary value to be retrieved from ContentVersion", versionedBinaryNodeData.getValue()); } }