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 2012/06/01 01:18:11 UTC

svn commit: r1344937 - in /jackrabbit/oak/trunk/oak-core: ./ src/main/java/org/apache/jackrabbit/oak/kernel/ src/main/java/org/apache/jackrabbit/oak/plugins/name/ src/test/java/org/apache/jackrabbit/oak/plugins/name/

Author: jukka
Date: Thu May 31 23:18:10 2012
New Revision: 1344937

URL: http://svn.apache.org/viewvc?rev=1344937&view=rev
Log:
OAK-125: Improved namespace registry

Use the registered namespaces also in the validator.
+ various smaller improvements

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/Namespaces.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/name/NameValidatorTest.java
Modified:
    jackrabbit/oak/trunk/oak-core/pom.xml
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/PropertyStateImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/NameValidator.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/NameValidatorProvider.java

Modified: jackrabbit/oak/trunk/oak-core/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/pom.xml?rev=1344937&r1=1344936&r2=1344937&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-core/pom.xml Thu May 31 23:18:10 2012
@@ -90,6 +90,11 @@
       <artifactId>bndlib</artifactId>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.scr.annotations</artifactId>
+      <scope>provided</scope>
+    </dependency>
 
     <dependency>
       <groupId>org.apache.jackrabbit</groupId>

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/PropertyStateImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/PropertyStateImpl.java?rev=1344937&r1=1344936&r2=1344937&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/PropertyStateImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/PropertyStateImpl.java Thu May 31 23:18:10 2012
@@ -25,6 +25,8 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
+import javax.jcr.PropertyType;
+
 public class PropertyStateImpl implements PropertyState {
 
     private final String name;
@@ -47,6 +49,10 @@ public class PropertyStateImpl implement
         this(name, null, Collections.unmodifiableList(values));
     }
 
