diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/JcrPathParser.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/JcrPathParser.java index 54c1c9e..76d0e5e 100644 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/JcrPathParser.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/JcrPathParser.java @@ -128,6 +128,11 @@ public final class JcrPathParser { listener.error('\'' + jcrPath + "' is not a valid path. '" + c + "' not a valid name character."); return false; + } else if (state == STATE_URI && c == EOF) { + // we reached EOF without finding the closing curly brace '}' + // skip the curly brace and parse again + state = STATE_PREFIX; + pos = lastPos + 1; } break; diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImplTest.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImplTest.java index 22c4800..697fa61 100644 --- a/oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImplTest.java +++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImplTest.java @@ -199,6 +199,25 @@ public class NamePathMapperImplTest { } @Test + public void testBracketsInPaths() throws Exception { + String[] paths = { + "/parent/childB1", + "/parent/}childB2", + "/parent/{childB3}", + "/parent/sub/childB4", + "/parent/sub/}childB5", + "/parent/sub/{childB6}", + "/parent/sub/{childB7", + "/parent/{childA1", + "/parent/{{childA2" + }; + + for (String path : paths) { + assertEquals(path, npMapper.getOakPath(path)); + } + } + + @Test public void testWhitespace() { String[] paths = new String[] { " leading", "trailing\n", " ", "\t", diff --git a/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/NamePathTest.java b/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/NamePathTest.java index 2b37fde..5f4cf1f 100644 --- a/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/NamePathTest.java +++ b/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/NamePathTest.java @@ -26,6 +26,7 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; import com.google.common.collect.ImmutableList; +import static junit.framework.TestCase.fail; import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider; import org.junit.After; @@ -208,6 +209,41 @@ public class NamePathTest { session.getNode(n.getPath()); } + @Test + public void testCurlyBrackets() throws RepositoryException { + session.getRootNode().addNode("parent"); + + assertNodeFound(true, + "/parent" + ); + + assertNodeFound(false, + "/parent/childB1", + "/parent/}childB2", + "/parent/{childB3}", + "/parent/sub/childB4", + "/parent/sub/}childB5", + "/parent/sub/{childB6}", + "/parent/sub/{childB7", + "/parent/{childA1", + "/parent/{{childA2" + ); + } + + private void assertNodeFound(boolean expected, String ... paths) { + for(String path : paths) { + try { + session.getNode(path); + if(!expected) { + fail("Expected node to be absent:" + path); + } + } catch(RepositoryException rex) { + if(expected) { + fail("Expected node to be present:" + path); + } + } + } + } private void testPaths(List paths) throws RepositoryException { for (String path : paths) {