jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r1558818 - in /jackrabbit/oak/trunk/oak-jcr: ./ src/main/java/org/apache/jackrabbit/oak/jcr/delegate/ src/main/java/org/apache/jackrabbit/oak/jcr/session/ src/test/java/org/apache/jackrabbit/oak/jcr/
Date Thu, 16 Jan 2014 14:42:35 GMT
Author: angela
Date: Thu Jan 16 14:42:34 2014
New Revision: 1558818

URL: http://svn.apache.org/r1558818
Log:
OAK-770 : NodeImpl should implement JackrabbitNode (wip)

Modified:
    jackrabbit/oak/trunk/oak-jcr/pom.xml
    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/session/NodeImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/JackrabbitNodeTest.java

Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1558818&r1=1558817&r2=1558818&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-jcr/pom.xml Thu Jan 16 14:42:34 2014
@@ -116,9 +116,6 @@
       org.apache.jackrabbit.oak.jcr.security.authorization.CopyTest#testCopyInvisibleProperty
       <!-- OAK-920 -->
       org.apache.jackrabbit.oak.jcr.security.authorization.CopyTest#testCopyInvisibleAcContent
      <!-- OAK-920 -->
 
-      <!-- JackrabbitNode -->
-      org.apache.jackrabbit.oak.jcr.JackrabbitNodeTest#testSetMixins                    
            <!-- OAK-770 -->
-
       <!-- Query -->
       org.apache.jackrabbit.test.api.query.ElementTest#testElementTestNameTestSomeNTWithSNS
         <!-- OAK-203 -->
       org.apache.jackrabbit.test.api.query.SaveTest#testItemExistsException             
            <!-- OAK-203 -->

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=1558818&r1=1558817&r2=1558818&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
Thu Jan 16 14:42:34 2014
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.oak.jcr.delegate;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
@@ -53,7 +55,6 @@ import static com.google.common.collect.
 import static com.google.common.collect.Lists.newArrayList;
 import static com.google.common.collect.Sets.newHashSet;
 import static com.google.common.collect.Sets.newLinkedHashSet;
-import static java.util.Collections.singletonList;
 import static org.apache.jackrabbit.JcrConstants.JCR_ISMIXIN;
 import static org.apache.jackrabbit.JcrConstants.JCR_LOCKISDEEP;
 import static org.apache.jackrabbit.JcrConstants.JCR_LOCKOWNER;
@@ -117,7 +118,7 @@ public class NodeDelegate extends ItemDe
     @Override
     @CheckForNull
     public NodeDelegate getParent() {
-        return tree.isRoot() || !tree.getParent().exists() 
+        return tree.isRoot() || !tree.getParent().exists()
             ? null
             : new NodeDelegate(sessionDelegate, tree.getParent());
     }
@@ -307,7 +308,7 @@ public class NodeDelegate extends ItemDe
      * the value is higher than max). If the implementation does not know the
      * exact value, and the child node count is higher than max, it may return
      * Long.MAX_VALUE. The cost of the operation is at most O(max).
-     * 
+     *
      * @param max the maximum value
      * @return number of child nodes of the node
      */
@@ -385,68 +386,99 @@ public class NodeDelegate extends ItemDe
     }
 
     public void removeMixin(String typeName) throws RepositoryException {
-        boolean wasLockable = isNodeType(MIX_LOCKABLE);
-
         Tree tree = getTree();
         Set<String> mixins = newLinkedHashSet(getNames(tree, JCR_MIXINTYPES));
         if (!mixins.remove(typeName)) {
-            throw new NoSuchNodeTypeException(
-                    "Mixin " + typeName +" not contained in " + getPath());
+            throw new NoSuchNodeTypeException("Mixin " + typeName +" not contained in " +
getPath());
         }
-        tree.setProperty(JCR_MIXINTYPES, mixins, NAMES);
-
-        boolean isLockable = isNodeType(MIX_LOCKABLE);
-        if (wasLockable && !isLockable && holdsLock(false)) {
-            // TODO: This should probably be done in a commit hook
-            unlock();
-            sessionDelegate.refresh(true);
-        }
-
-        // We need to remove all protected properties and child nodes
-        // associated with the removed mixin type, as there's no way for
-        // the client to do that. Other items defined in this mixin type
-        // might also need to be removed, but it's probably best to let
-        // the client take care of that before save(), as it's hard to tell
-        // whether removing such items really is the right thing to do.
-
-        Tree typeRoot = sessionDelegate.getRoot().getTree(NODE_TYPES_PATH);
-        List<Tree> removed = singletonList(typeRoot.getChild(typeName));
-        List<Tree> remaining = getNodeTypes(tree, typeRoot);
+        updateMixins(mixins, Collections.singleton(typeName));
+    }
 
