Can I get an URLConnection for a file within a JAR within a non-exploded WAR?
I have some resource files that are in the classpath of my web application (inside a JAR, if that matters). I know I can access the contents of those resources by calling e.g. SomeClassLoader.getResourceAsStream( "/samples/myscript.txt" )
. I have tested this in the past in both exploded and non-exploded WAR files with success.
However, to integrate with some other existing classes in my app, I need to provide an URLConnection objec开发者_如何学运维t to that file. I tested and confirmed that calling getResource("/samples/myscript.txt").openConnection()
works in exploded WARs (additionaly, debugging revealed that the result is a file:///
URL to the exploded file).
Question: will that method also work on non-exploded ("packaged?") WARs?
(I currently do not have easy access to a server that deploys wars without exploding them, hence why I'm asking instead of outright trying it. Also, some servers (e.g. Jetty, Tomcat -- even with unpackWARs="false"
) allows non-exploded deployments, but behind the scenes they unpack the war, effectively behaving like an exploded deployment -- and, evidently, working correctly. I think the servers that gave me trouble in the past were Websphere and Weblogic).
I don't believe so. To do that, you'd have to use a JarUrlConnection for a JAR URL whose underlying URL was another JAR URL. If i try that, i get:
java.net.MalformedURLException: no !/ in spec
'spec' is what JarUrlConnection calls the path that refers to the file inside the JAR. It seems that for a URL like jar:jar:file:///outer.jar!/inner.jar!/myscript.txt
, it chops off the spec at the first exclamation mark, and then rejects inner.jar!/myscript.txt
as a spec. When really, we'd like it to chop off the spec at the last exclamation path, unwrapping the inner URL (which refers to the outer JAR!) to use as a base. Unfortunate. I can't think of any way round this.
Something to note relative to the operation which is being attempted: An entry within an archive which is itself an entry of an archive has two layers of packaging, and potentially has two layers of compression. Any attempt to access the data of the entry while leaving the intermediate archive still as an entry within the outermost archive would have to decompress the intermediate archive before retrieving the entry.
To access a doubly nested archive two basic techniques and one advanced technique are used: First, most often, the intermediate archive is extracted to a temporary file. Second, occasionally, one can stream through the entries of the intermediate archive, but this is very slow and is not advised except in very limited circumstances. Third, an advanced technique would be to not compress then intermediate archive, then create an offset file with pointers to the region of the outermost archive to the intermediate archive. I'm not sure this is done anywhere, but it would avoid the overhead of the other two techniques.
In any case, there are considerable extra steps necessary to access the doubly nested entry, which are a bit much for a simple protocol handler to do.
Note also that this is a common problem for JavaEE application archives, which are defined as multi-layer archives: EAR -> ( JAR | WAR | RAR ), WAR -> JAR, and RAR -> JAR. JavaEE creates three tiers of nested archives.
精彩评论