package net.sf.cotta.zip; import net.sf.cotta.*; import net.sf.cotta.io.OutputMode; import net.sf.cotta.memory.InMemoryFileSystem; import net.sf.cotta.system.FileSystem; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.nio.channels.FileChannel; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** * ZipFileSystem that operates on a Zip file. All the entries are loaded into the memory and the contents * are retrieved on demand. */ public class ZipFileSystem implements FileSystem, TResource { private ZipFile file; private InMemoryFileSystem entrySystem; private TFileFactory factory; private File jarFile; public ZipFileSystem(File jarFile) throws IOException { entrySystem = new InMemoryFileSystem(); entrySystem.setFileInitialCapacity(0); entrySystem.setFileSizeIncrement(0); factory = new TFileFactory(entrySystem); load(jarFile); this.jarFile = jarFile; } private void load(File jarFile) throws IOException { this.file = new ZipFile(jarFile); for (Enumeration enumeration = file.entries(); enumeration.hasMoreElements();) { ZipEntry entry = (ZipEntry) enumeration.nextElement(); String pathString = "/" + entry.getName(); if (entry.isDirectory()) { factory.dir(pathString).ensureExists(); } else { factory.file(pathString).create(); } } } public boolean fileExists(TPath path) { return entrySystem.fileExists(path); } public boolean dirExists(TPath path) { return entrySystem.dirExists(path); } public InputStream createInputStream(TPath path) throws TIoException { if (!entrySystem.fileExists(path)) { throw new TFileNotFoundException(path); } ZipEntry entry = entry(path); try { return file.getInputStream(entry); } catch (IOException e) { throw new TIoException(path, "Error opening entry", e); } } private ZipEntry entry(TPath path) { String pathString = path.toPathString(); if (pathString.startsWith("/")) { pathString = pathString.substring(1); } return file.getEntry(pathString); } public void createDir(TPath path) throws TIoException { throw new UnsupportedOperationException(); } public PathContent list(TPath path) { return entrySystem.list(path); } public void createFile(TPath path) throws TIoException { throw new UnsupportedOperationException(); } public void deleteFile(TPath path) throws TIoException { throw new UnsupportedOperationException(); } public OutputStream createOutputStream(TPath path, OutputMode mode) throws TIoException { throw new UnsupportedOperationException(); } public FileChannel createOutputChannel(TPath path, OutputStream outputStream) throws TIoException { throw new UnsupportedOperationException(); } public void deleteDirectory(TPath path) throws TIoException { throw new UnsupportedOperationException(); } public void moveFile(TPath source, TPath destination) { throw new UnsupportedOperationException(); } public void moveDirectory(TPath path, TPath path1) throws TIoException { throw new UnsupportedOperationException(); } public String pathString(TPath path) { StringBuffer buffer = new StringBuffer(file.getName()); buffer.append("[").append(path.toPathString()).append("]"); return buffer.toString(); } public long fileLength(TPath path) { return entry(path).getSize(); } public long fileLastModified(TPath path) { return entry(path).getTime(); } public int compare(TPath path1, TPath path2) { return path1.compareTo(path2); } public boolean equals(TPath path1, TPath path2) { return path1.equals(path2); } public int hashCode(TPath path) { return path.hashCode(); } public URI toUri(TPath path) { try { return new URI("jar:" + jarFile.toURI().toString() + "!" + path.toPathString()); } catch (URISyntaxException e) { throw new Error(e.getMessage(), e); } } public File toJavaFile(TPath path) { throw new UnsupportedOperationException("ZipFileSystem"); } public String toCanonicalPath(TPath path) { return "jar://" + pathString(path); } public FileChannel createInputChannel(TPath path) throws TIoException { throw new UnsupportedOperationException("not implemented for zip file"); } public void close() throws TIoException { try { file.close(); } catch (IOException e) { throw new TIoException(TPath.parse("/"), "Cannot close jar file", e); } } public static FileSystem readOnlyZipFileSystem(File jarFile) throws TIoException { ZipFileSystem zipFileSystem; try { zipFileSystem = new ZipFileSystem(jarFile); } catch (IOException e) { throw new TIoException(TPath.parse("/"), "Error opening zip file <" + jarFile.getAbsolutePath() + ">", e); } return ControlledFileSystem.readOnlyFileSystem(zipFileSystem); } }