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);
+ }
+
+}