summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean McDirmid <sean.mcdirmid@gmail.com>2006-01-26 17:21:22 +0000
committerSean McDirmid <sean.mcdirmid@gmail.com>2006-01-26 17:21:22 +0000
commita5cffcb68756539a66ca9d604f79bb6cbe93b313 (patch)
tree291be5d46e69ca91c5e2a7490af81ea2697b83d0
parentbc13888586e6ed7062d59c8e883888cbaa5a7770 (diff)
downloadscala-a5cffcb68756539a66ca9d604f79bb6cbe93b313.tar.gz
scala-a5cffcb68756539a66ca9d604f79bb6cbe93b313.tar.bz2
scala-a5cffcb68756539a66ca9d604f79bb6cbe93b313.zip
Adding IO files to build.
-rw-r--r--src/compiler/scala/tools/nsc/io/AbstractFile.scala77
-rw-r--r--src/compiler/scala/tools/nsc/io/PlainFile.scala62
-rw-r--r--src/compiler/scala/tools/nsc/io/VirtualFile.scala26
-rw-r--r--src/compiler/scala/tools/nsc/io/ZipArchive.scala121
4 files changed, 286 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/io/AbstractFile.scala b/src/compiler/scala/tools/nsc/io/AbstractFile.scala
new file mode 100644
index 0000000000..3c556df646
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/io/AbstractFile.scala
@@ -0,0 +1,77 @@
+package scala.tools.nsc.io;
+
+import java.io.File;
+import java.io.IOException;
+
+/*
+object AbstractFile {
+ def getFile(path : String) : AbstractFile = getFile(new File(path));
+ def getFile(file : File ) : AbstractFile =
+ if (file.isFile() && file.exists()) new PlainFile(file);
+ else null;
+
+ def getDirectory(path : String) : AbstractFile = getDirectory(new File(path));
+ def getDirectory(file : File ) : AbstractFile =
+ if (!file.exists()) null;
+ else if (file.isDirectory()) new PlainFile(file);
+ else if (file.isFile()) {
+ val path = file.getPath();
+ if (path.endsWith(".jar") || path.endsWith(".zip"))
+ ZipArchive.fromFile(file);
+ else null;
+ } else null;
+}
+*/
+
+abstract class AbstractFile {
+ /** Returns the name of this abstract file. */
+ def name : String;
+ /** Returns the path of this abstract file. */
+ def path : String;
+ /** Returns the underlying File if any and null otherwise. */
+ def file : File;
+ /** Is this abstract file a directory? */
+ def isDirectory : Boolean;
+ /** Returns the time that this abstract file was last modified. */
+ def lastModified : Long;
+
+ /** Reads the content of this abstract file into a byte array. */
+ def read : Array[Byte];
+
+ /** Returns all abstract subfiles of this abstract directory. */
+ def list : List[AbstractFile];
+
+ /**
+ * Returns the abstract file in this abstract directory with the
+ * specified name. If there is no such file, returns null. The
+ * argument "directory" tells whether to look for a directory or
+ * or a regular file.
+ */
+ def lookupName(name : String, dir : Boolean) : AbstractFile;
+
+ final override def toString() : String = path;
+
+ /**
+ * Returns the abstract file in this abstract directory with the
+ * specified path relative to it, If there is no such file,
+ * returns null. The argument "directory" tells whether to look
+ * for a directory or or a regular file.
+ */
+ def lookupPath(path : String, dir : Boolean) : AbstractFile = {
+ val length = path.length();
+ val separator = File.separatorChar;
+ assert(0 < length && path.lastIndexOf(separator) < length - 1, path);
+ var file : AbstractFile = this;
+ var start : Int = 0;
+ var break = false;
+ while (!break) {
+ val index = path.indexOf(separator, start);
+ assert(index < 0 || start < index, path+" - "+start+" - "+index);
+ val name = path.substring(start, if (index < 0) length else index);
+ file = file.lookupName(name, if (index < 0) dir else true);
+ if (file == null || index < 0) break = true;
+ else start = index + 1;
+ }
+ file;
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/io/PlainFile.scala b/src/compiler/scala/tools/nsc/io/PlainFile.scala
new file mode 100644
index 0000000000..fa9e3db052
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/io/PlainFile.scala
@@ -0,0 +1,62 @@
+package scala.tools.nsc.io;
+
+import java.io._;
+
+object PlainFile {
+ def fromPath(path : String) : AbstractFile = fromFile(new File(path));
+
+ def fromFile(file : File) : AbstractFile =
+ if (file.exists()) new PlainFile(file) else null;
+
+}
+
+class PlainFile(val file : File) extends AbstractFile {
+ assert(file != null);
+ if (!file.exists()) throw new Error("non-existent file: " + file);
+
+ def name = file.getName();
+ def path = file.getPath();
+ def isDirectory = file.isDirectory();
+ def lastModified = file.lastModified();
+
+ def read = {
+ assert(!isDirectory, "cannot read directory");
+ val in = new FileInputStream(file);
+ var rest = file.length().asInstanceOf[Int];
+ val buf = new Array[Byte](rest);
+ var break = false;
+ while (!break) {
+ val res = in.read(buf, buf.length - rest, rest);
+ if (res == -1)
+ throw new IOException("read error");
+ rest = rest - res;
+ break = !(rest > 0);
+ }
+ in.close();
+ buf;
+ }
+
+ def lookupName0(name : String) : AbstractFile = {
+ assert(isDirectory, "not a directory '" + this + "'");
+ val child = new File(file, name);
+ if (!child.exists()) null;
+ else new PlainFile(child);
+ }
+
+ def lookupName(name : String, isDirectory: Boolean) : AbstractFile = {
+ val result = lookupName0(name);
+ if (result == null) null;
+ else if (isDirectory != result.isDirectory) null;
+ else result;
+ }
+
+ def list : List[AbstractFile] = {
+ assert(isDirectory, "not a directory '" + this + "'");
+ val names = file.list();
+ if (names == null || names.length == 0) return Nil;
+
+ val ret = for (val name <- names.toList) yield lookupName0(name);
+
+ for (val file <- ret; file != null) yield file;
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/io/VirtualFile.scala b/src/compiler/scala/tools/nsc/io/VirtualFile.scala
new file mode 100644
index 0000000000..da25f3b48a
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/io/VirtualFile.scala
@@ -0,0 +1,26 @@
+package scala.tools.nsc.io;
+
+class VirtualFile(val name : String, val path : String) extends AbstractFile {
+ assert(name != null && path != null, name + " - " + path);
+ def this(name : String) = this(name, name);
+ def file = null;
+ def isDirectory = false;
+ def lastModified = java.lang.Long.MIN_VALUE;
+
+ def read = {
+ assert(!isDirectory);
+ new Array[Byte](0);
+ }
+
+ def list : List[AbstractFile] = {
+ assert(isDirectory);
+ Nil;
+ }
+
+ def lookupName(name : String, isDirectory : Boolean) : AbstractFile = {
+ assert(isDirectory, "not a directory '" + this + "'");
+ null;
+ }
+
+
+}
diff --git a/src/compiler/scala/tools/nsc/io/ZipArchive.scala b/src/compiler/scala/tools/nsc/io/ZipArchive.scala
new file mode 100644
index 0000000000..251af7dbd4
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/io/ZipArchive.scala
@@ -0,0 +1,121 @@
+package scala.tools.nsc.io;
+
+import java.io._;
+import java.util.zip._;
+import scala.collection.mutable.HashMap;
+
+object ZipArchive {
+ def fromPath(path : String) : AbstractFile = fromFile(new File(path));
+ def fromFile(file : File ) : AbstractFile = {
+ try {
+ new ZipArchive(file, new ZipFile(file));
+ } catch {
+ case e : IOException => null;
+ }
+ }
+ def fromArchive(archive : ZipFile) =
+ new ZipArchive(new File(archive.getName()), archive);
+}
+
+final class ZipArchive(file : File, archive : ZipFile) extends PlainFile(file) {
+
+ assert(archive != null);
+ private var root0 : DirEntry = _;
+ assert(!super.isDirectory);
+
+ private def root = {
+ if (root0 == null) load else {}
+ root0
+ }
+
+
+
+ override def isDirectory = true;
+ override def list : List[AbstractFile] = for (val e : AbstractFile <- root.list) yield e.asInstanceOf[AbstractFile];
+ override def lookupName(name : String, isDirectory : Boolean) : AbstractFile = root.lookupName(name, isDirectory);
+
+
+ class Entry(name : String, path : String) extends VirtualFile(name, path) {
+ //override def path = ZipArchive.this.path + "(" + super.path + ")";
+ }
+ class DirEntry(name : String, path : String) extends Entry(name, path) {
+ val entries = new HashMap[String,Entry];
+ var entry : ZipEntry = _;
+
+ override def isDirectory = true;
+ override def lastModified = if (entry == null) super.lastModified else entry.getTime();
+
+ override def list = for (val e : AbstractFile <- entries.values.toList) yield e;
+
+ override def lookupName(name : String, isDirectory : Boolean) : AbstractFile =
+ entries(name + (if (isDirectory) "/" else ""));
+
+ }
+ class FileEntry(name : String, path : String, entry : ZipEntry) extends Entry(name, path) {
+ override def lastModified = entry.getTime();
+ override def read = {
+ val in = archive.getInputStream(entry);
+ var rest = entry.getSize().asInstanceOf[Int];
+ val buf = new Array[Byte](rest);
+
+ var break = false;
+ while (!break) {
+ val res = in.read(buf, buf.length - rest, rest);
+ if (res == -1)
+ throw new IOException("read error");
+ rest = rest - res;
+ break = !(rest > 0);
+ }
+ in.close();
+ buf;
+ }
+ }
+
+
+ /** Loads the archive and creates the root directory. */
+ private def load : Unit = {
+ root0 = new DirEntry("<root>", "/");
+ val dirs = new HashMap[String,DirEntry];
+ dirs("/") = root;
+
+ val e = archive.entries();
+ while (e.hasMoreElements()) {
+ val entry = e.nextElement().asInstanceOf[ZipEntry];
+ val path = entry.getName();
+ assert(entry.isDirectory() == path.endsWith("/"), "" + this +"-"+ path);
+ if (entry.isDirectory()) {
+ val dir = getDir(dirs, path);
+ assert(dir.entry == null, "" + this + " - " + 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 = getDir(dirs, home);
+ assert(!parent.entries.contains(path), ""+ this + " - " + path);
+ parent.entries(name) = new FileEntry(name, path, entry);
+ }
+ }
+ }
+
+ /**
+ * Lookups the specified table for a DirEntry with the specified
+ * path. If successful, returns the found DirEntry. Otherwise
+ * creates a new DirEntry, enters it into the table and in the
+ * table of its parent ZipDir and returns it.
+ */
+ private def getDir(dirs : HashMap[String,DirEntry], path : String): DirEntry = {
+ var dir = dirs(path);
+ if (dir == null) {
+ 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 = getDir(dirs, home);
+ dir = new DirEntry(name.substring(0, name.length() - 1), path);
+ parent.entries(name) = dir;
+ dirs(path) = dir;
+ }
+ dir
+ }
+
+}