summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/io/ZipArchive.scala
diff options
context:
space:
mode:
authormichelou <michelou@epfl.ch>2007-05-30 10:38:16 +0000
committermichelou <michelou@epfl.ch>2007-05-30 10:38:16 +0000
commit31d539218aaddc9e225800fc9c28869f4b6b96ab (patch)
tree8fc713a9c4b5b79f4d745e48b815e350133eb1b9 /src/compiler/scala/tools/nsc/io/ZipArchive.scala
parent6712cfd277781008d6c66610ab23397cfcb5c850 (diff)
downloadscala-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.scala162
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)
+ }
}