I'm gonna describe here the root cause of JBVFS-38.
The problem is Linux (maybe unix?) specific, and can be reproduced without VFS - the recipe is as follows:
1) Open an existing zip file using JDK's ZipFile object, iterate over entries but don't close the ZipFile.
ZipFile zf = new ZipFile(archive);
Enumeration enum = zf.entries();
while (enum.hasMoreElements()) {
...
}
2) Then, overwrite this zip file with new content using _any_ method (i.e. JarOutputStream, or copy over an existing archive ...) , and properly close it.
writeNewJar(archive);
3) Now, open a new ZipFile around this file and iterate over entries.
zf = new ZipFile(archive);
enum = zf.entries();
while (enum.hasMoreElements()) {
...
}
Enumeration of entries is corrupt at this point - it returns a non existent entry with a garbled name,
real entries are missing.
The key to the problem is step 2) - overwriting the _still open_ ZipFile with new content.
Interestingly enough, if after step 2) I do a Thread.sleep(30000) and copy the file over with another one through shell,
the iteration returns proper content. But no matter how I try to do that as part of the same java process - copying streams,
or going so far as to use Runtime.exec("sh -c 'cp file1 file2'") ... no matter what I do, it doesn't help.
If ZipFile is closed first, then overwritten, everything is fine.
If it's deleted and then recreated, everything is fine as well.
I added delete() method to VirtualFile. It delegates the delete all the way to ZipEntryHandler layer - which takes care of releasing locks if necessary - so we can now reliably delete a file, and then reconstruct it, in order to avoid writing over an open file.
- marko