- MyApp.jar
- /META-INF
- MANIFEST.MF
- Hello.jar
- /myapp/example
- Hello.class
- Hello.properties
- /myapp/example
- /META-INF
といった構成で、MyApp.jar内のHello.jarが持っているHello.classとかpropertiesを読み出したい。
コード
出力例
./build/libs/MyApp.jar - example.jar -- myapp/ 0 0x00000000 | | -- myapp/example/ 0 0x00000000 | | -- myapp/example/Hello.class 733 0x00000000 | CA FE BA BE 00 00 00 34 | .......4 ...... -- myapp/example/Hello.properties 19 0x00000000 | 6D 65 73 73 61 67 65 3D | message= ......
わかったこと
コード中に書いてないけども、URLからopenStreamはできなかった。
Jarは new URL("jar:file://..../MyApp.jar!/example.jar") とすると、getContentでストリームが取れたりするけども、 new URL("jar:file://..../MyApp.jar!/example.jar!/myapp/example/Hello.class") といった感じにJarが入れ子になっているとダメ。
パッと見るとJarEntryからデータを取れないようにみえるが、大本のJarFileが持つgetInputStreamに渡せば取ることが出来る。
が、Jarの中のJarだとJarFileのインスタンスが得られないので困った。(JarEntryが示すファイルがJarファイル以外もあるのだから当然だけど。)
ファイルのストリームは取り出せるので、それをJarInputStreamに横流しにする。
JarInputStream は getNextJarEntry とすると、JarEntryに合わせてストリームの開始位置が変化する。
なので、JarInputStream#getNextJarEntry したあと、JarInputStream#read すればちゃんとJarEntryが保持する情報を取り出せる。
入れ子になっている場合でも、JarInputStream自体を再度JarInputStreamに横流し・・・といった感じに再帰的にやれば、入れ子になったJarの中身も全て読み出せる。はず。