You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2015/10/23 11:37:39 UTC
svn commit: r1710159 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/plugins/version/
test/java/org/apache/jackrabbit/oak/
test/java/org/apache/jackrabbit/oak/plugins/version/
test/java/org/apache/jackrabbit/oak/security/au...
Author: angela
Date: Fri Oct 23 09:37:38 2015
New Revision: 1710159
URL: http://svn.apache.org/viewvc?rev=1710159&view=rev
Log:
OAK-3543 : Add ReadOnlyVersionManager.getVersionable
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/version/
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/version/ReadOnlyVersionManagerTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadOnlyVersionManager.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/package-info.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/VersionStorageTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadOnlyVersionManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadOnlyVersionManager.java?rev=1710159&r1=1710158&r2=1710159&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadOnlyVersionManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadOnlyVersionManager.java Fri Oct 23 09:37:38 2015
@@ -23,14 +23,18 @@ import javax.annotation.Nonnull;
import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
+import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
import org.apache.jackrabbit.oak.util.TreeUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -40,6 +44,8 @@ import static com.google.common.base.Pre
*/
public abstract class ReadOnlyVersionManager {
+ private static final Logger log = LoggerFactory.getLogger(ReadOnlyVersionManager.class);
+
/**
* @return the read-only {@link Tree} for the jcr:versionStorage node. The
* returned {@code Tree} instance must be up-to-date with the
@@ -49,7 +55,7 @@ public abstract class ReadOnlyVersionMan
protected abstract Tree getVersionStorage();
/**
- /**
+ /**
* @return the {@code Root} of the workspace.
*/
@Nonnull
@@ -61,6 +67,40 @@ public abstract class ReadOnlyVersionMan
@Nonnull
protected abstract ReadOnlyNodeTypeManager getNodeTypeManager();
+ //--------------------------------------------------------------------------
+
+ /**
+ * Return a new instance of {@code ReadOnlyVersionManager} that reads version
+ * information from the tree at {@link VersionConstants#VERSION_STORE_PATH}.
+ *
+ * @param root The root to read version information from.
+ * @param namePathMapper The {@code NamePathMapper} to use.
+ * @return a new instance of {@code ReadOnlyVersionManager}.
+ */
+ @Nonnull
+ public static ReadOnlyVersionManager getInstance(final Root root,
+ final NamePathMapper namePathMapper) {
+ return new ReadOnlyVersionManager() {
+ @Nonnull
+ @Override
+ protected Tree getVersionStorage() {
+ return root.getTree(VersionConstants.VERSION_STORE_PATH);
+ }
+
+ @Nonnull
+ @Override
+ protected Root getWorkspaceRoot() {
+ return root;
+ }
+
+ @Nonnull
+ @Override
+ protected ReadOnlyNodeTypeManager getNodeTypeManager() {
+ return ReadOnlyNodeTypeManager.getInstance(root, namePathMapper);
+ }
+ };
+ }
+
/**
* Returns {@code true} if the tree is checked out; otherwise
* {@code false}. The root node is always considered checked out.
@@ -166,6 +206,80 @@ public abstract class ReadOnlyVersionMan
return getIdentifierManager().getTree(p.getValue(Type.STRING));
}
+ /**
+ * Returns {@code true} if the specified tree has {@link VersionConstants#REP_VERSIONSTORAGE}
+ * defines as primary node type i.e. is part of the intermediate version storage
+ * structure that contains the version histories and the versions.
+ *
+ * @param tree The tree to be tested.
+ * @return {@code true} if the target node has {@link VersionConstants#REP_VERSIONSTORAGE}
+ * defines as primary node type; {@code false} otherwise.
+ */
+ public static boolean isVersionStoreTree(@Nonnull Tree tree) {
+ return VersionConstants.REP_VERSIONSTORAGE.equals(TreeUtil.getPrimaryTypeName(tree));
+ }
+
+ /**
+ * Tries to retrieve the tree corresponding to specified {@code versionTree}
+ * outside of the version storage based on versionable path information
+ * stored with the version history. The following cases are distinguished:
+ *
+ * <ul>
+ * <li>Version History: If the given tree is a version history the
+ * associated versionable tree in the specified workspace is being returned
+ * based on the information stored in the versionable path property. If
+ * no versionable path property is present {@code null} is returned.</li>
+ * <li>Version: Same as for version history.</li>
+ * <li>Version Labels: Same as for version history.</li>
+ * <li>Frozen Node: If the given tree forms part of a frozen node the
+ * path of the target node is computed from the versionable path and
+ * the relative path of the frozen node.</li>
+ * <li>Other Nodes: If the specified tree is not part of the tree structure
+ * defined by a version history, {@code null} will be returned.</li>
+ * </ul>
+ *
+ * Please note that this method will not verify if the tree at the versionable
+ * path or the computed subtree actually exists. This must be asserted by
+ * the caller before operating on the tree.
+ *
+ * @param versionTree The tree from within the version storage for which
+ * that versionable correspondent should be retrieved.
+ * @param workspaceName The name of the workspace for which the target should be retrieved.
+ * @return A existing or non-existing tree pointing to the location of the
+ * correspondent tree outside of the version storage or {@code null} if the
+ * versionable path property for the specified workspace is missing or if
+ * the given tree is not located within the tree structure defined by a version history.
+ *
+ * @see {@link VersionablePathHook}
+ * @see {@link VersionConstants#MIX_REP_VERSIONABLE_PATHS}
+ */
+ @CheckForNull
+ public Tree getVersionable(@Nonnull Tree versionTree, @Nonnull String workspaceName) {
+ Root root = getWorkspaceRoot();
+ String relPath = "";
+ Tree t = versionTree;
+ while (t.exists() && !isVersionStoreTree(t) && !t.isRoot()) {
+ String ntName = TreeUtil.getPrimaryTypeName(t);
+ if (VersionConstants.NT_FROZENNODE.equals(ntName)) {
+ relPath = PathUtils.relativize(t.getPath(), versionTree.getPath());
+ } else if (JcrConstants.NT_VERSIONHISTORY.equals(ntName)) {
+ PropertyState prop = t.getProperty(workspaceName);
+ if (prop != null) {
+ return root.getTree(PathUtils.concat(prop.getValue(Type.PATH), relPath));
+ } else {
+ // version history is missing the versionable path property for the given workspace name
+ log.warn("Missing versionable path property for {} at {}", workspaceName, t.getPath());
+ break;
+ }
+ }
+ t = t.getParent();
+ }
+
+ // intermediate node in the version storage that matches none of the special
+ // conditions checked above and cannot be resolve to a versionable tree.
+ return null;
+ }
+
//----------------------------< internal >----------------------------------
/**
* @return an identifier manager that is able to resolve identifiers of
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/package-info.java?rev=1710159&r1=1710158&r2=1710159&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/package-info.java Fri Oct 23 09:37:38 2015
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.0")
+@Version("1.1.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.plugins.version;
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java?rev=1710159&r1=1710158&r2=1710159&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java Fri Oct 23 09:37:38 2015
@@ -52,7 +52,9 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
+import org.apache.jackrabbit.oak.plugins.version.VersionEditorProvider;
import org.apache.jackrabbit.oak.security.SecurityProviderImpl;
+import org.apache.jackrabbit.oak.spi.commit.EditorHook;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import org.apache.jackrabbit.oak.spi.security.authentication.ConfigurationUtil;
@@ -82,6 +84,7 @@ public abstract class AbstractSecurityTe
public void before() throws Exception {
Oak oak = new Oak()
.with(new InitialContent())
+ .with(new EditorHook(new VersionEditorProvider()))
.with(JcrConflictHandler.createJcrConflictHandler())
.with(new NamespaceEditorProvider())
.with(new ReferenceEditorProvider())
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/version/ReadOnlyVersionManagerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/version/ReadOnlyVersionManagerTest.java?rev=1710159&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/version/ReadOnlyVersionManagerTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/version/ReadOnlyVersionManagerTest.java Fri Oct 23 09:37:38 2015
@@ -0,0 +1,169 @@
+/*
+ * 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.oak.plugins.version;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+import org.apache.jackrabbit.oak.util.NodeUtil;
+import org.apache.jackrabbit.oak.util.TreeUtil;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.JcrConstants.JCR_ISCHECKEDOUT;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class ReadOnlyVersionManagerTest extends AbstractSecurityTest {
+
+ private Tree versionable;
+ private String workspaceName;
+
+ private ReadOnlyVersionManager versionManager;
+
+ @Override
+ @Before
+ public void before() throws Exception {
+ super.before();
+
+ NodeUtil node = new NodeUtil(root.getTree("/"));
+ NodeUtil a = node.addChild("a", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ a.addChild("b", NodeTypeConstants.NT_OAK_UNSTRUCTURED).addChild("c", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+
+
+ TreeUtil.addMixin(a.getTree(), JcrConstants.MIX_VERSIONABLE, root.getTree(NodeTypeConstants.NODE_TYPES_PATH), null);
+ root.commit();
+
+ versionable = root.getTree("/a");
+
+ // force the creation of a version that has a frozen node
+ versionable.setProperty(JCR_ISCHECKEDOUT, Boolean.FALSE, Type.BOOLEAN);
+ root.commit();
+ versionable.setProperty(JCR_ISCHECKEDOUT, Boolean.TRUE, Type.BOOLEAN);
+ root.commit();
+
+ versionManager = ReadOnlyVersionManager.getInstance(root, NamePathMapper.DEFAULT);
+ workspaceName = root.getContentSession().getWorkspaceName();
+ }
+
+ @Override
+ @After
+ public void after() throws Exception {
+ try {
+ root.refresh();
+
+ Tree a = root.getTree("/a");
+ if (a.exists()) {
+ a.remove();
+ root.commit();
+ }
+ } finally {
+ super.after();
+ }
+ }
+
+ @Test
+ public void testIsVersionStoreTree() throws Exception {
+ assertFalse(ReadOnlyVersionManager.isVersionStoreTree(root.getTree("/")));
+ assertFalse(ReadOnlyVersionManager.isVersionStoreTree(root.getTree("/a")));
+ assertFalse(ReadOnlyVersionManager.isVersionStoreTree(root.getTree("/a/b/c")));
+
+ assertTrue(ReadOnlyVersionManager.isVersionStoreTree(root.getTree(VersionConstants.VERSION_STORE_PATH)));
+
+ Tree versionHistory = versionManager.getVersionHistory(root.getTree("/a"));
+ assertNotNull(versionHistory);
+ assertFalse(ReadOnlyVersionManager.isVersionStoreTree(versionHistory));
+ assertTrue(ReadOnlyVersionManager.isVersionStoreTree(versionHistory.getParent()));
+ }
+
+ @Test
+ public void testGetVersionable() throws Exception {
+ Tree versionHistory = checkNotNull(versionManager.getVersionHistory(root.getTree("/a")));
+ assertVersionable("/a", versionHistory);
+
+ Tree rootVersion = versionHistory.getChild(JcrConstants.JCR_ROOTVERSION);
+ assertVersionable("/a", rootVersion);
+
+ Tree baseVersion = checkNotNull(versionManager.getBaseVersion(versionable));
+ assertVersionable("/a", baseVersion);
+
+ Tree frozen = baseVersion.getChild(VersionConstants.JCR_FROZENNODE);
+ assertVersionable("/a", frozen);
+
+ Tree frozenB = frozen.getChild("b");
+ assertVersionable("/a/b", frozenB);
+
+ Tree frozenC = frozenB.getChild("c");
+ assertVersionable("/a/b/c", frozenC);
+ }
+
+
+ private void assertVersionable(@Nonnull String expectedPath, @Nonnull Tree versionTree) {
+ String p = versionTree.getPath();
+ assertTrue(p, versionTree.exists());
+
+ Tree versionable = versionManager.getVersionable(versionTree, workspaceName);
+ assertNotNull(p, versionable);
+ assertEquals(p, expectedPath, versionable.getPath());
+ }
+
+ @Test
+ public void testGetVersionableForNonVersionTree() throws Exception {
+ assertNull(versionManager.getVersionable(versionManager.getVersionStorage(), workspaceName));
+ assertNull(versionManager.getVersionable(versionable, workspaceName));
+ assertNull(versionManager.getVersionable(root.getTree("/"), workspaceName));
+ }
+
+ @Test
+ public void testGetVersionableMissingPathProperty() throws Exception {
+ Tree versionHistory = checkNotNull(versionManager.getVersionHistory(root.getTree("/a")));
+ versionHistory.removeProperty(workspaceName);
+
+ assertNull(versionManager.getVersionable(versionHistory, workspaceName));
+ assertNull(versionManager.getVersionable(versionHistory.getChild(JcrConstants.JCR_ROOTVERSION), workspaceName));
+ }
+
+ @Test
+ public void testGetVersionableNonExistingWorkspace() throws Exception {
+ Tree versionHistory = checkNotNull(versionManager.getVersionHistory(root.getTree("/a")));
+
+ assertNull(versionManager.getVersionable(versionHistory, "nonExistingWorkspaceName"));
+ assertNull(versionManager.getVersionable(versionHistory.getChild(JcrConstants.JCR_ROOTVERSION), "nonExistingWorkspaceName"));
+ }
+
+ @Test
+ public void testGetVersionableTargetRemoved() throws Exception {
+ Tree baseVersion = checkNotNull(versionManager.getBaseVersion(versionable));
+
+ versionable.remove();
+ root.commit();
+
+ Tree t = versionManager.getVersionable(baseVersion, workspaceName);
+ assertNotNull(t);
+ assertFalse(t.exists());
+ }
+}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/VersionStorageTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/VersionStorageTest.java?rev=1710159&r1=1710158&r2=1710159&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/VersionStorageTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/VersionStorageTest.java Fri Oct 23 09:37:38 2015
@@ -100,11 +100,6 @@ public class VersionStorageTest extends
root.commit();
}
- @Override
- protected Oak withEditors(Oak oak) {
- return oak.with(new VersionEditorProvider());
- }
-
@Test
public void testGetVersionStorage() throws Exception {
Tree vs = getTestRoot().getTree(VersionConstants.VERSION_STORE_PATH);