I have been programming Java for around 15 years. While this is a basic question, it is not due to willful ignorance of the Java APIs or of reading the documentation. To be frank, I am really alarmed that I have encountered a situation where I cannot create a simple jar file with command line tools and open it using the java.util.jar.* API. My detailed step-by-step process is below.
I have used jar -cf to create a simple .jar file for testing. It contains one text file in it. Here is the output from my shell showing how I created it in my Maven project’s src/test/resources directory:
Laird-Nelsons-MacBook-Pro:resources ljnelson$ cat > a.txt
Hello!
Laird-Nelsons-MacBook-Pro:resources ljnelson$ jar cf source.jar .
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
Laird-Nelsons-MacBook-Pro:resources ljnelson$ ls -al
total 16
drwxr-xr-x 4 ljnelson staff 136 Dec 28 13:21 .
drwxr-xr-x 4 ljnelson staff 136 Dec 28 13:01 ..
-rw-r--r-- 1 ljnelson staff 7 Dec 28 13:21 a.txt
-rw-r--r-- 1 ljnelson staff 445 Dec 28 13:21 source.jar
Laird-Nelsons-MacBook-Pro:resources ljnelson$ jar tf source.jar
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
META-INF/
META-INF/MANIFEST.MF
a.txt
(The Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8 is to work around a Mac bug where the default file encoding on the terminal is MacRoman. You need to manually set the file encoding to UTF-8 if you want to see accurately represented Unicode characters on your screen. To my knowledge, this has nothing to do with the problem I’m seeing.)
Then the following test case code fails when the JarFile is created:
public File getSourceJarFile() throws IOException, URISyntaxException {
final URL url = this.getClass().getResource("/source.jar");
assertNotNull(url);
final URI uri = url.toURI();
assertNotNull(uri);
final String path = uri.getPath();
assertNotNull(path);
return new File(path);
}
@Test
public void testWTF() throws IOException, URISyntaxException {
final File file = this.getSourceJarFile();
assertNotNull(file);
assertTrue(file.isFile());
assertTrue(file.canRead());
// At this point, the file itself is there and can be read by this user.
JarFile jarFile = null;
try {
jarFile = new JarFile(file); // XXX KABOOM
} finally {
if (jarFile != null) {
jarFile.close();
}
}
}
The exception is:
java.util.zip.ZipException: error in opening zip file
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(ZipFile.java:127)
at java.util.jar.JarFile.<init>(JarFile.java:135)
at java.util.jar.JarFile.<init>(JarFile.java:99)
at com.foobar.TestCaseJarFileWTF.testWTF(TestCaseJarFileWTF.java:72)
To recap:
- I create a
source.jarfile in a place that is accessible to my test case using the simplest invocation of thejarcommand line tool. - I verify that this file actually exists, both visually and in my test case.
- I have opened this file successfully in
emacs, withjar -xf, and withunzip. It is a valid jar and zip file. - I confirm in my test case that it can be read by the currently running user.
I feel stupid admitting this, but I guess I must have not even the most basic of understanding as to how the JarFile constructor works. Any input here is greatly appreciated.
Maven strikes again. I had the test resources area set up for Maven filtering so the resulting zip file had probably had its innards scrambled. I hope my failure here helps others to troubleshoot similar problems.