S
Simon
How do I safely get a JarURLConnection from a URL that points to a jar file,
and, in particular, if the jar file itself is located inside another jar file?
The following does not (always) work:
URL url = Foo.class.getResource("/my/jar.jar");
URL jarUrl = new Url(url, "jar:" + url + "!/";
JarURLConnection jarConnection =
(JarURLConnection)jarUrl.openConnection();
It works in some cases. If I have a folder "/build/" containing my classes and
resources and run my app, the value of url.toString() is
file:/build/my/jar.jar
and the value of jarUrl.toString() is
jar:file:/build/my/jar.jar!/
With this, everything works fine. However, if I package my app into a jar, say
"dist/app.jar", the value of url.toString() is
jar:file:/dist/app.jar!/my/jar.jar
and jarUrl becomes:
jar:jar:file:/dist/app.jar!/my/jar.jar!/
This seems to confuse JarURLConnection resulting in a MalformedURLException,
complaining "no !/ in spec". Note: The exception does *not* occur in the
constructor of the URL, but in openConnection, more precisely,
at java.net.URL.<init>(URL.java:601)
[...]
at java.net.JarURLConnection.parseSpecs(JarURLConnection.java:161)
Here is the code of JarURLConnection (1.6.0_06-b02):
/*
* REMIND: we don't handle nested JAR URLs
*/
if (separator == -1) {
throw new MalformedURLException("no !/ found in url spec:" + spec);
}
// This is line 161, in which it breaks. It is not the
// throws statement two lines above:
jarFileURL = new URL(spec.substring(0, separator++));
In fact, the comment inside the source seems to answer my question, saying "we
don't handle nested JAR URLs". However, I'm puzzled as to what the "REMIND"
refers to. I haven't found this documented anywhere.
In case it really does not work, what would be a suitable workaround?
My application is this: I have an application which can be extended using
resources bundled into jars. If the user adds another bundle, he enters a URL
(pointing to a jar) and everything works fine (as in the 1st example). My
standard bundle, however, is a jar inside the application jar, and this is where
I want it to be. Of course, I could ship my app as several jars, but that would
mean that I have to figure out some way for the app to locate the standard
bundle on the user's file system, which is something completely transparent to
the application up to now.
Any ideas?
Cheers,
Simon
and, in particular, if the jar file itself is located inside another jar file?
The following does not (always) work:
URL url = Foo.class.getResource("/my/jar.jar");
URL jarUrl = new Url(url, "jar:" + url + "!/";
JarURLConnection jarConnection =
(JarURLConnection)jarUrl.openConnection();
It works in some cases. If I have a folder "/build/" containing my classes and
resources and run my app, the value of url.toString() is
file:/build/my/jar.jar
and the value of jarUrl.toString() is
jar:file:/build/my/jar.jar!/
With this, everything works fine. However, if I package my app into a jar, say
"dist/app.jar", the value of url.toString() is
jar:file:/dist/app.jar!/my/jar.jar
and jarUrl becomes:
jar:jar:file:/dist/app.jar!/my/jar.jar!/
This seems to confuse JarURLConnection resulting in a MalformedURLException,
complaining "no !/ in spec". Note: The exception does *not* occur in the
constructor of the URL, but in openConnection, more precisely,
at java.net.URL.<init>(URL.java:601)
[...]
at java.net.JarURLConnection.parseSpecs(JarURLConnection.java:161)
Here is the code of JarURLConnection (1.6.0_06-b02):
/*
* REMIND: we don't handle nested JAR URLs
*/
if (separator == -1) {
throw new MalformedURLException("no !/ found in url spec:" + spec);
}
// This is line 161, in which it breaks. It is not the
// throws statement two lines above:
jarFileURL = new URL(spec.substring(0, separator++));
In fact, the comment inside the source seems to answer my question, saying "we
don't handle nested JAR URLs". However, I'm puzzled as to what the "REMIND"
refers to. I haven't found this documented anywhere.
In case it really does not work, what would be a suitable workaround?
My application is this: I have an application which can be extended using
resources bundled into jars. If the user adds another bundle, he enters a URL
(pointing to a jar) and everything works fine (as in the 1st example). My
standard bundle, however, is a jar inside the application jar, and this is where
I want it to be. Of course, I could ship my app as several jars, but that would
mean that I have to figure out some way for the app to locate the standard
bundle on the user's file system, which is something completely transparent to
the application up to now.
Any ideas?
Cheers,
Simon