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 ju...@apache.org on 2013/04/26 08:56:29 UTC

svn commit: r1476074 - in /jackrabbit/oak/trunk/oak-jcr/src: main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java test/java/org/apache/jackrabbit/oak/jcr/nodetype/MixinTest.java

Author: jukka
Date: Fri Apr 26 06:56:28 2013
New Revision: 1476074

URL: http://svn.apache.org/r1476074
Log:
OAK-702: Optimize access to node type information

Use the /jcr:system/jcr:nodeTypes tree directly in addNode()

Modified:
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/MixinTest.java

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java?rev=1476074&r1=1476073&r2=1476074&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java Fri Apr 26 06:56:28 2013
@@ -76,7 +76,6 @@ import org.apache.jackrabbit.oak.core.Id
 import org.apache.jackrabbit.oak.jcr.delegate.NodeDelegate;
 import org.apache.jackrabbit.oak.jcr.delegate.PropertyDelegate;
 import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
-import org.apache.jackrabbit.oak.plugins.nodetype.DefinitionProvider;
 import org.apache.jackrabbit.oak.plugins.nodetype.EffectiveNodeType;
 import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
 import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
@@ -90,6 +89,7 @@ import static com.google.common.base.Pre
 import static javax.jcr.Property.JCR_LOCK_IS_DEEP;
 import static javax.jcr.Property.JCR_LOCK_OWNER;
 import static javax.jcr.PropertyType.UNDEFINED;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
 
 /**
  * TODO document
@@ -203,9 +203,17 @@ public class NodeImpl<T extends NodeDele
         return addNode(relPath, null);
     }
 
-    @Override
-    @Nonnull
-    public Node addNode(final String relPath, final String primaryNodeTypeName) throws RepositoryException {
+    @Override @Nonnull
+    public Node addNode(final String relPath, String primaryNodeTypeName)
+            throws RepositoryException {
+        final String oakPath = getOakPathOrThrowNotFound(relPath);
+        final String oakTypeName;
+        if (primaryNodeTypeName != null) {
+            oakTypeName = getOakName(primaryNodeTypeName);
+        } else {
+            oakTypeName = null;
+        }
+
         return perform(new ItemWriteOperation<Node>() {
             @Override
             protected void checkPreconditions() throws RepositoryException {
@@ -215,7 +223,6 @@ public class NodeImpl<T extends NodeDele
 
             @Override
             public Node perform() throws RepositoryException {
-                String oakPath = sessionContext.getOakPathOrThrowNotFound(relPath);
                 String oakName = PathUtils.getName(oakPath);
                 String parentPath = PathUtils.getParentPath(oakPath);
 
@@ -238,30 +245,14 @@ public class NodeImpl<T extends NodeDele
                     throw new ItemExistsException(relPath);
                 }
 
-                String ntName = primaryNodeTypeName;
-                if (ntName == null) {
-                    DefinitionProvider dp = getDefinitionProvider();
-                    NodeDefinition def = dp.getDefinition(parent.getTree(), oakName);
-                    ntName = def.getDefaultPrimaryTypeName();
-                    if (ntName == null) {
-                        throw new ConstraintViolationException(
-                                "no matching child node definition found for " + relPath);
-                    }
-                } else {
-                    // check for NODE_TYPE_MANAGEMENT permission here as we cannot
-                    // distinguish between user-supplied and system-generated
-                    // modification of that property in the PermissionValidator
-                    if (!hasNtMgtPermission(JcrConstants.JCR_PRIMARYTYPE, ntName)) {
-                        throw new AccessDeniedException("Access denied.");
-                    }
+                // check for NODE_TYPE_MANAGEMENT permission here as we cannot
+                // distinguish between user-supplied and system-generated
+                // modification of that property in the PermissionValidator
+                if (oakTypeName != null &&
+                        !hasNtMgtPermission(JCR_PRIMARYTYPE, oakTypeName)) {
+                    throw new AccessDeniedException("Access denied.");
                 }
-
-                // TODO: figure out the right place for this check
-                NodeType nt = getNodeTypeManager().getNodeType(ntName); // throws on not found
-                if (nt.isAbstract() || nt.isMixin()) {
-                    throw new ConstraintViolationException();
-                }
-                // TODO: END
+                String ntName = dlg.getDefaultChildType(oakName, oakTypeName);
 
                 NodeDelegate added = parent.addChild(oakName);
                 if (added == null) {

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=1476074&r1=1476073&r2=1476074&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 Fri Apr 26 06:56:28 2013
@@ -16,8 +16,23 @@
  */
 package org.apache.jackrabbit.oak.jcr.delegate;
 
+import static com.google.common.collect.Lists.newArrayList;
+import static java.util.Collections.emptyList;
+import static org.apache.jackrabbit.JcrConstants.JCR_DEFAULTPRIMARYTYPE;
+import static org.apache.jackrabbit.JcrConstants.JCR_ISMIXIN;
+import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.oak.api.Type.BOOLEAN;
+import static org.apache.jackrabbit.oak.api.Type.NAME;
+import static org.apache.jackrabbit.oak.api.Type.NAMES;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_ABSTRACT;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.NODE_TYPES_PATH;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_NAMED_CHILD_NODE_DEFINITIONS;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_RESIDUAL_CHILD_NODE_DEFINITIONS;
+
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
@@ -25,10 +40,13 @@ import javax.jcr.InvalidItemStateExcepti
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.RepositoryException;
 import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Iterators;
+
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.TreeLocation;
@@ -242,6 +260,86 @@ public class NodeDelegate extends ItemDe
         getTree().setOrderableChildren(enable);
     }
 
