I always thought that URL
s can be composed via this constructor, and with something like
new URL(new URL("file:/foo/bar/"), "images/a.png")
I get
file:/foo/bar/images/a.png
as expected.1 However, from OneJar I obtain a strange looking URL and the result of
new URL(new URL("onejar:foo.bar"), "images.a.png")
is simply
onejar:images.a.png
The parent path gets simply dropped. I tried to prefix or suffix the parts with /
or .
, but nothing changes. Update: This isn't true, see below.
Is this a bug or am I missing something? Do I have to do it via strings (which feels pretty hacky).
I see that the trailing slash indeed helps. For whatever reason, onejar
uses dots as delimiters, but it seems to accept slashes as well. So I can take the original URL like onejar:foo.bar
convert to a string, append /
, and convert back to URL. The result can be then composed via the constructor mentioned above, so it seems to be the right way.
1 unless I forget the trailing slash, which I do very often, but this is a different story.
So, well, apart from the fact that the constructor you want to invoke uses a URL
object as first parameter instead of a String
, I guess the behavior you see may have something to do with the fact that file
scheme URI are hierarchical, but if you don't provide any hierarchy symbol (i.e. the slash) the constructor gives priority to the spec part (i.e. the second parameter) over the context part (i.e. the first parameter).
For example, when you forget the trailing slash on file:/foo/bar
, what you really are indicating is file bar
in directory foo
. If you pass along a relative path such as images/a.png
, the constructor combines the two as best as it can: of course it cannot append a relative path to what it believes to be a file, giving as a result file:/foo/bar/images/a.png
, so it just replaces the bar
file with the file you passed as second parameter, giving as a result file:/foo/images/a.png
.
The same applies to your second example: file:foo.bar
indicates a foo.bar
file, but when you pass the second parameter representing an images.a.png
file, the substitution happens as explained in the preceding example, giving a result of file:images.a.png
. This happens, I believe, because you are missing hierarchy symbols (i.e. slashes) where you need to have them in order to obtain the desired result.
This is really a guess rather than an ol' good informed answer.
However, when you type:
URL url = new URL(new URL("file:foo.bar/"), "images.a.png");
System.out.println(url);
appending a /
suffix to one of the parts, as you say you had, the result indeed changes, contrary to what you affirm, giving the following result:
file:foo.bar/images.a.png
which appears to be consistent with my guesses.
Still, since I never used OneJar, from your question is unclear what your input really is, and what you want to obtain as a result.