Index: oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImplTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>MacRoman =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImplTest.java (revision 1336304) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImplTest.java (revision ) @@ -63,6 +63,28 @@ "{http://www.jcp.org/jcr/nt/1.0}unstructured")); assertEquals("foobar/oak-jcr:content", npMapper.getOakPath( "foobar/{http://www.jcp.org/jcr/1.0}content")); + assertEquals("foobar", npMapper.getOakPath( + "foobar/{http://www.jcp.org/jcr/1.0}content/..")); + assertEquals("", npMapper.getOakPath( + "foobar/{http://www.jcp.org/jcr/1.0}content/../..")); + assertEquals("..", npMapper.getOakPath( + "foobar/{http://www.jcp.org/jcr/1.0}content/../../..")); + assertEquals("../..", npMapper.getOakPath( + "foobar/{http://www.jcp.org/jcr/1.0}content/../../../..")); + assertEquals("oak-jcr:content", npMapper.getOakPath( + "foobar/../{http://www.jcp.org/jcr/1.0}content")); + assertEquals("../oak-jcr:content", npMapper.getOakPath( + "foobar/../../{http://www.jcp.org/jcr/1.0}content")); + assertEquals("..", npMapper.getOakPath("..")); + assertEquals("", npMapper.getOakPath(".")); + assertEquals("foobar/oak-jcr:content", npMapper.getOakPath( + "foobar/{http://www.jcp.org/jcr/1.0}content/.")); + assertEquals("foobar/oak-jcr:content", npMapper.getOakPath( + "foobar/{http://www.jcp.org/jcr/1.0}content/./.")); + assertEquals("foobar/oak-jcr:content", npMapper.getOakPath( + "foobar/./{http://www.jcp.org/jcr/1.0}content")); + assertEquals("oak-jcr:content", npMapper.getOakPath( + "foobar/./../{http://www.jcp.org/jcr/1.0}content")); } @Test @@ -71,6 +93,7 @@ assertEquals("/jcr-foo:bar/jcr-quu:qux", npMapper.getJcrPath("/foo:bar/quu:qux")); assertEquals("jcr-foo:bar", npMapper.getJcrPath("foo:bar")); + assertEquals(".", npMapper.getJcrPath("")); try { npMapper.getJcrPath("{http://www.jcp.org/jcr/nt/1.0}unstructured"); Index: oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/JcrPathParser.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>MacRoman =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/JcrPathParser.java (revision 1336304) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/JcrPathParser.java (revision ) @@ -48,14 +48,14 @@ // check for length int len = jcrPath == null ? 0 : jcrPath.length(); - // shortcut + // shortcut for root path if (len == 1 && jcrPath.charAt(0) == '/') { listener.root(); return; } + // short cut for empty path if (len == 0) { - listener.error("empty path"); return; } Index: oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>MacRoman =================================================================== --- oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java (revision 1336304) +++ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java (revision ) @@ -366,8 +366,8 @@ String oakPath = sessionDelegate.getOakPathOrThrowNotFound(relPath); - // TODO: hack - if (".".equals(oakPath)) { + // shortcut + if (oakPath.isEmpty()) { return this; } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImpl.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>MacRoman =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImpl.java (revision 1336304) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapperImpl.java (revision ) @@ -91,9 +91,9 @@ @Override public boolean parent() { - if (elements.isEmpty()) { - parseErrors.append(".. of empty path"); - return false; + if (elements.isEmpty() || "..".equals(elements.get(elements.size() - 1))) { + elements.add(".."); + return true; } elements.remove(elements.size() - 1); return true; @@ -131,6 +131,11 @@ return null; } + // Empty path maps to "" + if (elements.isEmpty()) { + return ""; + } + StringBuilder oakPath = new StringBuilder(); for (String element : elements) { if (element.isEmpty()) { @@ -143,11 +148,6 @@ } } - // empty path: map to "." - if (oakPath.length() == 0) { - return "."; - } - // root path is special-cased early on so it does not need to // be considered here oakPath.deleteCharAt(oakPath.length() - 1); @@ -191,8 +191,9 @@ @Override public boolean parent() { - if (elements.isEmpty()) { - throw new IllegalArgumentException(".. of empty path"); + if (elements.isEmpty() || "..".equals(elements.get(elements.size() - 1))) { + elements.add(".."); + return true; } elements.remove(elements.size() - 1); return true; @@ -221,6 +222,11 @@ JcrPathParser.parse(oakPath, listener); + // empty path: map to "." + if (elements.isEmpty()) { + return "."; + } + StringBuilder jcrPath = new StringBuilder(); for (String element : elements) { if (element.isEmpty()) { @@ -231,11 +237,6 @@ jcrPath.append(element); jcrPath.append('/'); } - } - - // empty path: map to "." - if (jcrPath.length() == 0) { - return "."; } jcrPath.deleteCharAt(jcrPath.length() - 1);