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/02/19 13:30:00 UTC

svn commit: r1447697 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak: plugins/identifier/ plugins/nodetype/ plugins/observation/ plugins/version/ security/authorization/

Author: jukka
Date: Tue Feb 19 12:29:59 2013
New Revision: 1447697

URL: http://svn.apache.org/r1447697
Log:
OAK-639: Optimize isNodeType checks

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeFilter.java
    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/VersionHook.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionablePathHook.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidator.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionHook.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java?rev=1447697&r1=1447696&r2=1447697&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java Tue Feb 19 12:29:59 2013
@@ -25,7 +25,6 @@ import java.util.UUID;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
 import javax.jcr.query.Query;
 
 import com.google.common.base.Charsets;
@@ -197,56 +196,52 @@ public class IdentifierManager {
      */
     @Nonnull
     public Set<String> getReferences(boolean weak, Tree tree, final String propertyName, final String... nodeTypeNames) {
-        if (!isReferenceable(tree)) {
-            return Collections.emptySet();
-        } else {
-            try {
-                final String uuid = getIdentifier(tree);
-                String reference = weak ? PropertyType.TYPENAME_WEAKREFERENCE : PropertyType.TYPENAME_REFERENCE;
-                String pName = propertyName == null ? "*" : propertyName;   // TODO: sanitize against injection attacks!?
-                Map<String, ? extends PropertyValue> bindings = Collections.singletonMap("uuid", PropertyValues.newString(uuid));
-
-                Result result = root.getQueryEngine().executeQuery(
-                        "SELECT * FROM [nt:base] WHERE PROPERTY([" + pName + "], '" + reference + "') = $uuid",
-                        Query.JCR_SQL2, Long.MAX_VALUE, 0, bindings, new NamePathMapper.Default());
-
-                Iterable<String> paths = Iterables.transform(result.getRows(),
-                        new Function<ResultRow, String>() {
-                            @Override
-                            public String apply(ResultRow row) {
-                                String pName = propertyName == null
-                                        ? findProperty(row.getPath(), uuid)
-                                        : propertyName;
-                                return PathUtils.concat(row.getPath(), pName);
-                            }
-                        });
+        if (!nodeTypeManager.isNodeType(tree, JcrConstants.MIX_REFERENCEABLE)) {
+            return Collections.emptySet(); // shortcut
+        }
+
+        try {
+            final String uuid = getIdentifier(tree);
+            String reference = weak ? PropertyType.TYPENAME_WEAKREFERENCE : PropertyType.TYPENAME_REFERENCE;
+            String pName = propertyName == null ? "*" : propertyName;   // TODO: sanitize against injection attacks!?
+            Map<String, ? extends PropertyValue> bindings = Collections.singletonMap("uuid", PropertyValues.newString(uuid));
+
+            Result result = root.getQueryEngine().executeQuery(
+                    "SELECT * FROM [nt:base] WHERE PROPERTY([" + pName + "], '" + reference + "') = $uuid",
+                    Query.JCR_SQL2, Long.MAX_VALUE, 0, bindings, new NamePathMapper.Default());
+
+            Iterable<String> paths = Iterables.transform(result.getRows(),
+                    new Function<ResultRow, String>() {
+                @Override
+                public String apply(ResultRow row) {
+                    String pName = propertyName == null
+                            ? findProperty(row.getPath(), uuid)
+                                    : propertyName;
+                            return PathUtils.concat(row.getPath(), pName);
+                }
+            });
 
-                if (nodeTypeNames.length > 0) {
-                    paths = Iterables.filter(paths, new Predicate<String>() {
-                        @Override
-                        public boolean apply(String path) {
-                            Tree tree = root.getTree(PathUtils.getParentPath(path));
-                            if (tree != null) {
-                                for (String ntName : nodeTypeNames) {
-                                    try {
-                                        if (nodeTypeManager.isNodeType(tree, ntName)) {
-                                            return true;
-                                        }
-                                    } catch (RepositoryException e) {
-                                        log.warn(e.getMessage());
-                                    }
+            if (nodeTypeNames.length > 0) {
+                paths = Iterables.filter(paths, new Predicate<String>() {
+                    @Override
+                    public boolean apply(String path) {
+                        Tree tree = root.getTree(PathUtils.getParentPath(path));
+                        if (tree != null) {
+                            for (String ntName : nodeTypeNames) {
+                                if (nodeTypeManager.isNodeType(tree, ntName)) {
+                                    return true;
                                 }
                             }
-                            return false;
                         }
-                    });
-                }
-
-                return Sets.newHashSet(paths);
-            } catch (ParseException e) {
-                log.error("query failed", e);
-                return Collections.emptySet();
+                        return false;
+                    }
+                });
             }
+
+            return Sets.newHashSet(paths);
+        } catch (ParseException e) {
+            log.error("query failed", e);
+            return Collections.emptySet();
         }
     }
 
@@ -273,15 +268,6 @@ public class IdentifierManager {
         return refProp.getName();
     }
 
-    public boolean isReferenceable(Tree tree) {
-        try {
-            return nodeTypeManager.isNodeType(tree, JcrConstants.MIX_REFERENCEABLE);
-        } catch (RepositoryException e) {
-            log.warn(e.getMessage());
-            return false;
-        }
-    }
-
     @CheckForNull
     private String resolveUUID(String uuid) {
         return resolveUUID(StringPropertyState.stringProperty("", uuid));

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java?rev=1447697&r1=1447696&r2=1447697&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java Tue Feb 19 12:29:59 2013
@@ -18,9 +18,11 @@ package org.apache.jackrabbit.oak.plugin
 
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Queue;
+import java.util.Set;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
@@ -45,11 +47,14 @@ import javax.jcr.nodetype.PropertyDefini
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Queues;
+import com.google.common.collect.Sets;
+
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.commons.iterator.NodeTypeIteratorAdapter;
 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.core.ReadOnlyTree;
 import org.apache.jackrabbit.oak.namepath.NameMapper;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
@@ -278,24 +283,62 @@ public abstract class ReadOnlyNodeTypeMa
     }
 
     //------------------------------------------< EffectiveNodeTypeProvider >---
+
     @Override
-    public boolean isNodeType(Tree tree, String oakNtName) throws RepositoryException {
-        NodeTypeImpl nodeType = internalGetNodeType(oakNtName);
-        NodeUtil node = new NodeUtil(tree);
-        String ntName = node.getPrimaryNodeTypeName();
-        if (ntName == null) {
-            return false;
-        } else if (oakNtName.equals(ntName) || internalGetNodeType(ntName).isNodeType(oakNtName)) {
+    public boolean isNodeType(Tree tree, String oakNtName) {
+        // shortcuts for common cases
+        if (JcrConstants.NT_BASE.equals(oakNtName)) {
             return true;
+        } else if (JcrConstants.MIX_REFERENCEABLE.equals(oakNtName)
+                && !tree.hasProperty(JcrConstants.JCR_UUID)) {
+            return false;
+        } else if (JcrConstants.MIX_VERSIONABLE.equals(oakNtName)
+                && !tree.hasProperty(JcrConstants.JCR_ISCHECKEDOUT)) {
+            return false;
+        }
+
+        Set<String> typeNames = Sets.newHashSet();
+
+        PropertyState primary = tree.getProperty(JcrConstants.JCR_PRIMARYTYPE);
+        if (primary != null && primary.getType() == Type.NAME) {
+            String name = primary.getValue(Type.NAME);
+            if (oakNtName.equals(name)) {
+                return true;
+            } else {
+                typeNames.add(name);
+            }
         }
-        String[] mixinNames = node.getStrings(JcrConstants.JCR_MIXINTYPES);
-        if (mixinNames != null) {
-            for (String mixinName : mixinNames) {
-                if (oakNtName.equals(mixinName) || internalGetNodeType(mixinName).isNodeType(oakNtName)) {
+
+        PropertyState mixins = tree.getProperty(JcrConstants.JCR_MIXINTYPES);
+        if (mixins != null && mixins.getType() == Type.NAMES) {
+            for (String name : mixins.getValue(Type.NAMES)) {
+                if (oakNtName.equals(name)) {
                     return true;
+                } else {
+                    typeNames.add(name);
                 }
             }
         }
+
+        Tree types = getTypes();
+        LinkedList<String> queue = Lists.newLinkedList(typeNames);
+        while (!queue.isEmpty()) {
+            Tree type = types.getChild(queue.removeFirst());
+            if (type != null) {
+                PropertyState supertypes =
+                        type.getProperty(JcrConstants.JCR_SUPERTYPES);
+                if (supertypes != null && supertypes.getType() == Type.NAMES) {
+                    for (String name : supertypes.getValue(Type.NAMES)) {
+                        if (oakNtName.equals(name)) {
+                            return true;
+                        } else if (typeNames.add(name)) {
+                            queue.addLast(name);
+                        }
+                    }
+                }
+            }
+        }
+
         return false;
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeFilter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeFilter.java?rev=1447697&r1=1447696&r2=1447697&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeFilter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeFilter.java Tue Feb 19 12:29:59 2013
@@ -101,20 +101,15 @@ class ChangeFilter {
     private boolean includeByType(Tree associatedParentNode) {
         if (nodeTypeOakName == null) {
             return true;
-        }
-        try {
+        } else {
             for (String oakName : nodeTypeOakName) {
                 if (ntMgr.isNodeType(associatedParentNode, oakName)) {
                     return true;
                 }
             }
-        } catch (RepositoryException e) {
-            // shouldn't happen, because node type was validated in constructor
-            // FIXME: rather throw?
-            log.warn("Unable to check node type of associated parent node", e);
+            // filter has node types set but none matched
+            return false;
         }
-        // filter has node types set but none matched
-        return false;
     }
 
     /**

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=1447697&r1=1447696&r2=1447697&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 Tue Feb 19 12:29:59 2013
@@ -223,12 +223,8 @@ public abstract class ReadOnlyVersionMan
      * @throws RepositoryException if an error occurs while checking the node
      *                             type of the tree.
      */
-    protected boolean isVersionable(@Nonnull Tree tree) throws RepositoryException {
-        checkNotNull(tree);
-        // the first check for the jcr:isCheckedOut property will fail fast
-        // if the node is not versionable. the second check is to make sure
-        // the node is in fact versionable.
-        return tree.hasProperty(VersionConstants.JCR_ISCHECKEDOUT)
-                && getNodeTypeManager().isNodeType(tree, VersionConstants.MIX_VERSIONABLE);
+    protected boolean isVersionable(@Nonnull Tree tree) {
+        return getNodeTypeManager().isNodeType(
+                checkNotNull(tree), VersionConstants.MIX_VERSIONABLE);
     }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionHook.java?rev=1447697&r1=1447696&r2=1447697&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionHook.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionHook.java Tue Feb 19 12:29:59 2013
@@ -166,18 +166,14 @@ public class VersionHook implements Comm
          * @return whether the node is versionable.
          */
         private boolean isVersionable() {
-            try {
-                if (isVersionable == null) {
-                    // this is not 100% correct, because t.getPath() will
-                    // not return the correct path for nodeAfter, but is
-                    // sufficient to check if it is versionable
-                    Tree t = new ReadOnlyTree(nodeAfter.getNodeState());
-                    isVersionable = vMgr.isVersionable(t);
-                }
-                return isVersionable;
-            } catch (RepositoryException e) {
-                throw new UncheckedRepositoryException(e);
+            if (isVersionable == null) {
+                // this is not 100% correct, because t.getPath() will
+                // not return the correct path for nodeAfter, but is
+                // sufficient to check if it is versionable
+                Tree t = new ReadOnlyTree(nodeAfter.getNodeState());
+                isVersionable = vMgr.isVersionable(t);
             }
+            return isVersionable;
         }
 
         private boolean isVersionProperty(PropertyState state) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionablePathHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionablePathHook.java?rev=1447697&r1=1447696&r2=1447697&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionablePathHook.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/version/VersionablePathHook.java Tue Feb 19 12:29:59 2013
@@ -17,7 +17,6 @@
 package org.apache.jackrabbit.oak.plugins.version;
 
 import javax.annotation.Nonnull;
-import javax.jcr.RepositoryException;
 
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
@@ -33,6 +32,8 @@ import org.apache.jackrabbit.oak.spi.sta
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
+import com.google.common.collect.ImmutableSet;
+
 /**
  * Commit hook which is responsible for storing the path of the versionable
  * node with every version history. This includes creating the path property
@@ -74,7 +75,10 @@ public class VersionablePathHook impleme
                 NodeBuilder vhBuilder = versionManager.getOrCreateVersionHistory(nodeAfter.builder);
 
                 if (vhBuilder.getProperty(JcrConstants.JCR_MIXINTYPES) == null) {
-                    vhBuilder.setProperty(JcrConstants.JCR_MIXINTYPES, MIX_REP_VERSIONABLE_PATHS, Type.PATH);
+                    vhBuilder.setProperty(
+                            JcrConstants.JCR_MIXINTYPES,
+                            ImmutableSet.of(MIX_REP_VERSIONABLE_PATHS),
+                            Type.NAMES);
                 }
 
                 String versionablePath = nodeAfter.path;
@@ -112,11 +116,7 @@ public class VersionablePathHook impleme
         private boolean isVersionable(ReadWriteVersionManager versionManager) {
             // FIXME: this readonlytree is not properly connect to it's parent
             Tree tree = new ReadOnlyTree(null, PathUtils.getName(path), builder.getNodeState());
-            try {
-                return versionManager.isVersionable(tree);
-            } catch (RepositoryException e) {
-                return false;
-            }
+            return versionManager.isVersionable(tree);
         }
     }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidator.java?rev=1447697&r1=1447696&r2=1447697&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidator.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AccessControlValidator.java Tue Feb 19 12:29:59 2013
@@ -161,12 +161,8 @@ class AccessControlValidator implements 
         }
 
         String msg = "Isolated policy node. Parent is not of type " + requiredMixin;
-        try {
-            if (!ntMgr.isNodeType(accessControlledTree, requiredMixin)) {
-                fail(msg);
-            }
-        } catch (RepositoryException e) {
-            throw new CommitFailedException(msg, e);
+        if (!ntMgr.isNodeType(accessControlledTree, requiredMixin)) {
+            fail(msg);
         }
 
         if (MIX_REP_REPO_ACCESS_CONTROLLABLE.equals(requiredMixin)) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionHook.java?rev=1447697&r1=1447696&r2=1447697&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionHook.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionHook.java Tue Feb 19 12:29:59 2013
@@ -19,7 +19,6 @@ package org.apache.jackrabbit.oak.securi
 import java.util.Collections;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
-import javax.jcr.RepositoryException;
 
 import com.google.common.collect.Lists;
 import org.apache.jackrabbit.JcrConstants;
@@ -179,19 +178,11 @@ public class PermissionHook implements C
 
         //--------------------------------------------------------< private >---
         private boolean isACL(Node parent) {
-            try {
-                return ntMgr.isNodeType(getTree(parent.getName(), parent.getNodeState()), NT_REP_POLICY);
-            } catch (RepositoryException e) {
-                return false;
-            }
+            return ntMgr.isNodeType(getTree(parent.getName(), parent.getNodeState()), NT_REP_POLICY);
         }
 
         private boolean isACE(String name, NodeState nodeState) {
-            try {
-                return ntMgr.isNodeType(getTree(name, nodeState), NT_REP_ACE);
-            } catch (RepositoryException e) {
-                return false;
-            }
+            return ntMgr.isNodeType(getTree(name, nodeState), NT_REP_ACE);
         }
 
         private static String getAccessControlledPath(BaseNode aclNode) {