+    public PropertyStateImpl(String name, String value) {
+        this(name, new CoreValueImpl(value, PropertyType.STRING));
+    }
+
     @Override
     public String getName() {
         return name;

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/NameValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/NameValidator.java?rev=1344937&r1=1344936&r2=1344937&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/NameValidator.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/NameValidator.java Thu May 31 23:18:10 2012
@@ -17,12 +17,15 @@
 package org.apache.jackrabbit.oak.plugins.name;
 
 import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.CoreValue;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.spi.commit.Validator;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
 import java.util.Set;
 
+import javax.jcr.PropertyType;
+
 class NameValidator implements Validator {
 
     private final Set<String> prefixes;
@@ -32,36 +35,37 @@ class NameValidator implements Validator
     }
 
     protected void checkValidName(String name) throws CommitFailedException {
-        String prefix = null;
-        String local = name;
-
         int colon = name.indexOf(':');
-        if (colon == name.length() - 1) {
-            throw new CommitFailedException("Local name most not be empty");
-        }
         if (colon != -1) {
-            prefix = name.substring(0, colon);
-            local = name.substring(colon + 1);
+            String prefix = name.substring(0, colon);
+            if (prefix.length() == 0 || !prefixes.contains(prefix)) {
+                throw new CommitFailedException(
+                        "Invalid namespace prefix: " + name);
+            }
         }
 
-        if ((prefix != null && !prefixes.contains(prefix)) || !isValidLocalName(local)) {
+        String local = name.substring(colon + 1);
+        if (!Namespaces.isValidLocalName(local)) {
             throw new CommitFailedException("Invalid name: " + name);
         }
     }
 
-    private static boolean isValidLocalName(String local) {
-        if (".".equals(local) || "..".equals(local)) {
-            return false;
-        }
-
-        for (int i = 0; i < local.length(); i++) {
-            char ch = local.charAt(i);
-            if ("/:[]|*".indexOf(ch) != -1) { // TODO: XMLChar check
-                return false;
+    protected void checkValidValue(PropertyState property)
+            throws CommitFailedException {
+        if (property.isArray()) {
+            for (CoreValue value : property.getValues()) {
+                checkValidValue(value);
             }
+        } else {
+            checkValidValue(property.getValue());
         }
+    }
 
-        return true;
+    protected void checkValidValue(CoreValue value)
+            throws CommitFailedException {
+        if (value.getType() == PropertyType.NAME) {
+            checkValidName(value.getString());
+        }
     }
 
     //-------------------------------------------------------< NodeValidator >
@@ -70,11 +74,13 @@ class NameValidator implements Validator
     public void propertyAdded(PropertyState after)
             throws CommitFailedException {
         checkValidName(after.getName());
+        checkValidValue(after);
     }
 
     @Override
-    public void propertyChanged(PropertyState before, PropertyState after) {
-        // do nothing
+    public void propertyChanged(PropertyState before, PropertyState after)
+            throws CommitFailedException {
+        checkValidValue(after);
     }
 
     @Override
@@ -91,8 +97,7 @@ class NameValidator implements Validator
 
     @Override
     public Validator childNodeChanged(
-            String name, NodeState before, NodeState after)
-            throws CommitFailedException {
+            String name, NodeState before, NodeState after) {
         return this;
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/NameValidatorProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/NameValidatorProvider.java?rev=1344937&r1=1344936&r2=1344937&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/NameValidatorProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/NameValidatorProvider.java Thu May 31 23:18:10 2012
@@ -16,45 +16,24 @@
  */
 package org.apache.jackrabbit.oak.plugins.name;
 
-import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
 import org.apache.jackrabbit.oak.spi.commit.Validator;
 import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
-import java.util.HashSet;
-import java.util.Set;
-
+/**
+ * Validator service that checks that all node and property names as well
+ * as any name values are syntactically valid and that any namespace prefixes
+ * are properly registered.
+ */
+@Component
+@Service(ValidatorProvider.class)
 public class NameValidatorProvider implements ValidatorProvider {
 
     @Override
     public Validator getRootValidator(NodeState before, NodeState after) {
-        Set<String> prefixes = new HashSet<String>();
-
-        // FIXME don't hardcode these here but fetch them from the ns registry
-        // Default JCR prefixes are always available
-        prefixes.add("jcr");
-        prefixes.add("nt");
-        prefixes.add("mix");
-        prefixes.add("sv");
-
-        // Jackrabbit 2.x prefixes are always available
-        prefixes.add("rep");
-
-        prefixes.add("tst");
-        prefixes.add("test");
-
-        // Find any extra prefixes from /jcr:system/jcr:namespaces
-        NodeState system = after.getChildNode("jcr:system");
-        if (system != null) {
-            NodeState registry = system.getChildNode("jcr:namespaces");
-            if (registry != null) {
-                for (PropertyState property : registry.getProperties()) {
-                    prefixes.add(property.getName());
-                }
-            }
-        }
-
-        return new NameValidator(prefixes);
+        return new NameValidator(Namespaces.getNamespaceMap(after).keySet());
     }
 
 }

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/Namespaces.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/Namespaces.java?rev=1344937&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/Namespaces.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/name/Namespaces.java Thu May 31 23:18:10 2012
@@ -0,0 +1,97 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.jackrabbit.oak.plugins.name;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.PropertyType;
+
+import org.apache.jackrabbit.oak.api.CoreValue;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+/**
+ * Internal static utility class for managing the persisted namespace registry.
+ */
+class Namespaces {
+
+    private static final Map<String, String> defaults =
+            new HashMap<String, String>();
+
+    static {
+        // Standard namespace specified by JCR (default one not included)
+        defaults.put("", "");
+        defaults.put("jcr", "http://www.jcp.org/jcr/1.0");
+        defaults.put("nt",  "http://www.jcp.org/jcr/nt/1.0");
+        defaults.put("mix", "http://www.jcp.org/jcr/mix/1.0");
+        defaults.put("xml", "http://www.w3.org/XML/1998/namespace");
+
+        // Namespace included in Jackrabbit 2.x
+        defaults.put("sv", "http://www.jcp.org/jcr/sv/1.0");
+
+        // TODO: see OAK-74
+        defaults.put("rep", "internal");
+
+        // test prefix TODO: remove again.
+        defaults.put("test", "http://apache.jackrabbit.org/oak/0.1");
+    }
+
+    public static Map<String, String> getNamespaceMap(NodeState root) {
+        Map<String, String> map = new HashMap<String, String>(defaults);
+
+        NodeState system = root.getChildNode("jcr:system");
+        if (system != null) {
+            NodeState namespaces = system.getChildNode("jcr:namespaces");
+            if (namespaces != null) {
+                for (PropertyState property : namespaces.getProperties()) {
+                    String prefix = property.getName();
+                    if (!property.isArray() && isValidPrefix(prefix)) {
+                        CoreValue value = property.getValue();
+                        if (value.getType() == PropertyType.STRING) {
+                            map.put(prefix, value.getString());
+                        }
+                    }
+                }
+            }
+        }
+
+        return map;
+    }
+
+    public static boolean isValidPrefix(String prefix) {
+        // TODO: Other prefix rules?
+        return prefix.length() > 0 && prefix.indexOf(':') == -1;
+    }
+
+    public static boolean isValidLocalName(String local) {
+        if (local.length() == 0 || ".".equals(local) || "..".equals(local)) {
+            return false;
+        }
+
+        for (int i = 0; i < local.length(); i++) {
+            char ch = local.charAt(i);
+            if ("/:[]|*".indexOf(ch) != -1) { // TODO: XMLChar check
+                return false;
+            }
+        }
+
+        // TODO: Other name rules?
+        return true;
+    }
+
+}

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/name/NameValidatorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/name/NameValidatorTest.java?rev=1344937&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/name/NameValidatorTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/name/NameValidatorTest.java Thu May 31 23:18:10 2012
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.plugins.name;
+
+import java.util.Collections;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState;
+import org.apache.jackrabbit.oak.spi.commit.Validator;
+import org.junit.Test;
+
+public class NameValidatorTest {
+
+    private final Validator validator =
+            new NameValidator(Collections.singleton("valid"));
+
+    @Test(expected = CommitFailedException.class)
+    public void testCurrentPath() throws CommitFailedException {
+        validator.childNodeAdded(".", MemoryNodeState.EMPTY_NODE);
+    }
+
+    @Test(expected = CommitFailedException.class)
+    public void testParentPath() throws CommitFailedException {
+        validator.childNodeAdded(".", MemoryNodeState.EMPTY_NODE);
+    }
+
+    @Test(expected = CommitFailedException.class)
+    public void testEmptyPrefix() throws CommitFailedException {
+        validator.childNodeAdded(":name", MemoryNodeState.EMPTY_NODE);
+    }
+
+    @Test(expected = CommitFailedException.class)
+    public void testInvalidPrefix() throws CommitFailedException {
+        validator.childNodeAdded("invalid:name", MemoryNodeState.EMPTY_NODE);
+    }
+
+    @Test
+    public void testValidPrefix() throws CommitFailedException {
+        validator.childNodeAdded("valid:name", MemoryNodeState.EMPTY_NODE);
+    }
+
+    @Test(expected = CommitFailedException.class)
+    public void testSlashName() throws CommitFailedException {
+        validator.childNodeAdded("invalid/name", MemoryNodeState.EMPTY_NODE);
+    }
+
+    @Test(expected = CommitFailedException.class)
+    public void testIndexInName() throws CommitFailedException {
+        validator.childNodeAdded("name[1]", MemoryNodeState.EMPTY_NODE);
+    }
+
+    @Test
+    public void testValidName() throws CommitFailedException {
+        validator.childNodeAdded("name", MemoryNodeState.EMPTY_NODE);
+    }
+
+    @Test
+    public void testDeleted() throws CommitFailedException {
+        validator.childNodeDeleted(".", MemoryNodeState.EMPTY_NODE);
+        validator.childNodeDeleted("..", MemoryNodeState.EMPTY_NODE);
+        validator.childNodeDeleted("valid:name", MemoryNodeState.EMPTY_NODE);
+        validator.childNodeDeleted("invalid:name", MemoryNodeState.EMPTY_NODE);
+        validator.childNodeDeleted("invalid/name", MemoryNodeState.EMPTY_NODE);
+    }
+
+}