Question

I always thought that URLs 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).

UPDATE:

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.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top