Apache URIUtils should work. If you do not want to use an external library, here is a simple implementation of a method that should correctly resolve relative URIs for the case where java.net.URI
cannot handle (i.e., where the base URI path is not a prefix of the child URI path).
public static URI relativize(URI base, URI child) { // Normalize paths to remove . and .. segments base = base.normalize(); child = child.normalize(); // Split paths into segments String[] bParts = base.getPath().split("\\/"); String[] cParts = child.getPath().split("\\/"); // Discard trailing segment of base path if (bParts.length > 0 && !base.getPath().endsWith("/")) { bParts = Arrays.copyOf(bParts, bParts.length - 1); } // Remove common prefix segments int i = 0; while (i < bParts.length && i < cParts.length && bParts[i].equals(cParts[i])) { i++; } // Construct the relative path StringBuilder sb = new StringBuilder(); for (int j = 0; j < (bParts.length - i); j++) { sb.append("../"); } for (int j = i; j < cParts.length; j++) { if (j != i) { sb.append("/"); } sb.append(cParts[j]); } return URI.create(sb.toString()); }
Note that this does not guarantee that the base and the child have the same scheme and authority - you will have to add this if you want him to handle the general case. This may not work against all boundary cases, but it works against you.
Alex source share