+    public String getDefaultChildType(String childName, String typeName)
+            throws NoSuchNodeTypeException, ConstraintViolationException,
+            InvalidItemStateException {
+        Tree typeRoot = sessionDelegate.getRoot().getTree(NODE_TYPES_PATH);
+        if (typeName != null) {
+            Tree type = typeRoot.getChild(typeName);
+            if (type == null) {
+                throw new NoSuchNodeTypeException(
+                        "Node type " + typeName + " does not exist");
+            } else if (getBoolean(type, JCR_IS_ABSTRACT)) {
+                throw new ConstraintViolationException(
+                        "Node type " + typeName + " is abstract");
+            } else if (getBoolean(type, JCR_ISMIXIN)) {
+                throw new ConstraintViolationException(
+                        "Node type " + typeName + " is a mixin type");
+            } else {
+                return typeName;
+            }
+        } else {
+            List<Tree> types = newArrayList();
+            Tree parent = getTree();
+
+            String primary = getName(parent, JCR_PRIMARYTYPE);
+            if (primary != null) {
+                Tree type = typeRoot.getChild(primary);
+                if (type != null) {
+                    types.add(type);
+                }
+            }
+
+            for (String mixin : getNames(parent, JCR_MIXINTYPES)) {
+                Tree type = typeRoot.getChild(mixin);
+                if (type != null) {
+                    types.add(type);
+                }
+            }
+
+            // first look for named node definitions
+            for (Tree type : types) {
+                Tree named = type.getChild(OAK_NAMED_CHILD_NODE_DEFINITIONS);
+                if (named != null) {
+                    Tree definitions = named.getChild(childName);
+                    if (definitions != null) {
+                        String defaultName =
+                                findDefaultPrimaryType(typeRoot, definitions);
+                        if (defaultName != null) {
+                            return defaultName;
+                        }
+                    }
+                }
+            }
+
+            // then check residual definitions
+            for (Tree type : types) {
+                Tree definitions = type.getChild(OAK_RESIDUAL_CHILD_NODE_DEFINITIONS);
+                if (definitions != null) {
+                    String defaultName =
+                            findDefaultPrimaryType(typeRoot, definitions);
+                    if (defaultName != null) {
+                        return defaultName;
+                    }
+                }
+            }
+
+            // no matching child node definition found
+            throw new ConstraintViolationException(
+                    "No default node type available for child node " + childName);
+        }
+    }
+
+    private String findDefaultPrimaryType(Tree typeRoot, Tree definitions) {
+        for (Tree definition : definitions.getChildren()) {
+            String defaultName = getName(definition, JCR_DEFAULTPRIMARYTYPE);
+            if (defaultName != null) {
+                return defaultName;
+            }
+        }
+        return null;
+    }
+
     //------------------------------------------------------------< internal >---
 
     @Nonnull // FIXME this should be package private. OAK-672
@@ -297,4 +395,34 @@ public class NodeDelegate extends ItemDe
                     }
                 });
     }
+
+    // Generic property value accessors. TODO: add to Tree?
+
+    private static boolean getBoolean(Tree tree, String name) {
+        PropertyState property = tree.getProperty(name);
+        return property != null
+                && property.getType() == BOOLEAN
+                && property.getValue(BOOLEAN);
+    }
+
+    @CheckForNull
+    private static String getName(Tree tree, String name) {
+        PropertyState property = tree.getProperty(name);
+        if (property != null && property.getType() == NAME) {
+            return property.getValue(NAME);
+        } else {
+            return null;
+        }
+    }
+
+    @Nonnull
+    private static Iterable<String> getNames(Tree tree, String name) {
+        PropertyState property = tree.getProperty(name);
+        if (property != null && property.getType() == NAMES) {
+            return property.getValue(NAMES);
+        } else {
+            return emptyList();
+        }
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/MixinTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/MixinTest.java?rev=1476074&r1=1476073&r2=1476074&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/MixinTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/MixinTest.java Fri Apr 26 06:56:28 2013
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.oak.jcr.nodetype;
 
+import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
+
 import javax.jcr.Node;
 import javax.jcr.nodetype.NoSuchNodeTypeException;
 
@@ -47,19 +49,26 @@ public class MixinTest extends AbstractJ
 
     @Test
     public void testRemoveMixinWithoutMixinProperty() throws Exception {
+        Node node = testRootNode.addNode(
+                "testRemoveMixinWithoutMixinProperty", NT_UNSTRUCTURED);
+        superuser.save();
         try {
-            assertFalse(testRootNode.hasProperty(JcrConstants.JCR_MIXINTYPES));
-            testRootNode.removeMixin(JcrConstants.MIX_REFERENCEABLE);
+            node.removeMixin(JcrConstants.MIX_REFERENCEABLE);
             fail();
         } catch (NoSuchNodeTypeException e) {
             // success
+        } finally {
+            node.remove();
+            superuser.save();
         }
 
     }
 
     @Test
     public void testRemoveInheritedMixin() throws Exception {
-        testRootNode.addMixin(JcrConstants.MIX_VERSIONABLE);
+        Node node = testRootNode.addNode(
+                "testRemoveInheritedMixin", NT_UNSTRUCTURED);
+        node.addMixin(JcrConstants.MIX_VERSIONABLE);
         superuser.save();
 
         try {
@@ -67,6 +76,9 @@ public class MixinTest extends AbstractJ
             fail();
         } catch (NoSuchNodeTypeException e) {
             // success
+        } finally {
+            node.remove();
+            superuser.save();
         }
     }