jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r1485150 - in /jackrabbit/oak/trunk: oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/ oak-jcr/src/t...
Date Wed, 22 May 2013 11:20:19 GMT
Author: jukka
Date: Wed May 22 11:20:18 2013
New Revision: 1485150

URL: http://svn.apache.org/r1485150
Log:
OAK-829: ConstraintViolationException while retrieving definition for all nodes with name
jcr:childNodeDefinition

Drop the index suffix from SNS names before looking up child node definitions.

Modified:
    jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/PathUtils.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.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/RepositoryTest.java

Modified: jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/PathUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/PathUtils.java?rev=1485150&r1=1485149&r2=1485150&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/PathUtils.java
(original)
+++ jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/PathUtils.java
Wed May 22 11:20:18 2013
@@ -18,6 +18,9 @@ package org.apache.jackrabbit.oak.common
 
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 import javax.annotation.Nonnull;
 
 /**
@@ -30,6 +33,9 @@ import javax.annotation.Nonnull;
  */
 public final class PathUtils {
 
+    private static final Pattern SNS_PATTERN =
+            Pattern.compile("(.+)\\[[1-9][0-9]*\\]$");
+
     private PathUtils() {
         // utility class
     }
@@ -153,6 +159,23 @@ public final class PathUtils {
     }
 
     /**
+     * Returns the given name without the possible SNS index suffix. If the
+     * name does not contain an SNS index, then it is returned as-is.
+     *
+     * @param name name with a possible SNS index suffix
+     * @return name without the SNS index suffix
+     */
+    @Nonnull
+    public static String dropIndexFromName(@Nonnull String name) {
+        Matcher matcher = SNS_PATTERN.matcher(name);
+        if (matcher.matches()) {
+            return matcher.group(1);
+        } else {
+            return name;
+        }
+    }
+
+    /**
      * Calculate the number of elements in the path. The root path has zero
      * elements.
      *

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java?rev=1485150&r1=1485149&r2=1485150&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java
Wed May 22 11:20:18 2013
@@ -28,15 +28,19 @@ import static org.apache.jackrabbit.JcrC
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
 import static org.apache.jackrabbit.JcrConstants.JCR_NODETYPENAME;
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.JcrConstants.JCR_SAMENAMESIBLINGS;
 import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
 import static org.apache.jackrabbit.oak.api.CommitFailedException.CONSTRAINT;
 import static org.apache.jackrabbit.oak.api.Type.UNDEFINED;
 import static org.apache.jackrabbit.oak.api.Type.UNDEFINEDS;
+import static org.apache.jackrabbit.oak.commons.PathUtils.dropIndexFromName;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_ABSTRACT;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_MANDATORY_CHILD_NODES;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_MANDATORY_PROPERTIES;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_NAMED_CHILD_NODE_DEFINITIONS;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_NAMED_PROPERTY_DEFINITIONS;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_RESIDUAL_CHILD_NODE_DEFINITIONS;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_RESIDUAL_PROPERTY_DEFINITIONS;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_SUPERTYPES;
 
 import java.util.List;
@@ -134,8 +138,9 @@ class EffectiveType {
 
         // Find matching named property definition
         for (NodeState type : types) {
-            NodeState named = type.getChildNode("oak:namedPropertyDefinitions");
-            NodeState definitions = named.getChildNode(escapedName);
+            NodeState definitions = type
+                    .getChildNode(OAK_NAMED_PROPERTY_DEFINITIONS)
+                    .getChildNode(escapedName);
 
             NodeState definition = definitions.getChildNode(definedType);
             if (definition.exists()) {
@@ -164,7 +169,7 @@ class EffectiveType {
         // Find matching residual property definition
         for (NodeState type : types) {
             NodeState residual =
-                    type.getChildNode("oak:residualPropertyDefinitions");
+                    type.getChildNode(OAK_RESIDUAL_PROPERTY_DEFINITIONS);
             NodeState definition = residual.getChildNode(definedType);
             if (!definition.exists()) {
                 definition = residual.getChildNode(undefinedType);
@@ -187,18 +192,19 @@ class EffectiveType {
      *         {@code false} otherwise
      */
     boolean isValidChildNode(String nameWithIndex, EffectiveType effective) {
-        String nodeName = getNameWithoutIndex(nameWithIndex);
+        String name = dropIndexFromName(nameWithIndex);
+        boolean sns = !name.equals(nameWithIndex);
         Set<String> typeNames = effective.getTypeNames();
 
         // Find matching named child node definition
         for (NodeState type : types) {
             NodeState definitions = type
                     .getChildNode(OAK_NAMED_CHILD_NODE_DEFINITIONS)
-                    .getChildNode(nodeName);
+                    .getChildNode(name);
 
             for (String typeName : typeNames) {
                 NodeState definition = definitions.getChildNode(typeName);
-                if (definition.exists()) {
+                if (definition.exists() && snsMatch(sns, definition)) {
                     return true;
                 }
             }
@@ -223,7 +229,7 @@ class EffectiveType {
                     type.getChildNode(OAK_RESIDUAL_CHILD_NODE_DEFINITIONS);
             for (String typeName : typeNames) {
                 NodeState definition = residual.getChildNode(typeName);
-                if (definition.exists()) {
+                if (definition.exists() && snsMatch(sns, definition)) {
                     return true;
                 }
             }
@@ -240,7 +246,8 @@ class EffectiveType {
      */
     @CheckForNull
     String getDefaultType(String nameWithIndex) {
-        String name = getNameWithoutIndex(nameWithIndex);
+        String name = dropIndexFromName(nameWithIndex);
+        boolean sns = !name.equals(nameWithIndex);
 
         for (NodeState type : types) {
             NodeState named = type
@@ -254,7 +261,7 @@ class EffectiveType {
                     residual.getChildNodeEntries())) {
                 NodeState definition = entry.getNodeState();
                 String defaultType = definition.getName(JCR_DEFAULTPRIMARYTYPE);
-                if (defaultType != null) {
+                if (defaultType != null && snsMatch(sns, definition)) {
                     return defaultType;
                 }
             }
@@ -343,18 +350,15 @@ class EffectiveType {
 
     //-----------------------------------------------------------< private >--
 
-    private static String getNameWithoutIndex(String name) {
-        int n = name.length();
-        if (n > 3 && name.charAt(n - 1) == ']') {
-            int i = n - 2;
-            while (i > 1 && Character.isDigit(name.charAt(i))) {
-                i--;
-            }
-            if (name.charAt(i) == '[') {
-                return name.substring(0, i);
-            }
-        }
-        return name;
+    /**
+     * Depending on the given SNS flag, checks whether the given child node
+     * definition allows same-name-siblings.
+     *
+     * @param sns SNS flag, {@code true} if processing an SNS node
+     * @param definition child node definition
+     */
+    private boolean snsMatch(boolean sns, NodeState definition) {
+        return !sns || definition.getBoolean(JCR_SAMENAMESIBLINGS);
     }
 
     private boolean nameSetContains(String set, String name) {

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=1485150&r1=1485149&r2=1485150&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
Wed May 22 11:20:18 2013
@@ -21,6 +21,7 @@ import static com.google.common.collect.
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
 import static org.apache.jackrabbit.oak.api.Type.STRING;
+import static org.apache.jackrabbit.oak.commons.PathUtils.dropIndexFromName;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.NODE_TYPES_PATH;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_SUPERTYPES;
 
@@ -390,7 +391,7 @@ public abstract class ReadOnlyNodeTypeMa
         checkNotNull(parent);
         checkNotNull(targetNode);
 
-        String name = targetNode.getName();
+        String name = dropIndexFromName(targetNode.getName());
         EffectiveNodeType eff = getEffectiveNodeType(parent);
         return eff.getNodeDefinition(name, getEffectiveNodeType(targetNode));
     }

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=1485150&r1=1485149&r2=1485150&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
Wed May 22 11:20:18 2013
@@ -36,12 +36,14 @@ import static org.apache.jackrabbit.JcrC
 import static org.apache.jackrabbit.JcrConstants.JCR_NODETYPENAME;
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
 import static org.apache.jackrabbit.JcrConstants.JCR_PROTECTED;
+import static org.apache.jackrabbit.JcrConstants.JCR_SAMENAMESIBLINGS;
 import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
 import static org.apache.jackrabbit.oak.api.Type.BOOLEAN;
 import static org.apache.jackrabbit.oak.api.Type.DATE;
 import static org.apache.jackrabbit.oak.api.Type.NAME;
 import static org.apache.jackrabbit.oak.api.Type.NAMES;
 import static org.apache.jackrabbit.oak.api.Type.STRING;
+import static org.apache.jackrabbit.oak.commons.PathUtils.dropIndexFromName;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_CREATEDBY;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_ABSTRACT;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_LASTMODIFIEDBY;
@@ -158,7 +160,9 @@ public class NodeDelegate extends ItemDe
         }
 
         Tree parent = tree.getParent();
-        String name = tree.getName();
+        String nameWithIndex = tree.getName();
+        String name = dropIndexFromName(nameWithIndex);
+        boolean sns = !name.equals(nameWithIndex);
         Tree typeRoot = sessionDelegate.getRoot().getTree(NODE_TYPES_PATH);
         List<Tree> types = getEffectiveType(parent, typeRoot);
 
@@ -183,10 +187,12 @@ public class NodeDelegate extends ItemDe
             }
 
             for (Tree type : types) {
-                Tree definitions = type.getChild(OAK_RESIDUAL_CHILD_NODE_DEFINITIONS);
+                Tree definitions =
+                        type.getChild(OAK_RESIDUAL_CHILD_NODE_DEFINITIONS);
                 for (String typeName : typeNames) {
                     Tree definition = definitions.getChild(typeName);
-                    if (getBoolean(definition, JCR_PROTECTED)) {
+                    if ((!sns || getBoolean(definition, JCR_SAMENAMESIBLINGS))
+                            && getBoolean(definition, JCR_PROTECTED)) {
                         return true;
                     }
                 }
@@ -541,6 +547,9 @@ public class NodeDelegate extends ItemDe
         }
 
         // TODO: use a separate oak:autoCreateChildNodeDefinitions
+        // Note that we use only named, non-SNS child node definitions
+        // as there can be no reasonable default values for residual or
+        // SNS child nodes
         Tree childNodes = type.getChild(OAK_NAMED_CHILD_NODE_DEFINITIONS);
         for (Tree definitions : childNodes.getChildren()) {
             String name = definitions.getName();
@@ -606,13 +615,17 @@ public class NodeDelegate extends ItemDe
      */
     private static String getDefaultChildType(
             Tree typeRoot, Tree parent, String childName) {
+        String name = dropIndexFromName(childName);
+        boolean sns = !name.equals(childName);
         List<Tree> types = getEffectiveType(parent, typeRoot);
 
         // first look for named node definitions
         for (Tree type : types) {
-            Tree named = type.getChild(OAK_NAMED_CHILD_NODE_DEFINITIONS);
-            Tree definitions = named.getChild(childName);
-            String defaultName = findDefaultPrimaryType(typeRoot, definitions);
+            Tree definitions = type
+                    .getChild(OAK_NAMED_CHILD_NODE_DEFINITIONS)
+                    .getChild(name);
+            String defaultName =
+                    findDefaultPrimaryType(typeRoot, definitions, sns);
             if (defaultName != null) {
                 return defaultName;
             }
@@ -620,8 +633,10 @@ public class NodeDelegate extends ItemDe
 
         // then check residual definitions
         for (Tree type : types) {
-            Tree definitions = type.getChild(OAK_RESIDUAL_CHILD_NODE_DEFINITIONS);
-            String defaultName = findDefaultPrimaryType(typeRoot, definitions);
+            Tree definitions = type
+                    .getChild(OAK_RESIDUAL_CHILD_NODE_DEFINITIONS);
+            String defaultName =
+                    findDefaultPrimaryType(typeRoot, definitions, sns);
             if (defaultName != null) {
                 return defaultName;
             }
@@ -655,10 +670,12 @@ public class NodeDelegate extends ItemDe
         return types;
     }
 
-    private static String findDefaultPrimaryType(Tree typeRoot, Tree definitions) {
+    private static String findDefaultPrimaryType(
+            Tree typeRoot, Tree definitions, boolean sns) {
         for (Tree definition : definitions.getChildren()) {
             String defaultName = getName(definition, JCR_DEFAULTPRIMARYTYPE);
-            if (defaultName != null) {
+            if (defaultName != null
+                    && (!sns || getBoolean(definition, JCR_SAMENAMESIBLINGS))) {
                 return defaultName;
             }
         }

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/RepositoryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/RepositoryTest.java?rev=1485150&r1=1485149&r2=1485150&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/RepositoryTest.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/RepositoryTest.java
Wed May 22 11:20:18 2013
@@ -74,6 +74,7 @@ import javax.jcr.observation.Observation
 
 import com.google.common.collect.Sets;
 import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.commons.JcrUtils;
 import org.apache.jackrabbit.commons.cnd.CndImporter;
 import org.apache.jackrabbit.commons.cnd.ParseException;
 import org.junit.Before;
@@ -2151,6 +2152,17 @@ public class RepositoryTest extends Abst
         assertTrue(session.nodeExists("/{0} test"));
     }
 
+    @Test
+    public void testGetDefinitionWithSNS() throws RepositoryException, IOException {
+        Session session = getAdminSession();
+        Node node = session.getNode("/jcr:system/jcr:nodeTypes/nt:file");
+        // TODO: use getNode("jcr:childNodeDefinition[1]") once that works
+        for (Node definition
+                : JcrUtils.getChildNodes(node, "jcr:childNodeDefinition")) {
+            definition.getDefinition(); // should not throw
+        }
+    }
+
     //------------------------------------------------------------< private >---
 
     private Node getNode(String path) throws RepositoryException {



Mime
View raw message