You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2011/07/04 12:37:53 UTC

svn commit: r1142612 - in /jackrabbit/sandbox/microkernel/src: main/java/org/apache/jackrabbit/mk/util/PathUtils.java test/java/org/apache/jackrabbit/mk/PathTest.java

Author: thomasm
Date: Mon Jul  4 10:37:53 2011
New Revision: 1142612

URL: http://svn.apache.org/viewvc?rev=1142612&view=rev
Log:
Improve PathUtils.

Modified:
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/util/PathUtils.java
    jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/PathTest.java

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/util/PathUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/util/PathUtils.java?rev=1142612&r1=1142611&r2=1142612&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/util/PathUtils.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/util/PathUtils.java Mon Jul  4 10:37:53 2011
@@ -27,19 +27,43 @@ public class PathUtils {
         // utility class
     }
 
+    /**
+     * Whether the path is the root path ("/").
+     *
+     * @param path the path
+     * @return whether this is the root
+     */
     public static boolean denotesRoot(String path) {
         return "/".equals(path);
     }
 
+    /**
+     * Whether the path is absolute (starts with a slash) or not.
+     *
+     * @param path the path
+     * @return true if it starts with a slash
+     */
     public static boolean isAbsolute(String path) {
         return path.startsWith("/");
     }
 
