public static boolean hasPrefix(String path, String prefix) throws InvalidPathException {
    // normalize path and prefix(e.g. "/a/b/../c" -> "/a/c", "/a/b/" --> "/a/b")
    path = cleanPath(path);
    prefix = cleanPath(prefix);

    if (prefix.equals("/")) {
      return true;
    }
    if (!path.startsWith(prefix)) {
      return false;
    }
    return path.length() == prefix.length()  // path == prefix
        // Include cases like `prefix=/a/b/, path=/a/b/c/`
        || prefix.endsWith("/")
        // Exclude cases like `prefix=/a/b/c, path=/a/b/ccc`
        || path.charAt(prefix.length()) == '/';
  }
@Test
  public void hasPrefix() throws InvalidPathException {
    assertTrue(PathUtils.hasPrefix("/", "/"));
    assertTrue(PathUtils.hasPrefix("/a/b/c", "/"));
    assertTrue(PathUtils.hasPrefix("/a", "/a"));
    assertTrue(PathUtils.hasPrefix("/a/b/c/", "/a/b/c"));
    assertTrue(PathUtils.hasPrefix("/a", "/a/"));
    assertTrue(PathUtils.hasPrefix("/a/b/c", "/a"));
    assertTrue(PathUtils.hasPrefix("/a/b/c", "/a/b"));
    assertTrue(PathUtils.hasPrefix("/a/b/c", "/a/b/c"));
    assertTrue(PathUtils.hasPrefix("/a/b/c/d/e", "/a/b/"));
    assertTrue(PathUtils.hasPrefix("/a/b/./c/../d", "/a/../a/b/d"));
    assertFalse(PathUtils.hasPrefix("/a/b/../c", "/a/b"));
    assertFalse(PathUtils.hasPrefix("/", "/a"));
    assertFalse(PathUtils.hasPrefix("/", "/a/b/c"));
    assertFalse(PathUtils.hasPrefix("/a", "/a/b/c"));
    assertFalse(PathUtils.hasPrefix("/a/b", "/a/b/c"));
    assertFalse(PathUtils.hasPrefix("/a/b/c", "/aa"));
    assertFalse(PathUtils.hasPrefix("/a/b/c", "/a/bb"));
    assertFalse(PathUtils.hasPrefix("/a/b/c", "/a/b/cc"));
    assertFalse(PathUtils.hasPrefix("/aa/b/c", "/a"));
    assertFalse(PathUtils.hasPrefix("/a/bb/c", "/a/b"));
    assertFalse(PathUtils.hasPrefix("/a/b/cc", "/a/b/c"));
  }