-        for (PropertyState property : tree.getProperties()) {
-            String name = property.getName();
-            Type<?> type = property.getType();
-
-            Tree oldDefinition = findMatchingPropertyDefinition(
-                    removed, name, type, true);
-            if (oldDefinition != null) {
-                Tree newDefinition = findMatchingPropertyDefinition(
-                        remaining, name, type, true);
-                if (newDefinition == null
-                        || (getBoolean(oldDefinition, JCR_PROTECTED)
-                                && !getBoolean(newDefinition, JCR_PROTECTED))) {
-                    tree.removeProperty(name);
+    public void setMixins(Set<String> mixinNames) throws RepositoryException {
+        Set<String> existingMixins = newLinkedHashSet(getNames(tree, JCR_MIXINTYPES));
+        if (existingMixins.isEmpty()) {
+            updateMixins(mixinNames, Collections.EMPTY_SET);
+        } else {
+            Set<String> toRemove = newLinkedHashSet();
+            for (String name : existingMixins) {
+                if (!mixinNames.remove(name)) {
+                    toRemove.add(name);
                 }
             }
+            updateMixins(mixinNames, toRemove);
         }
+    }
 
-        for (Tree child : tree.getChildren()) {
-            String name = child.getName();
-            Set<String> typeNames = newLinkedHashSet();
-            for (Tree type : getNodeTypes(child, typeRoot)) {
-                typeNames.add(TreeUtil.getName(type, JCR_NODETYPENAME));
-                addAll(typeNames, getNames(type, REP_SUPERTYPES));
+
+    public void updateMixins(Set<String> addMixinNames, Set<String> removedOakMixinNames)
throws RepositoryException {
+        // 1. set all new mixin types including validation
+        for (String oakMixinName : addMixinNames) {
+            addMixin(oakMixinName);
+        }
+
+        if (!removedOakMixinNames.isEmpty()) {
+            // 2. retrieve the updated set of mixin types, remove the mixins that should
no longer be present
+            Set<String> mixinNames = newLinkedHashSet(getNames(getTree(), JCR_MIXINTYPES));
+            if (mixinNames.removeAll(removedOakMixinNames)) {
+                // FIXME: add mixins to add again as the removal may change the effect of
type inheritance as evaluated during #addMixin
+                mixinNames.addAll(addMixinNames);
+                tree.setProperty(JCR_MIXINTYPES, mixinNames, NAMES);
+            }
+
+            // 3. deal with locked nodes
+            boolean wasLockable = isNodeType(MIX_LOCKABLE);
+            boolean isLockable = isNodeType(MIX_LOCKABLE);
+            if (wasLockable && !isLockable && holdsLock(false)) {
+                // TODO: This should probably be done in a commit hook
+                unlock();
+                sessionDelegate.refresh(true);
+            }
+
+            // 4. clean up set of properties and child nodes such that all child items
+            // have a valid item definition according to the effective node type present
+            // after having updated the mixin property. this includes removing all
+            // protected properties and child nodes associated with the removed mixin
+            // type(s), as there's no way for the client to do that. Other items
+            // defined in this mixin type might also need to be removed if there
+            // is no longer a matching item definition available.
+            Tree typeRoot = sessionDelegate.getRoot().getTree(NODE_TYPES_PATH);
+            List<Tree> removed = new ArrayList<Tree>();
+            for (String name : removedOakMixinNames) {
+                removed.add(typeRoot.getChild(name));
+            }
+            List<Tree> remaining = getNodeTypes(tree, typeRoot);
+
+            for (PropertyState property : tree.getProperties()) {
+                String name = property.getName();
+                Type<?> type = property.getType();
+
+                Tree oldDefinition = findMatchingPropertyDefinition(removed, name, type,
true);
+                if (oldDefinition != null) {
+                    Tree newDefinition = findMatchingPropertyDefinition(remaining, name,
type, true);
+                    if (newDefinition == null
+                            || (getBoolean(oldDefinition, JCR_PROTECTED)
+                            && !getBoolean(newDefinition, JCR_PROTECTED))) {
+                        tree.removeProperty(name);
+                    }
+                }
             }
 
-            Tree oldDefinition = findMatchingChildNodeDefinition(
-                    removed, name, typeNames);
-            if (oldDefinition != null) {
-                Tree newDefinition = findMatchingChildNodeDefinition(
-                        remaining, name, typeNames);
-                if (newDefinition == null
-                        || (getBoolean(oldDefinition, JCR_PROTECTED)
-                                && !getBoolean(newDefinition, JCR_PROTECTED))) {
-                    child.remove();
+            for (Tree child : tree.getChildren()) {
+                String name = child.getName();
+                Set<String> typeNames = newLinkedHashSet();
+                for (Tree type : getNodeTypes(child, typeRoot)) {
+                    typeNames.add(TreeUtil.getName(type, JCR_NODETYPENAME));
+                    addAll(typeNames, getNames(type, REP_SUPERTYPES));
+                }
+
+                Tree oldDefinition = findMatchingChildNodeDefinition(removed, name, typeNames);
+                if (oldDefinition != null) {
+                    Tree newDefinition = findMatchingChildNodeDefinition(remaining, name,
typeNames);
+                    if (newDefinition == null
+                            || (getBoolean(oldDefinition, JCR_PROTECTED)
+                            && !getBoolean(newDefinition, JCR_PROTECTED))) {
+                        child.remove();
+                    }
                 }
             }
         }

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java?rev=1558818&r1=1558817&r2=1558818&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/NodeImpl.java
Thu Jan 16 14:42:34 2014
@@ -1474,8 +1474,45 @@ public class NodeImpl<T extends NodeDele
         }
     }
 
+    /**
+     * Simplified implementation of the {@link org.apache.jackrabbit.api.JackrabbitNode#setMixins(String[])}
+     * method that adds all mixin types that are not yet present on this node
+     * and removes all mixins that are no longer contained in the specified
+     * array. Note, that this implementation will not work exactly like the
+     * variant in Jackrabbit 2.x which first created the effective node type
+     * and adjusted the set of child items accordingly.
+     *
+     * @param mixinNames
+     * @throws RepositoryException
+     */
     @Override
-    public void setMixins(String[] strings) throws RepositoryException {
-        throw new UnsupportedRepositoryOperationException("TODO: JackrabbitNode.setMixins
(OAK-770");
+    public void setMixins(String[] mixinNames) throws RepositoryException {
+        final Set<String> oakTypeNames = newLinkedHashSet();
+        for (String mixinName : mixinNames) {
+            oakTypeNames.add(getOakName(checkNotNull(mixinName)));
+        }
+        perform(new ItemWriteOperation<Void>() {
+            @Override
+            public void checkPreconditions() throws RepositoryException {
+                super.checkPreconditions();
+                if (!isCheckedOut()) {
+                    throw new VersionException("Cannot set mixin types. Node is checked in.");
+                }
+
+                // check for NODE_TYPE_MANAGEMENT permission here as we cannot
+                // distinguish between a combination of removeMixin and addMixin
+                // and Node#remove plus subsequent addNode when it comes to
+                // autocreated properties like jcr:create, jcr:uuid and so forth.
+                PropertyDelegate mixinProp = dlg.getPropertyOrNull(JCR_MIXINTYPES);
+                if (mixinProp != null) {
+                    sessionContext.getAccessManager().checkPermissions(dlg.getTree(), mixinProp.getPropertyState(),
Permissions.NODE_TYPE_MANAGEMENT);
+                }
+            }
+            @Override
+            public Void perform() throws RepositoryException {
+                dlg.setMixins(oakTypeNames);
+                return null;
+            }
+        });
     }
 }

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/JackrabbitNodeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/JackrabbitNodeTest.java?rev=1558818&r1=1558817&r2=1558818&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/JackrabbitNodeTest.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/JackrabbitNodeTest.java
Thu Jan 16 14:42:34 2014
@@ -25,11 +25,11 @@ import javax.jcr.Session;
 import javax.jcr.observation.Event;
 import javax.jcr.observation.ObservationManager;
 
+import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.api.JackrabbitNode;
 import org.apache.jackrabbit.commons.cnd.CndImporter;
 import org.apache.jackrabbit.test.AbstractJCRTest;
 import org.apache.jackrabbit.test.api.observation.EventResult;
-import org.junit.Ignore;
 
 /**
  * JackrabbitNodeTest: Copied and slightly adjusted from org.apache.jackrabbit.api.JackrabbitNodeTest,
@@ -120,23 +120,96 @@ public class JackrabbitNodeTest extends 
         }
     }
 
-    public void testRemoveMixin() throws RepositoryException {
+    /**
+     * @since oak 1.0
+     */
+    public void testSetNewMixins() throws RepositoryException {
+        // create node with mixin test:AA
+        Node n = testRootNode.addNode("foo", "nt:folder");
+        ((JackrabbitNode) n).setMixins(new String[]{"test:AA", "test:A"});
+        superuser.save();
+
+        assertTrue(n.isNodeType("test:AA"));
+        assertTrue(n.isNodeType("test:A"));
+        assertTrue(n.hasProperty(JcrConstants.JCR_MIXINTYPES));
+    }
+
+    /**
+     * @since oak 1.0
+     */
+    public void testSetNewMixins2() throws RepositoryException {
+        // create node with mixin test:AA
+        Node n = testRootNode.addNode("foo", "nt:folder");
+        ((JackrabbitNode) n).setMixins(new String[]{"test:A", "test:AA"});
+        superuser.save();
+
+        assertTrue(n.isNodeType("test:A"));
+        assertTrue(n.isNodeType("test:AA"));
+        assertTrue(n.hasProperty(JcrConstants.JCR_MIXINTYPES));
+    }
+
+    /**
+     * @since oak 1.0
+     */
+    public void testSetEmptyMixins() throws RepositoryException {
         // create node with mixin test:AA
         Node n = testRootNode.addNode("foo", "nt:folder");
         n.addMixin("test:AA");
-        n.setProperty("test:propAA", "AA");
-        n.setProperty("test:propA", "A");
         superuser.save();
 
-        // 'downgrade' from test:AA to test:A
-        n.removeMixin("test:AA");
+        ((JackrabbitNode) n).setMixins(new String[0]);
         superuser.save();
 
-        assertFalse(n.hasProperty("test:propA"));
-        assertFalse(n.hasProperty("test:propAA"));
+        assertFalse(n.isNodeType("test:AA"));
+        assertTrue(n.hasProperty(JcrConstants.JCR_MIXINTYPES));
+        assertEquals(0, n.getProperty(JcrConstants.JCR_MIXINTYPES).getValues().length);
+    }
+
+    /**
+     * @since oak 1.0
+     */
+    public void testSetRemoveMixins() throws RepositoryException {
+        // create node with mixin test:AA
+        Node n = testRootNode.addNode("foo", "nt:folder");
+        ((JackrabbitNode) n).setMixins(new String[]{"test:A", "test:AA"});
+        superuser.save();
+
+        ((JackrabbitNode) n).setMixins(new String[]{"test:A"});
+        superuser.save();
+
+        assertTrue(n.isNodeType("test:A"));
+        assertFalse(n.isNodeType("test:AA"));
+    }
+
+    /**
+     * @since oak 1.0
+     */
+    public void testUpdateMixins() throws RepositoryException {
+        // create node with mixin test:AA
+        Node n = testRootNode.addNode("foo", "nt:folder");
+        ((JackrabbitNode) n).setMixins(new String[]{"test:A", "test:AA"});
+        superuser.save();
+
+        assertTrue(n.isNodeType("test:AA"));
+        assertTrue(n.isNodeType("test:A"));
+
+        ((JackrabbitNode) n).setMixins(new String[]{"test:A", "test:AA", JcrConstants.MIX_REFERENCEABLE});
+        superuser.save();
+
+        assertTrue(n.isNodeType("test:AA"));
+        assertTrue(n.isNodeType("test:A"));
+        assertTrue(n.isNodeType(JcrConstants.MIX_REFERENCEABLE));
+        assertTrue(n.hasProperty(JcrConstants.JCR_UUID));
+
+        ((JackrabbitNode) n).setMixins(new String[]{JcrConstants.MIX_REFERENCEABLE});
+        superuser.save();
+
+        assertFalse(n.isNodeType("test:AA"));
+        assertFalse(n.isNodeType("test:A"));
+        assertTrue(n.isNodeType(JcrConstants.MIX_REFERENCEABLE));
+        assertTrue(n.hasProperty(JcrConstants.JCR_UUID));
     }
 
-    @Ignore("OAK-770") // FIXME: OAK-770
     public void testSetMixins() throws RepositoryException {
         // create node with mixin test:AA
         Node n = testRootNode.addNode("foo", "nt:folder");



Mime
View raw message