diff options
author | michelou <michelou@epfl.ch> | 2007-05-30 10:38:16 +0000 |
---|---|---|
committer | michelou <michelou@epfl.ch> | 2007-05-30 10:38:16 +0000 |
commit | 31d539218aaddc9e225800fc9c28869f4b6b96ab (patch) | |
tree | 8fc713a9c4b5b79f4d745e48b815e350133eb1b9 /src/compiler/scala/tools/nsc/io/ZipArchive.scala | |
parent | 6712cfd277781008d6c66610ab23397cfcb5c850 (diff) | |
download | scala-31d539218aaddc9e225800fc9c28869f4b6b96ab.tar.gz scala-31d539218aaddc9e225800fc9c28869f4b6b96ab.tar.bz2 scala-31d539218aaddc9e225800fc9c28869f4b6b96ab.zip |
added option -Xcodebase
Diffstat (limited to 'src/compiler/scala/tools/nsc/io/ZipArchive.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/io/ZipArchive.scala | 162 |
1 files changed, 144 insertions, 18 deletions
diff --git a/src/compiler/scala/tools/nsc/io/ZipArchive.scala b/src/compiler/scala/tools/nsc/io/ZipArchive.scala index e5c144db08..8fcb553ba3 100644 --- a/src/compiler/scala/tools/nsc/io/ZipArchive.scala +++ b/src/compiler/scala/tools/nsc/io/ZipArchive.scala @@ -1,5 +1,5 @@ /* NSC -- new Scala compiler - * Copyright 2005-2006 LAMP/EPFL + * Copyright 2005-2007 LAMP/EPFL * @author Martin Odersky */ // $Id$ @@ -8,8 +8,9 @@ package scala.tools.nsc.io import java.io.{File, IOException, InputStream} +import java.net.URL import java.util.Enumeration -import java.util.zip.{ZipEntry, ZipFile} +import java.util.zip.{ZipEntry, ZipFile, ZipInputStream} import scala.collection.mutable.{Map, HashMap} @@ -48,13 +49,25 @@ object ZipArchive { * @return ... */ def fromArchive(archive: ZipFile): AbstractFile = - new ZipArchive(new File(archive.getName()), archive); + new ZipArchive(new File(archive.getName()), archive) + + /** + * Returns an abstract directory backed by the specified archive. + * + * @param url ... + * @return ... + */ + def fromURL(url: URL): AbstractFile = + new URLZipArchive(url) } /** * This class implements an abstract directory backed by a zip - * archive. We let the encoding be null, because we behave like - * a directory + * archive. We let the encoding be <code>null</code>, because we behave like + * a directory. + * + * @author Philippe Altherr + * @version 1.0, 23/03/2004 */ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file) { @@ -92,7 +105,7 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file) // Private Methods /** Loads the archive and creates the root directory. */ - private def load(): Unit = { + private def load() { this.root = new DirEntry("<root>", "/") // A path to DirEntry map val dirs: Map[String,DirEntry] = new HashMap() @@ -127,16 +140,15 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file) private def getDir(dirs: Map[String,DirEntry], path: String): DirEntry = dirs.get(path) match { case Some(dir) => dir - case None => { - val index = path.lastIndexOf('/', path.length() - 2); - val name = if (index < 0) path else path.substring(index + 1); - val home = if (index < 0) "/" else path.substring(0, index + 1); - val parent: DirEntry = getDir(dirs, home); - val dir = new DirEntry(name.substring(0, name.length() - 1), path); - parent.entries.update(name, dir); - dirs.update(path, dir); + case None => + val index = path.lastIndexOf('/', path.length() - 2) + val name = if (index < 0) path else path.substring(index + 1) + val home = if (index < 0) "/" else path.substring(0, index + 1) + val parent: DirEntry = getDir(dirs, home) + val dir = new DirEntry(name.substring(0, name.length() - 1), path) + parent.entries.update(name, dir) + dirs.update(path, dir) dir - } } //######################################################################## @@ -162,7 +174,7 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file) var entry: ZipEntry = _ override def isDirectory = true - override def read = throw new Error("cannot read directories"); + override def read = throw new Error("cannot read directories") override def lastModified: Long = if (entry ne null) entry.getTime() else super.lastModified @@ -182,10 +194,124 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file) /** A regular file archive entry */ final class FileEntry(name: String, path: String, val entry: ZipEntry) extends Entry(name, path) { - def archive = ZipArchive.this.archive; + def archive = ZipArchive.this.archive override def lastModified: Long = entry.getTime() - override def read = archive.getInputStream(entry); + override def read = archive.getInputStream(entry) override def size = Some(entry.getSize().toInt) } +} + +/** + * This class implements an abstract directory backed by a specified + * zip archive. + * + * @author Stephane Micheloud + * @version 1.0, 29/05/2007 + */ +final class URLZipArchive(url: URL) extends AbstractFile { + assert(url ne null) + + private var root: DirEntry = _ + + def name: String = url.getFile() + + def path: String = url.getPath() + + def file: File = null + + def isDirectory: Boolean = true + + def lastModified: Long = + try { url.openConnection().getLastModified() } + catch { case _ => 0 } + + def read: InputStream = url.openStream() + + override def elements: Iterator[AbstractFile] = { + if (root eq null) load() + root.elements + } + + override def lookupName(name: String, directory: Boolean): AbstractFile = { + if (root eq null) load() + root.lookupName(name, directory) + } + + private def load() { + this.root = new DirEntry("<root>", "/") + // A path to DirEntry map + val dirs: Map[String, DirEntry] = new HashMap() + dirs.update("/", root) + val zis = new ZipInputStream(read) + var entry = zis.getNextEntry() + while (entry ne null) { + val path = entry.getName() + assert(entry.isDirectory() == path.endsWith("/"), + this.toString() + " - " + path); + if (entry.isDirectory()) { + val dir: DirEntry = getDir(dirs, path) + assert(dir.entry eq null, this.toString() + " - " + path) + dir.entry = entry + } else { + val index = path.lastIndexOf('/') + val name = if (index < 0) path else path.substring(index + 1) + val home = if (index < 0) "/" else path.substring(0, index + 1) + val parent: DirEntry = getDir(dirs, home) + assert(!parent.entries.contains(path), this.toString() + " - " + path) + parent.entries.update(name, new FileEntry(name, path, zis)) + } + entry = zis.getNextEntry() + } + zis.close + } + + private def getDir(dirs: Map[String, DirEntry], path: String): DirEntry = + dirs.get(path) match { + case Some(dir) => dir + case None => + val index = path.lastIndexOf('/', path.length() - 2) + val name = if (index < 0) path else path.substring(index + 1) + val home = if (index < 0) "/" else path.substring(0, index + 1) + val parent: DirEntry = getDir(dirs, home) + val dir = new DirEntry(name.substring(0, name.length() - 1), path) + parent.entries.update(name, dir) + dirs.update(path, dir) + dir + } + + /** Superclass of archive entries */ + abstract class Entry(name: String, path: String) + extends VirtualFile(name, path) { + final override def path = URLZipArchive.this.toString() + "(" + super.path + ")" + //final def getArchive = URLZipArchive.this.archive + } + + /** A directory archive entry */ + private final class DirEntry(name: String, path: String) + extends Entry(name, path) + { + val entries: Map[String, Entry] = new HashMap() + var entry: ZipEntry = _ + + override def isDirectory = true + override def read = throw new Error("cannot read directories"); + + override def lastModified: Long = + if (entry ne null) entry.getTime() else super.lastModified + + override def elements: Iterator[AbstractFile] = entries.values + + override def lookupName(name: String, directory: Boolean): AbstractFile = + entries.get(if (directory) name + "/" else name) match { + case Some(dir) => dir + case None => null + } + } + final class FileEntry(name: String, path: String, val zis: ZipInputStream) + extends Entry(name, path) { + override def lastModified: Long = 0 + override def read = zis + override def size = Some(0) + } } |