Author: angela
Date: Tue Feb 11 12:26:46 2014
New Revision: 1567085
URL: http://svn.apache.org/r1567085
Log:
OAK-918 : Copying nodes does not create independant version histories
OAK-919 : Proper handling of locks present on copied nodes
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/HiddenPropertyTest.java
- copied, changed from r1566630,
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/ChildOrderPropertyTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadWriteVersionManager.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionConstants.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/WorkspaceDelegate.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/CopyTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadWriteVersionManager.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadWriteVersionManager.java?rev=1567085&r1=1567084&r2=1567085&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadWriteVersionManager.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/ReadWriteVersionManager.java
Tue Feb 11 12:26:46 2014
@@ -63,6 +63,7 @@ import static org.apache.jackrabbit.JcrC
import static org.apache.jackrabbit.JcrConstants.NT_VERSIONHISTORY;
import static org.apache.jackrabbit.JcrConstants.NT_VERSIONLABELS;
import static org.apache.jackrabbit.oak.plugins.version.Utils.uuidFromNode;
+import static
org.apache.jackrabbit.oak.plugins.version.VersionConstants.JCR_COPIED_FROM;
import static
org.apache.jackrabbit.oak.plugins.version.VersionConstants.REP_VERSIONSTORAGE;
import static
org.apache.jackrabbit.oak.plugins.version.VersionConstants.VERSION_STORE_PATH;
@@ -133,6 +134,11 @@ class ReadWriteVersionManager extends Re
node.setProperty(JCR_PRIMARYTYPE, nt, Type.NAME);
}
}
+ PropertyState copiedFrom =
versionable.getProperty(VersionConstants.HIDDEN_COPY_SOURCE);
+ if (copiedFrom != null) {
+ node.setProperty(JCR_COPIED_FROM,
copiedFrom.getValue(Type.STRING), Type.WEAKREFERENCE);
+ }
+
// use jcr:rootVersion node to detect if we need to initialize the
// version history
if (!node.hasChildNode(JCR_ROOTVERSION)) {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionConstants.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionConstants.java?rev=1567085&r1=1567084&r2=1567085&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionConstants.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionConstants.java
Tue Feb 11 12:26:46 2014
@@ -160,4 +160,10 @@ public interface VersionConstants extend
VersionConstants.REP_ACTIVITIES,
VersionConstants.REP_CONFIGURATIONS
);
+
+ /**
+ * Name of the hidden property that indicates the ID of the base version
+ * of a versionable node that has been copied.
+ */
+ String HIDDEN_COPY_SOURCE = ":copySource";
}
\ No newline at end of file
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java?rev=1567085&r1=1567084&r2=1567085&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/util/TreeUtil.java
Tue Feb 11 12:26:46 2014
@@ -38,6 +38,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
import org.apache.jackrabbit.util.ISO8601;
+import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Lists.newArrayList;
import static java.util.Collections.emptyList;
import static org.apache.jackrabbit.JcrConstants.JCR_AUTOCREATED;
@@ -65,6 +66,7 @@ import static org.apache.jackrabbit.oak.
import static
org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.REP_NAMED_CHILD_NODE_DEFINITIONS;
import static
org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.REP_NAMED_PROPERTY_DEFINITIONS;
import static
org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.REP_RESIDUAL_CHILD_NODE_DEFINITIONS;
+import static
org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.REP_SUPERTYPES;
/**
* Utility providing common operations for the {@code Tree} that are not
provided
@@ -391,4 +393,29 @@ public final class TreeUtil {
}
return null;
}
+
+ public static boolean isNodeType(Tree tree, String typeName, Tree
typeRoot) {
+ String primaryName = TreeUtil.getName(tree, JCR_PRIMARYTYPE);
+ if (typeName.equals(primaryName)) {
+ return true;
+ } else if (primaryName != null) {
+ Tree type = typeRoot.getChild(primaryName);
+ if (contains(getNames(type, REP_SUPERTYPES), typeName)) {
+ return true;
+ }
+ }
+
+ for (String mixinName : getNames(tree, JCR_MIXINTYPES)) {
+ if (typeName.equals(mixinName)) {
+ return true;
+ } else {
+ Tree type = typeRoot.getChild(mixinName);
+ if (contains(getNames(type, REP_SUPERTYPES), typeName)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
}
\ No newline at end of file
Copied:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/HiddenPropertyTest.java
(from r1566630,
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/ChildOrderPropertyTest.java)
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/HiddenPropertyTest.java?p2=jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/HiddenPropertyTest.java&p1=jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/ChildOrderPropertyTest.java&r1=1566630&r2=1567085&rev=1567085&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/ChildOrderPropertyTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/HiddenPropertyTest.java
Tue Feb 11 12:26:46 2014
@@ -16,46 +16,55 @@
*/
package org.apache.jackrabbit.oak.security.authorization.evaluation;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
import java.util.Set;
import com.google.common.collect.Sets;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
-import org.apache.jackrabbit.oak.plugins.tree.TreeConstants;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.version.VersionConstants;
+import org.apache.jackrabbit.oak.spi.state.MoveDetector;
import org.junit.Before;
import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
/**
* Test for the hidden {@link
org.apache.jackrabbit.oak.plugins.tree.TreeConstants#OAK_CHILD_ORDER} property
*/
-public class ChildOrderPropertyTest extends AbstractOakCoreTest {
+public class HiddenPropertyTest extends AbstractOakCoreTest {
+ private String[] hiddenProps = new String[] {":hiddenProp",
MoveDetector.SOURCE_PATH, VersionConstants.HIDDEN_COPY_SOURCE};
@Override
@Before
public void before() throws Exception {
super.before();
Tree a = root.getTree("/a");
- a.setOrderableChildren(true);
+ a.setProperty(":hiddenProp", "val", Type.STRING);
+ a.setProperty(MoveDetector.SOURCE_PATH, "/some/path", Type.PATH);
+ a.setProperty(VersionConstants.HIDDEN_COPY_SOURCE, "abc", Type.STRING);
root.commit();
}
@Test
public void testHasProperty() {
Tree a = root.getTree("/a");
- assertFalse(a.hasProperty(TreeConstants.OAK_CHILD_ORDER));
+ for (String propName : hiddenProps) {
+ assertFalse(a.hasProperty(propName));
+ }
}
@Test
public void testGetProperty() {
Tree a = root.getTree("/a");
- assertNull(a.getProperty(TreeConstants.OAK_CHILD_ORDER));
+ for (String propName : hiddenProps) {
+ assertNull(a.getProperty(propName));
+ }
}
@Test
@@ -78,7 +87,9 @@ public class ChildOrderPropertyTest exte
@Test
public void testGetPropertyStatus() {
Tree a = root.getTree("/a");
- assertNull(a.getPropertyStatus(TreeConstants.OAK_CHILD_ORDER));
+ for (String propName : hiddenProps) {
+ assertNull(a.getPropertyStatus(propName));
+ }
}
}
\ No newline at end of file
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java?rev=1567085&r1=1567084&r2=1567085&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
Tue Feb 11 12:26:46 2014
@@ -562,30 +562,7 @@ public class NodeDelegate extends ItemDe
}
private boolean isNodeType(Tree tree, String typeName, Root root) {
- Tree typeRoot = root.getTree(NODE_TYPES_PATH);
-
- String primaryName = TreeUtil.getName(tree, JCR_PRIMARYTYPE);
- if (typeName.equals(primaryName)) {
- return true;
- } else if (primaryName != null) {
- Tree type = typeRoot.getChild(primaryName);
- if (contains(getNames(type, REP_SUPERTYPES), typeName)) {
- return true;
- }
- }
-
- for (String mixinName : getNames(tree, JCR_MIXINTYPES)) {
- if (typeName.equals(mixinName)) {
- return true;
- } else {
- Tree type = typeRoot.getChild(mixinName);
- if (contains(getNames(type, REP_SUPERTYPES), typeName)) {
- return true;
- }
- }
- }
-
- return false;
+ return TreeUtil.isNodeType(tree, typeName,
root.getTree(NODE_TYPES_PATH));
}
private Tree findMatchingPropertyDefinition(
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/WorkspaceDelegate.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/WorkspaceDelegate.java?rev=1567085&r1=1567084&r2=1567085&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/WorkspaceDelegate.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/WorkspaceDelegate.java
Tue Feb 11 12:26:46 2014
@@ -26,6 +26,7 @@ import javax.jcr.RepositoryException;
import javax.jcr.nodetype.ConstraintViolationException;
import com.google.common.collect.Maps;
+import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Root;
@@ -34,13 +35,16 @@ import org.apache.jackrabbit.oak.api.Typ
import org.apache.jackrabbit.oak.jcr.security.AccessManager;
import org.apache.jackrabbit.oak.jcr.session.SessionContext;
import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
+import org.apache.jackrabbit.oak.plugins.lock.LockConstants;
import org.apache.jackrabbit.oak.plugins.memory.GenericPropertyState;
import org.apache.jackrabbit.oak.plugins.memory.MultiGenericPropertyState;
+import org.apache.jackrabbit.oak.plugins.version.VersionConstants;
import
org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
import org.apache.jackrabbit.oak.util.TreeUtil;
import org.apache.jackrabbit.util.Text;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
import static
org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.NODE_TYPES_PATH;
@@ -138,17 +142,27 @@ public class WorkspaceDelegate {
Tree dest = TreeUtil.addChild(destParent, destName, primaryType,
typeRoot, userId);
for (PropertyState property : source.getProperties()) {
String propName = property.getName();
- if (JCR_UUID.equals(propName)) {
+ if (JCR_MIXINTYPES.equals(propName)) {
+ for (String mixin : property.getValue(Type.NAMES)) {
+ TreeUtil.addMixin(dest, mixin, typeRoot, userId);
+ }
+ } else if (JCR_UUID.equals(propName)) {
String sourceId = property.getValue(Type.STRING);
String newId = IdentifierManager.generateUUID();
dest.setProperty(JCR_UUID, newId, Type.STRING);
if (!translated.containsKey(sourceId)) {
translated.put(sourceId, newId);
}
- } else if (!JCR_PRIMARYTYPE.equals(propName)) {
+ } else if (!JCR_PRIMARYTYPE.equals(propName)
+ &&
!VersionConstants.VERSION_PROPERTY_NAMES.contains(propName)
+ &&
!LockConstants.LOCK_PROPERTY_NAMES.contains(propName)) {
dest.setProperty(property);
}
}
+ if (TreeUtil.isNodeType(source, JcrConstants.MIX_VERSIONABLE,
typeRoot)) {
+ String sourceBaseVersionId =
source.getProperty(JcrConstants.JCR_BASEVERSION).getValue(Type.STRING);
+ dest.setProperty(VersionConstants.HIDDEN_COPY_SOURCE,
sourceBaseVersionId, Type.PATH);
+ }
for (Tree child : source.getChildren()) {
copy(child, dest, child.getName());
}
@@ -164,19 +178,22 @@ public class WorkspaceDelegate {
private void updateReferences(Tree src, Tree dest)
throws RepositoryException {
for (PropertyState prop : src.getProperties()) {
- Type<?> type = prop.getType();
- if (type == Type.REFERENCE
- || type == Type.REFERENCES
- || type == Type.WEAKREFERENCE
- || type == Type.WEAKREFERENCES) {
+ if (isReferenceType(prop) &&
!VersionConstants.VERSION_PROPERTY_NAMES.contains(prop.getName()))
updateProperty(prop, dest);
- }
}
for (Tree child : src.getChildren()) {
updateReferences(child, dest.getChild(child.getName()));
}
}
+ private boolean isReferenceType(PropertyState property) {
+ Type<?> type = property.getType();
+ return (type == Type.REFERENCE
+ || type == Type.REFERENCES
+ || type == Type.WEAKREFERENCE
+ || type == Type.WEAKREFERENCES);
+ }
+
private void updateProperty(PropertyState prop, Tree dest) {
boolean multi = prop.isArray();
boolean weak = prop.getType() == Type.WEAKREFERENCE
Modified:
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/CopyTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/CopyTest.java?rev=1567085&r1=1567084&r2=1567085&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/CopyTest.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/CopyTest.java
Tue Feb 11 12:26:46 2014
@@ -17,20 +17,25 @@
package org.apache.jackrabbit.oak.jcr;
import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
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;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.plugins.version.VersionConstants;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
public class CopyTest extends AbstractRepositoryTest {
@@ -105,7 +110,6 @@ public class CopyTest extends AbstractRe
assertFalse(childCopy.getUUID().equals(testNode.getNode("source/node/child").getUUID()));
}
- @Ignore("OAK-918") // FIXME
@Test
public void testCopyVersionableNode() throws Exception {
Session session = getAdminSession();
@@ -113,8 +117,6 @@ public class CopyTest extends AbstractRe
toCopy.addMixin(JcrConstants.MIX_VERSIONABLE);
session.save();
- Version baseV = toCopy.getBaseVersion();
-
session.getWorkspace().copy(TEST_PATH + "/source/node", TEST_PATH +
"/target/copied");
assertTrue(testNode.hasNode("source/node"));
@@ -123,15 +125,70 @@ public class CopyTest extends AbstractRe
Node copy = testNode.getNode("target/copied");
assertTrue(copy.isNodeType(JcrConstants.MIX_VERSIONABLE));
- VersionHistory copiedVh = copy.getVersionHistory();
assertFalse(copy.getVersionHistory().isSame(toCopy.getVersionHistory()));
+ }
+
+ @Test
+ public void testCopyVersionableNodeClearsVersions() throws Exception {
+ Session session = getAdminSession();
+ Node toCopy = session.getNode(TEST_PATH + "/source/node");
+ toCopy.addMixin(JcrConstants.MIX_VERSIONABLE);
+ session.save();
+
+ Version v1 = toCopy.checkin();
+ toCopy.checkout();
+ Version v2 = toCopy.checkin();
+ toCopy.checkout();
+
+ session.getWorkspace().copy(TEST_PATH + "/source/node", TEST_PATH +
"/target/copied");
+
+ Node copy = testNode.getNode("target/copied");
+
+ VersionHistory vh = copy.getVersionHistory();
+ Version rootV = vh.getRootVersion();
+
+ assertEquals(0, rootV.getSuccessors().length);
+ VersionIterator vItr = vh.getAllVersions();
+ while (vItr.hasNext()) {
+ if (!rootV.isSame(vItr.nextVersion())) {
+ fail("Unexpected version in version history of copied node.");
+ }
+ }
+ try {
+ vh.getVersion(v1.getName());
+ fail("Unexpected version in version history of copied node.");
+ } catch (VersionException e) {
+ // success
+ }
+ try {
+ vh.getVersion(v2.getName());
+ fail("Unexpected version in version history of copied node.");
+ } catch (VersionException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testCopyVersionableNodeCreatesJcrCopiedFrom() throws Exception
{
+ Session session = getAdminSession();
+ Node toCopy = session.getNode(TEST_PATH + "/source/node");
+ toCopy.addMixin(JcrConstants.MIX_VERSIONABLE);
+ session.save();
+
+ Version baseV = toCopy.getBaseVersion();
+
+ session.getWorkspace().copy(TEST_PATH + "/source/node", TEST_PATH +
"/target/copied");
+
+ Node copy = testNode.getNode("target/copied");
+ VersionHistory copiedVh = copy.getVersionHistory();
assertTrue(copiedVh.hasProperty(VersionConstants.JCR_COPIED_FROM));
- Node copiedFrom =
copiedVh.getProperty(VersionConstants.JCR_COPIED_FROM).getNode();
+ Property prop = copiedVh.getProperty(VersionConstants.JCR_COPIED_FROM);
+ assertEquals(PropertyType.WEAKREFERENCE, prop.getType());
+ Node copiedFrom = prop.getNode();
assertTrue(baseV.isSame(copiedFrom));
}
- @Ignore("OAK-919") // FIXME
@Test
public void testCopyLockedNode() throws Exception {
Session session = getAdminSession();