diff options
author | Sean McDirmid <sean.mcdirmid@gmail.com> | 2006-01-26 17:21:22 +0000 |
---|---|---|
committer | Sean McDirmid <sean.mcdirmid@gmail.com> | 2006-01-26 17:21:22 +0000 |
commit | a5cffcb68756539a66ca9d604f79bb6cbe93b313 (patch) | |
tree | 291be5d46e69ca91c5e2a7490af81ea2697b83d0 | |
parent | bc13888586e6ed7062d59c8e883888cbaa5a7770 (diff) | |
download | scala-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.scala | 77 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/PlainFile.scala | 62 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/VirtualFile.scala | 26 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/ZipArchive.scala | 121 |
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 + } + +} |