beginnings of zipinputstream code
diff --git a/org.eclipse.virgo.kernel.artifact/src/main/java/org/eclipse/virgo/kernel/artifact/fs/internal/JarFileArtifactFSEntry.java b/org.eclipse.virgo.kernel.artifact/src/main/java/org/eclipse/virgo/kernel/artifact/fs/internal/JarFileArtifactFSEntry.java index 3c6584d..da01efb 100644 --- a/org.eclipse.virgo.kernel.artifact/src/main/java/org/eclipse/virgo/kernel/artifact/fs/internal/JarFileArtifactFSEntry.java +++ b/org.eclipse.virgo.kernel.artifact/src/main/java/org/eclipse/virgo/kernel/artifact/fs/internal/JarFileArtifactFSEntry.java
@@ -13,7 +13,11 @@ package org.eclipse.virgo.kernel.artifact.fs.internal; +import java.io.BufferedInputStream; +import java.io.Closeable; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -23,12 +27,18 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; import org.eclipse.virgo.kernel.artifact.fs.ArtifactFS; import org.eclipse.virgo.kernel.artifact.fs.ArtifactFSEntry; /** * {@link JarFileArtifactFSEntry} is an {@link ArtifactFSEntry} implementation for JAR file entries. + * <p/> + * The implementation uses ZipInputStream specifically to avoid JarFile's caching behaviour, inherited from that of + * ZipFile. See the note on caching in http://java.sun.com/developer/technicalArticles/Programming/compression/ + * JarFile's caching behaviour produces incorrect results when a JAR file is replaced with a new version since the cache + * returns entries from the old version. * * <strong>Concurrent Semantics</strong><br /> * @@ -36,12 +46,10 @@ */ final class JarFileArtifactFSEntry implements ArtifactFSEntry { + private final File file; + private final String entryName; - private final JarFile jarFile; - - private final ZipEntry zipEntry; - /** * Constructs a new {@link JarFileArtifactFSEntry} for the given file which is assumed to be in JAR format and the * given entry name. @@ -51,13 +59,8 @@ * @throws IOException if the entry cannot be created */ JarFileArtifactFSEntry(File file, String entryName) throws IOException { - this(new JarFile(file), entryName); - } - - private JarFileArtifactFSEntry(JarFile jarFile, String entryName) { + this.file = file; this.entryName = entryName; - this.jarFile = jarFile; - this.zipEntry = jarFile.getEntry(entryName); } /** @@ -91,23 +94,30 @@ * {@inheritDoc} */ public boolean isDirectory() { - return exists() ? this.zipEntry.isDirectory() : false; + ZipEntry zipEntry = findZipEntry(); + return zipEntry != null ? zipEntry.isDirectory() : false; + } + + private ZipEntry findZipEntry() { + // TODO Auto-generated method stub + return null; } /** * {@inheritDoc} */ public InputStream getInputStream() { - if (!exists()) { + ZipEntry zipEntry = findZipEntry(); + if (zipEntry == null) { throw new UnsupportedOperationException("Cannot open an input stream for a non-existent entry"); } - if (isDirectory()) { + if (zipEntry.isDirectory()) { throw new UnsupportedOperationException("Cannot open an input stream for a directory"); } - + try { - return this.jarFile.getInputStream(this.zipEntry); + return this.jarFile.getInputStream(zipEntry); } catch (IOException e) { // Preserve compatibility with current interface. throw new RuntimeException(e); @@ -135,7 +145,7 @@ JarEntry entry = entries.nextElement(); String childEntry = entry.getName(); if (childEntry.length() > this.entryName.length() && childEntry.startsWith(this.entryName)) { - children.add(new JarFileArtifactFSEntry(this.jarFile, childEntry)); + children.add(new JarFileArtifactFSEntry(this.file, childEntry)); } } } @@ -168,4 +178,36 @@ return false; } + private class JarFileScanner implements Closeable { + + private final ZipInputStream zipInputStream; + + public JarFileScanner() { + InputStream is = null; + try { + is = new BufferedInputStream(new FileInputStream(file)); + } catch (FileNotFoundException _) { + } + this.zipInputStream = is == null ? null : new ZipInputStream(is); + } + + public ZipEntry nextEntry() { + if (this.zipInputStream != null) { + try { + return this.zipInputStream.getNextEntry(); + } catch (IOException _) { + } + } + return null; + } + + public ZipInputStream getZipInputStream() { + return this.zipInputStream; + } + + public void close() throws IOException { + this.zipInputStream.close(); + } + } + }