PathTools { public static List<String> getPathStack(String path, boolean evaluateDots) { List<String> pathStack = new ArrayList<>(); boolean wasAbsolute = false; if(!path.isEmpty() && path.charAt(0) =='/') { wasAbsolute = true; } int underflowCounter = 0; StringTokenizer tok = new StringTokenizer(path, "/", false); while(tok.hasMoreTokens()) { String pathElement = tok.nextToken(); if(pathElement.length() != 0) { if(evaluateDots) { if(isDotPattern(pathElement)) { for(int i = 1; i < pathElement.length(); i++) { if(pathStack.isEmpty()) { underflowCounter++; } else { pathStack.remove(pathStack.size()-1); } } } else { pathStack.add(pathElement); } } else { pathStack.add(pathElement); } } } if(underflowCounter > 0) { StringBuilder dots = new StringBuilder(underflowCounter); for(int i = 0; i <= underflowCounter; i++) { dots.append('.'); } pathStack.add(0, dots.toString()); } else if(wasAbsolute) { pathStack.add(0, "/"); } return pathStack; } private  PathTools(); static String resolvePath(String basePath, String path); static String evaluatePath(String path); static String getAbsolutePath(String basePath, String path); static String getParentPath(String path); static String getCompatiblePath(String path); static boolean isDotPattern(String s); static List<String> getPathStack(String path, boolean evaluateDots); static String getPathStackString(List<String> pathStack);  }
@Test public void getPathStack() throws Exception { internalGetPathStack("", true, new String[]{}); internalGetPathStack("/", true, new String[]{"/",}); internalGetPathStack("/foo", true, new String[]{"/", "foo",}); internalGetPathStack("foo", true, new String[]{"foo",}); internalGetPathStack("/foo/bar/../foo", true, new String[]{"/", "foo", "foo",}); internalGetPathStack("/foo/bar/...", true, new String[]{"/",}); internalGetPathStack("/foo/bar/....", true, new String[]{"..",}); internalGetPathStack("/foo/bar/..../foo", true, new String[]{"..", "foo",}); }