+    /**
+     * Get the parent of a path. The parent of the root path ("/") is the root
+     * path. Only minimal validation takes place within this function, so when
+     * the parameter is an illegal path, the the result of this method is
+     * undefined.
+     *
+     * @param path the path
+     * @return the parent path
+     */
     public static String getParentPath(String path) {
-        int end = path.length() - 1;
-        while (end >= 0 && path.charAt(end) == '/') {
-            end--;
+        if (path.equals("/") || path.length() == 0) {
+            return path;
+        }
+        if (path.endsWith("/")) {
+            throw new IllegalArgumentException(path + " (ends with '/')");
         }
+        int end = path.length() - 1;
         int pos = getPreviousSlash(path, end);
         if (pos > 0) {
             return path.substring(0, pos);
@@ -50,19 +74,20 @@ public class PathUtils {
     }
 
     /**
-     * Get the last element of the path
+     * Get the last element of the (absolute or relative) path. The name of the
+     * root node ("/") and the name of the empty path ("") is the empty path.
      *
      * @param path the complete path
      * @return the last element
      */
     public static String getName(String path) {
-        int end = path.length() - 1;
-        while (end >= 0 && path.charAt(end) == '/') {
-            end--;
-            if (end < 0) {
-                return "";
-            }
+        if (path.equals("/") || path.length() == 0) {
+            return "";
         }
+        if (path.endsWith("/")) {
+            throw new IllegalArgumentException(path + " (ends with '/')");
+        }
+        int end = path.length() - 1;
         int pos = getPreviousSlash(path, end);
         if (pos != -1) {
             return path.substring(pos + 1, end + 1);
@@ -70,18 +95,28 @@ public class PathUtils {
         return path;
     }
 
+    /**
+     * Calculate the number of elements in the path.
+     * The root path has zero elements.
+     *
+     * @param path the path
+     * @return the number of elements
+     */
     public static int getDepth(String path) {
-        if (PathUtils.denotesRoot(path)) {
-            return 0;
-        }
-        int count = 0, i = 0;
+        int count = 1, i = 0;
         if (path.startsWith("/")) {
+            if (PathUtils.denotesRoot(path)) {
+                return 0;
+            }
             i++;
         }
-        for (; i > 0; i = getNextSlash(path, i) + 1) {
+        while (true) {
+            i = getNextSlash(path, i) + 1;
+            if (i == 0) {
+                return count;
+            }
             count++;
         }
-        return count;
     }
 
     public static String[] split(String path) {
@@ -113,18 +148,20 @@ public class PathUtils {
         return array;
     }
 
-    public static String concat(String parentPath, String nameOrRelativePath) {
-        if (nameOrRelativePath.startsWith("/")) {
+    public static String concat(String parentPath, String relativePath) {
+        if (relativePath.startsWith("/")) {
             throw new IllegalArgumentException("can't append absolute path");
+        } else if (relativePath.length() == 0) {
+            return parentPath;
         }
         int parentLen = parentPath.length();
         StringBuilder buff = new StringBuilder(
-                parentLen + 1 + nameOrRelativePath.length());
+                parentLen + 1 + relativePath.length());
         buff.append(parentPath);
         if (parentLen > 0 && !parentPath.endsWith("/")) {
             buff.append('/');
         }
-        buff.append(nameOrRelativePath);
+        buff.append(relativePath);
         return buff.toString();
     }
 
@@ -196,4 +233,49 @@ public class PathUtils {
         return index;
     }
 
+    /**
+     * Check if the path is valid, and throw an IllegalArgumentException if not.
+     * A valid path is absolute (starts with a '/') or relative (doesn't start
+     * with '/'), and contain one or more elements. A path may not end with '/',
+     * except for the root path. Elements itself must be at least one character
+     * long. Within an element, there may be one or more section starting with
+     * '{' and ending with '}' that can contain any character (including '/',
+     * but not '{' or '}').
+     *
+     * @param path the path
+     */
+    public static void validate(String path) {
+        if ("/".equals(path) || path.length() == 0) {
+            return;
+        } else if (path.endsWith("/")) {
+            throw new IllegalArgumentException(path + " (ends with '/')");
+        }
+        char last = 0;
+        for (int index = 0, len = path.length(); index < len; index++) {
+            char c = path.charAt(index);
+            if (c == '/') {
+                if (last == '/') {
+                    throw new IllegalArgumentException(path + " (contains '//')");
+                }
+            }
+            if (c == '{') {
+                while (true) {
+                    index++;
+                    if (index >= len) {
+                        throw new IllegalArgumentException(path + " (missing '{')");
+                    }
+                    char x = path.charAt(index);
+                    if (x == '{') {
+                        throw new IllegalArgumentException(path +" (unmatched '{')");
+                    } if (x == '}') {
+                        break;
+                    }
+                }
+            } else if (c == '}') {
+                throw new IllegalArgumentException(path + " (missing '{')");
+            }
+            last = c;
+        }
+    }
+
 }

Modified: jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/PathTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/PathTest.java?rev=1142612&r1=1142611&r2=1142612&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/PathTest.java (original)
+++ jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/PathTest.java Mon Jul  4 10:37:53 2011
@@ -37,6 +37,20 @@ public class PathTest extends TestCase {
             // expected
         }
 
+        try {
+            PathUtils.getParentPath("invalid/path/");
+            fail();
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            PathUtils.getName("invalid/path/");
+            fail();
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
         test("parent", "child");
 
         test("{/}parent", "child");
@@ -48,20 +62,53 @@ public class PathTest extends TestCase {
         test("parent", "{x/y}child");
     }
 
+    public void testValidate() {
+        for (String invalid : new String[] {
+                "//",
+                "//test",
+                "/test/",
+                "test/",
+                "/test//",
+                "/test//test",
+                "{{}",
+                "{}}",
+                "{test",
+                "}test"
+        }) {
+            try {
+                PathUtils.validate(invalid);
+                fail(invalid);
+            } catch (IllegalArgumentException e) {
+                // expected
+            }
+        }
+        for (String valid : new String[] {
+                "",
+                "/",
+                "test",
+                "test/test",
+                "/test",
+                "/test/test",
+                "{}",
+                "{}/{}",
+                "/{}",
+                "/{}/{}",
+                "/{/}",
+        }) {
+            PathUtils.validate(valid);
+        }
+    }
+
     public void testMore() {
         String[] paths = {
             "",
             "/",
-            "/foo",
-            "/foo/",
-            "/foo//",
-            "/foo///",
             "foo",
             "/foo",
+            "foo/bar",
             "/foo/bar",
-            "/foo/bar/",
-            "/foo/bar//",
-            "foo//bar"
+            "foo/bar/baz",
+            "/foo/bar/baz",
         };
 
         for (String path : paths) {
@@ -69,12 +116,9 @@ public class PathTest extends TestCase {
             String name = PathUtils.getName(path);
             String concat = PathUtils.concat(parent, name);
 
-            System.out.println("(" + path + ")(" + parent + "," + name + ")(" + concat + ")");
-
-            while (path.endsWith("/") && path.length() > 1) {
-                path = path.substring(0, path.length() - 1);
-            }
-            assertEquals(path, concat);
+            assertEquals("original: " + path + " parent: " + parent +
+                    " name: " + name + " concat: " + concat,
+                    path, concat);
         }
     }
 
@@ -111,6 +155,8 @@ public class PathTest extends TestCase {
         assertEquals(0, PathUtils.getDepth("/"));
         assertEquals(1, PathUtils.getDepth("/" + parent));
         assertEquals(2, PathUtils.getDepth("/" + parent + "/" + child));
+        assertEquals(1, PathUtils.getDepth(parent));
+        assertEquals(2, PathUtils.getDepth(parent + "/" + child));
 
         // getName
         assertEquals("", PathUtils.getName("/"));