java.net.URI.relativize doesn't work with JAR URIs
java, uri
Solution
I've been mildly annoyed by this too. The answer has nothing do to with the semantics of JAR files—it has to do with the syntax of `jar:` URIs. To be "relativized," a URI has to be hierarchical and not opaque. You will note from the JavaDoc for java.net.URI that:
At the highest level a URI reference (hereinafter simply "URI") in string form has the syntax
[scheme:]scheme-specific-part[#fragment]
...
An opaque URI is an absolute URI whose scheme-specific part does not begin with a slash character ('/'). Opaque URIs are not subject to further parsing.
...
A hierarchical URI is subject to further parsing according to the syntax
[scheme:][//authority][path][?query][#fragment]
A JAR URI like `jar:file:///home/me/foo.jar!/conf/` is parsed as:
- scheme = `jar`
- scheme-specific-part = `file:///home/me/foo.jar!/conf/`
- fragment = (none)
Because the scheme-specific-part does not begin with "`/`," it cannot be considered a hierarchical URI. The URI class does not treat `jar:` (or any) URIs specially, so it cannot recognize that the `file://` part is a nested URI that is hierarchical.
Since `jar:` URIs are opaque and not hierarchical, they are subject to the behavior documented for URI#relativize():
The relativization of the given URI against this URI is computed as follows:
- If either this URI or the given URI are opaque, [...], then the given URI is returned.
EDIT: Left out a crucial part about opaque URIs.
Problem
I have two URI objects. One is pointing to a folder in a JAR file, and another is pointing to a file in the same JAR file. The file is in a subfolder of the directory specified by the first URI. I like to create a relative URI so the resulting URI only containing the relative path to the file in the JAR. Folder URI ``` jar:file:/C:/Users/inagy/.m2/repository/hu/inagy/my-config-artifact/2.0-SNAPSHOT/my-config-artifact-2.0-SNAPSHOT.jar!/conf/ ``` Resource URI ``` jar:file:/C:/Users/inagy/.m2/repository/hu/inagy/my-config-artifact/2.0-SNAPSHOT/my-config-artifact-2.0-SNAPSHOT.jar!/conf/somesubpath/someconfig.xml ``` After calling `folderUri.relativize(resourceURI)` i'm expecting the following URI as a result: ``` somesubpath/someconfig.xml ``` However i get resourceURI back which mean according to the URI class's Javadoc that the JDK code find this two paths non relative to each other. Is this a bug or i'm doing something wrong?