PathUtil { public static String toCanonicalPath(String path, boolean removeLastSlash) { if (path == null || path.isEmpty()) { return path; } if (path.charAt(0) == '.') { if (path.length() == 1) { return ""; } char c = path.charAt(1); if (c == '/') { path = path.substring(2); } } int index = -1; do { index = path.indexOf('/', index + 1); char next = index == path.length() - 1 ? 0 : path.charAt(index + 1); if (next == '.' || next == '/') { break; } } while (index != -1); if (index == -1) { if (removeLastSlash) { int start = processRoot(path, NullWriter.INSTANCE); int slashIndex = path.lastIndexOf('/'); return slashIndex != -1 && slashIndex > start ? StringUtils.trimEnd(path, '/') : path; } return path; } String finalPath = path; Supplier<String> canonicalPath = () -> { try { return new File(finalPath).getCanonicalPath(); } catch (IOException ignore) { return toCanonicalPath(finalPath, removeLastSlash); } }; StringBuilder result = new StringBuilder(path.length()); int start = processRoot(path, result); int dots = 0; boolean separator = true; for (int i = start; i < path.length(); ++i) { char c = path.charAt(i); if (c == '/') { if (!separator) { if (!processDots(result, dots, start)) { return canonicalPath.get(); } dots = 0; } separator = true; } else if (c == '.') { if (separator || dots > 0) { ++dots; } else { result.append('.'); } separator = false; } else { if (dots > 0) { StringUtils.repeatSymbol(result, '.', dots); dots = 0; } result.append(c); separator = false; } } if (dots > 0) { if (!processDots(result, dots, start)) { return canonicalPath.get(); } } int lastChar = result.length() - 1; if (removeLastSlash && lastChar >= 0 && result.charAt(lastChar) == '/' && lastChar > start) { result.deleteCharAt(lastChar); } return result.toString(); }  static String toCanonicalPath(String path, boolean removeLastSlash);  }
@Test public void testCanonicalPath() throws Exception { String path = PathUtil.toCanonicalPath("/foo/../bar", false); assertNotNull(path); assertFalse(path.isEmpty()); assertEquals(path, "/bar"); }
@Test public void testRemoveLastSlash() throws Exception { String path = PathUtil.toCanonicalPath("/foo/bar/", true); assertNotNull(path); assertFalse(path.isEmpty()); assertEquals(path, "/foo/bar"); }
@Test public void testEliminationDot() throws Exception { String path = PathUtil.toCanonicalPath("./bar", false); assertNotNull(path); assertFalse(path.isEmpty()); assertEquals(path, "bar"); }
@Test public void testCanonicalPathWithFile() throws Exception { String path = PathUtil.toCanonicalPath("/foo/../bar/pom.xml", false); assertNotNull(path); assertFalse(path.isEmpty()); assertEquals(path, "/bar/pom.xml"); }