You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2010/07/22 16:13:55 UTC

svn commit: r966672 - in /jackrabbit/trunk: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/ jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/co...

Author: stefan
Date: Thu Jul 22 14:13:55 2010
New Revision: 966672

URL: http://svn.apache.org/viewvc?rev=966672&view=rev
Log:
JCR-2675: Node.hasProperty() with relative path can throw ClassCastException

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/PathParserTest.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/JcrPath.java
    jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java?rev=966672&r1=966671&r2=966672&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java Thu Jul 22 14:13:55 2010
@@ -189,6 +189,12 @@ public class NodeImpl extends ItemImpl i
      */
     protected PropertyId resolveRelativePropertyPath(String relPath)
             throws RepositoryException {
+        Path p = resolveRelativePath(relPath);
+        return getPropertyId(p);
+    }
+
+    protected PropertyId resolveRelativePropertyPathOld(String relPath)
+            throws RepositoryException {
         try {
             /**
              * first check if relPath is just a name (in which case we don't
@@ -291,11 +297,55 @@ public class NodeImpl extends ItemImpl i
         /**
          * build and resolve absolute path
          */
-        p = PathFactoryImpl.getInstance().create(getPrimaryPath(), p, true);
+        try {
+            p = PathFactoryImpl.getInstance().create(getPrimaryPath(), p, true);
+        } catch (RepositoryException re) {
+            // failed to build canonical path
+            return null;
+        }
         return sessionContext.getHierarchyManager().resolveNodePath(p);
     }
 
     /**
+     * Returns the id of the property at <code>p</code> or <code>null</code>
+     * if no node exists at <code>p</code>.
+     * <p/>
+     * Note that access rights are not checked.
+     *
+     * @param p relative path of a (possible) node
+     * @return the id of the node at <code>p</code> or
+     *         <code>null</code> if no node exists at <code>p</code>
+     * @throws RepositoryException if <code>relPath</code> is not a valid
+     *                             relative path
+     */
+    private PropertyId getPropertyId(Path p) throws RepositoryException {
+        if (p.getLength() == 1) {
+            Path.Element pe = p.getNameElement();
+            if (pe.denotesName()) {
+                // check if property entry exists
+                NodeState thisState = data.getNodeState();
+                if (pe.getIndex() == Path.INDEX_UNDEFINED
+                        && thisState.hasPropertyName(pe.getName())) {
+                    return new PropertyId(thisState.getNodeId(), pe.getName());
+                } else {
+                    // there's no property with that name
+                    return null;
+                }
+            }
+        }
+        /**
+         * build and resolve absolute path
+         */
+        try {
+            p = PathFactoryImpl.getInstance().create(getPrimaryPath(), p, true);
+        } catch (RepositoryException re) {
+            // failed to build canonical path
+            return null;
+        }
+        return sessionContext.getHierarchyManager().resolvePropertyPath(p);
+    }
+
+    /**
      * Determines if there are pending unsaved changes either on <i>this</i>
      * node or on any node or property in the subtree below it.
      *

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java?rev=966672&r1=966671&r2=966672&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/name/PathFactoryImpl.java Thu Jul 22 14:13:55 2010
@@ -75,7 +75,12 @@ public class PathFactoryImpl implements 
         l.addAll(Arrays.asList(parent.getElements()));
         l.addAll(Arrays.asList(relPath.getElements()));
 
-        Builder pb = new Builder(l);
+        Builder pb;
+        try {
+            pb = new Builder(l);
+        } catch (IllegalArgumentException iae) {
+             throw new RepositoryException(iae.getMessage());
+        }
         Path path = pb.getPath();
         if (normalize) {
             return path.getNormalizedPath();
@@ -92,7 +97,12 @@ public class PathFactoryImpl implements 
         elements.addAll(Arrays.asList(parent.getElements()));
         elements.add(createElement(name));
 
-        Builder pb = new Builder(elements);
+        Builder pb;
+        try {
+            pb = new Builder(elements);
+        } catch (IllegalArgumentException iae) {
+             throw new RepositoryException(iae.getMessage());
+        }
         Path path = pb.getPath();
         if (normalize) {
             return path.getNormalizedPath();
@@ -109,7 +119,12 @@ public class PathFactoryImpl implements 
         elements.addAll(Arrays.asList(parent.getElements()));
         elements.add(createElement(name, index));
 
-        Builder pb = new Builder(elements);
+        Builder pb;
+        try {
+            pb = new Builder(elements);
+        } catch (IllegalArgumentException iae) {
+             throw new RepositoryException(iae.getMessage());
+        }
         Path path = pb.getPath();
         if (normalize) {
             return path.getNormalizedPath();
@@ -366,18 +381,14 @@ public class PathFactoryImpl implements 
                         "Identifier-based path cannot be normalized: " + this);
             }
             LinkedList<Path.Element> queue = new LinkedList<Path.Element>();
-            Path.Element last = PARENT_ELEMENT;
             for (Element elem : elements) {
-                if (elem.denotesParent() && !last.denotesParent()) {
-                    queue.removeLast();
-                    if (queue.isEmpty()) {
-                        last = PARENT_ELEMENT;
-                    } else {
-                        last = queue.getLast();
+                if (elem.denotesParent() && !queue.isEmpty() && !queue.getLast().denotesParent()) {
+                    if (queue.getLast().denotesRoot()) {
+                        throw new RepositoryException("Path cannot be normalized: " + this);
                     }
+                    queue.removeLast();
                 } else if (!elem.denotesCurrent()) {
-                    last = elem;
-                    queue.add(last);
+                    queue.add(elem);
                 }
             }
             if (queue.isEmpty()) {
@@ -1047,9 +1058,9 @@ public class PathFactoryImpl implements 
          *
          * @param elemList
          * @throws IllegalArgumentException if the given elements array is null
-         * or has a length less than 1;
+         * or has a zero length or would otherwise constitute an invalid path
          */
-        private Builder(List<Path.Element> elemList) {
+        private Builder(List<Path.Element> elemList) throws IllegalArgumentException {
             this(elemList.toArray(new Path.Element[elemList.size()]));
         }
 
@@ -1059,9 +1070,9 @@ public class PathFactoryImpl implements 
          *
          * @param elements
          * @throws IllegalArgumentException if the given elements array is null
-         * or has a length less than 1;
+         * or has a zero length or would otherwise constitute an invalid path
          */
-        private Builder(Path.Element[] elements) {
+        private Builder(Path.Element[] elements) throws IllegalArgumentException {
             if (elements == null || elements.length == 0) {
                 throw new IllegalArgumentException("Cannot build path from null or 0 elements.");
             }
@@ -1072,12 +1083,11 @@ public class PathFactoryImpl implements 
             } else {
                 boolean absolute = elements[0].denotesRoot();
                 isNormalized = true;
-                int parents = 0;
-                int named = 0;
+                int depth = 0;
                 for (int i = 0; i < elements.length; i++) {
                     Path.Element elem = elements[i];
                     if (elem.denotesName()) {
-                        named++;
+                        depth++;
                     } else if (elem.denotesRoot()) {
                         if (i > 0) {
                             throw new IllegalArgumentException("Invalid path: The root element may only occur at the beginning.");
@@ -1085,17 +1095,17 @@ public class PathFactoryImpl implements 
                     } else if (elem.denotesIdentifier()) {
                         throw new IllegalArgumentException("Invalid path: The identifier element may only occur at the beginning of a single element path.");
                     } else  if (elem.denotesParent()) {
-                        parents++;
-                        if (absolute || named > 0) {
+                        depth--;
+                        if (absolute && depth < 0) {
+                            throw new IllegalArgumentException("Invalid path: Too many parent elements.");
+                        }
+                        if (absolute || (i > 0 && elements[i - 1].denotesName())) {
                             isNormalized = false;
                         }
                     } else /* current element */ {
                         isNormalized = false;
                     }
                 }
-                if (absolute && parents > named) {
-                    throw new IllegalArgumentException("Invalid path: Too many parent elements.");
-                }
             }
         }
 

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/PathParserTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/PathParserTest.java?rev=966672&r1=966671&r2=966672&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/PathParserTest.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/conversion/PathParserTest.java Thu Jul 22 14:13:55 2010
@@ -194,7 +194,7 @@ public class PathParserTest extends Test
 
         paths.clear();
 
-        // not canonical paths
+        // non-canonical paths
         paths.add(PathParser.parse("/foo/..", resolver, factory));
         paths.add(PathParser.parse("/foo/.", resolver, factory));
         paths.add(PathParser.parse("/foo/../bar", resolver, factory));
@@ -202,7 +202,6 @@ public class PathParserTest extends Test
         paths.add(PathParser.parse("./foo", resolver, factory));
         paths.add(PathParser.parse(".", resolver, factory));
         paths.add(PathParser.parse("/foo/..", resolver, factory));
-        paths.add(PathParser.parse("/../foo/.", resolver, factory));
 
         for (Iterator it = paths.iterator(); it.hasNext(); ) {
             Path path = (Path) it.next();

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/JcrPath.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/JcrPath.java?rev=966672&r1=966671&r2=966672&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/JcrPath.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/spi/commons/name/JcrPath.java Thu Jul 22 14:13:55 2010
@@ -77,6 +77,7 @@ public final class JcrPath {
         list.add(new JcrPath("prefix:name[2]foo/prefix:name[2]"));
         list.add(new JcrPath("/..", "/..", 0));
         list.add(new JcrPath("/a/b/../../..", "/a/b/../../..", 0));
+        list.add(new JcrPath("/a/b/../../../c", "/a/b/../../../c", 0));
 
         list.add(new JcrPath("/prefix:*name"));
         list.add(new JcrPath("/prefix:n*ame"));
@@ -95,7 +96,7 @@ public final class JcrPath {
         list.add(new JcrPath("../../a/b", "../../a/b", NOR|VAL));
         list.add(new JcrPath("../a", "../a",NOR|VAL));        
 
-        // not normalized paths
+        // non-normalized paths
         list.add(new JcrPath("/a/../b", "/b", VAL));
         list.add(new JcrPath("/a/../b/./c/d/..", "/b/c", VAL));
         list.add(new JcrPath("./../.", "..", VAL));
@@ -106,7 +107,7 @@ public final class JcrPath {
         list.add(new JcrPath("a/../..", "..", VAL));
         list.add(new JcrPath("../../a/.", "../../a", VAL));
 
-        // other non-normalized, relative path
+        // other non-normalized, relative paths
         list.add(new JcrPath("./.", ".", VAL));
         list.add(new JcrPath("./a", "a", VAL));
         list.add(new JcrPath("a/..", ".", VAL));

Modified: jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java?rev=966672&r1=966671&r2=966672&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java (original)
+++ jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/PathFactory.java Thu Jul 22 14:13:55 2010
@@ -34,8 +34,8 @@ public interface PathFactory {
      * @param normalize
      * @return
      * @throws IllegalArgumentException if <code>relPath</code> is absolute.
-     * @throws RepositoryException if <code>normalize</code> is true but the
-     * created Path cannot be normalized.
+     * @throws RepositoryException If the <code>normalized</code> is
+     * <code>true</code> and the resulting path cannot be normalized.
      */
     public Path create(Path parent, Path relPath, boolean normalize) throws IllegalArgumentException, RepositoryException;
 
@@ -48,9 +48,10 @@ public interface PathFactory {
      *
      * @param parent the parent path
      * @param name the name of the new path element.
-     * @param normalize
+     * @param normalize If true the Path is normalized before being returned.
      * @return
-     * @throws RepositoryException
+     * @throws RepositoryException If the <code>normalized</code> is
+     * <code>true</code> and the resulting path cannot be normalized.
      */
     public Path create(Path parent, Name name, boolean normalize) throws RepositoryException;
 
@@ -67,7 +68,7 @@ public interface PathFactory {
      * @throws IllegalArgumentException If the given index is lower than
      * {@link Path#INDEX_UNDEFINED}.
      * @throws RepositoryException If the <code>normalized</code> is
-     * <code>true</code> and the path cannot be normalized.
+     * <code>true</code> and the resulting path cannot be normalized.
      */
     public Path create(Path parent, Name name, int index, boolean normalize) throws IllegalArgumentException, RepositoryException;
 
@@ -99,7 +100,7 @@ public interface PathFactory {
      * @param elements
      * @return the <code>Path</code> created from the elements.
      * @throws IllegalArgumentException If the given elements are <code>null</code>
-     * or have a length of 0.
+     * or have a length of 0 or would otherwise constitute an invalid path.
      */
     public Path create(Path.Element[] elements) throws IllegalArgumentException;