summaryrefslogtreecommitdiff
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
parent6712cfd277781008d6c66610ab23397cfcb5c850 (diff)
downloadscala-31d539218aaddc9e225800fc9c28869f4b6b96ab.tar.gz
scala-31d539218aaddc9e225800fc9c28869f4b6b96ab.tar.bz2
scala-31d539218aaddc9e225800fc9c28869f4b6b96ab.zip
added option -Xcodebase
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala71
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala8
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala6
-rw-r--r--src/compiler/scala/tools/nsc/io/AbstractFile.scala54
-rw-r--r--src/compiler/scala/tools/nsc/io/PlainFile.scala2
-rw-r--r--src/compiler/scala/tools/nsc/io/SourceReader.scala11
-rw-r--r--src/compiler/scala/tools/nsc/io/VirtualFile.scala7
-rw-r--r--src/compiler/scala/tools/nsc/io/ZipArchive.scala162
-rw-r--r--src/compiler/scala/tools/nsc/util/ClassPath.scala66
9 files changed, 274 insertions, 113 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 9d76ab531c..d47d48d750 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -112,8 +112,8 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
if (onlyPresentation) new HashMap[Symbol,String]
else null
val methodArgumentNames =
- if (onlyPresentation) new HashMap[Symbol,List[List[Symbol]]];
- else null;
+ if (onlyPresentation) new HashMap[Symbol,List[List[Symbol]]]
+ else null
// reporting -------------------------------------------------------
@@ -130,8 +130,10 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
def informTime(msg: String, start: Long) =
informProgress(msg + " in " + (currentTime - start) + "ms")
- def log(msg: AnyRef): unit =
- if (settings.logAll.value || (settings.log contains phase.name)) inform("[log " + phase + "] " + msg)
+ def log(msg: AnyRef) {
+ if (settings.logAll.value || (settings.log contains phase.name))
+ inform("[log " + phase + "] " + msg)
+ }
class ErrorWithPosition(val pos: Int, val error: Throwable) extends Error
@@ -143,6 +145,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
case e : Error => throw new ErrorWithPosition(pos, e)
case e : RuntimeException => throw new ErrorWithPosition(pos, e)
}
+
def catchWith[T](source : SourceFile, body : => T) : T = try {
body
} catch {
@@ -151,7 +154,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
throw e.error
}
- def logError(msg: String, t: Throwable): Unit = {}
+ def logError(msg: String, t: Throwable): Unit = ()
def abort(msg: String) = throw new Error(msg)
@@ -178,12 +181,13 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
val classPath0 = new ClassPath(false && onlyPresentation)
- val classPath = new classPath0.Build(
- if (forMSIL) "" else settings.classpath.value,
- settings.sourcepath.value,
- settings.outdir.value,
- if (forMSIL) "" else settings.bootclasspath.value,
- if (forMSIL) "" else settings.extdirs.value)
+ val classPath =
+ if (forMSIL)
+ new classPath0.Build(settings.sourcepath.value, settings.outdir.value)
+ else
+ new classPath0.Build(settings.classpath.value, settings.sourcepath.value,
+ settings.outdir.value, settings.bootclasspath.value,
+ settings.extdirs.value, settings.Xcodebase.value)
if (settings.verbose.value) {
inform("[Classpath = " + classPath+"]")
@@ -229,12 +233,12 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
phaseWithId(id) = this
def run { currentRun.units foreach applyPhase }
- def apply(unit: CompilationUnit): unit
+ def apply(unit: CompilationUnit): Unit
private val isErased = prev.name == "erasure" || prev.erasedTypes
override def erasedTypes: boolean = isErased
private val isFlat = prev.name == "flatten" || prev.flatClasses
override def flatClasses: boolean = isFlat
- final def applyPhase(unit: CompilationUnit): unit = {
+ final def applyPhase(unit: CompilationUnit) {
if (settings.debug.value) inform("[running phase " + name + " on " + unit + "]")
val unit0 = currentRun.currentUnit
currentRun.currentUnit = unit
@@ -247,7 +251,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
class TerminalPhase(prev: Phase) extends GlobalPhase(prev) {
def name = "terminal"
- def apply(unit: CompilationUnit): unit = {}
+ def apply(unit: CompilationUnit): Unit = ()
}
object syntaxAnalyzer extends SyntaxAnalyzer {
@@ -402,14 +406,14 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
private var runCount = 0
class Run {
- curRunId = curRunId + 1
+ curRunId += 1
assert(curRunId > 0)
//Console.println("starting run: " + id)
var currentUnit: CompilationUnit = _
curRun = this
val firstPhase = syntaxAnalyzer.newPhase(NoPhase)
phase = firstPhase
- definitions.init; // needs firstPhase and phase to be defined != NoPhase,
+ definitions.init // needs firstPhase and phase to be defined != NoPhase,
// that's why it is placed here.
icodes.init
@@ -425,7 +429,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
def cancel { reporter.cancelled = true }
// progress tracking
- def progress(current: Int, total: Int): Unit = {}
+ def progress(current: Int, total: Int): Unit = ()
private var phasec: Int = 0
private var unitc: Int = 0
@@ -537,7 +541,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
informTime("total", startTime)
}
- def compileLate(file: AbstractFile): unit =
+ def compileLate(file: AbstractFile) {
if (fileset eq null) {
val msg = "No class file for " + file +
" was found\n(This file cannot be loaded as a source file)"
@@ -554,15 +558,17 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
}
refreshProgress
}
+ }
- def compileFiles(files: List[AbstractFile]): unit =
+ def compileFiles(files: List[AbstractFile]) {
try {
compileSources(files map getSourceFile)
} catch {
case ex: IOException => error(ex.getMessage())
}
+ }
- def compile(filenames: List[String]): unit =
+ def compile(filenames: List[String]) {
try {
if (settings.Xscript.value && filenames.length != 1)
error("can only compile one script at a time")
@@ -575,8 +581,9 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
} catch {
case ex: IOException => error(ex.getMessage())
}
+ }
- private def resetPackageClass(pclazz: Symbol): unit = {
+ private def resetPackageClass(pclazz: Symbol) {
atPhase(firstPhase) {
pclazz.setInfo(atPhase(typerPhase)(pclazz.info))
}
@@ -587,7 +594,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
def showDef(name: Name, module: boolean) {
def getSym(name: Name, module: boolean): Symbol = {
var i = name.length - 1
- while (i != 0 && name(i) != '#' && name(i) != '.') i = i - 1
+ while (i != 0 && name(i) != '#' && name(i) != '.') i -= 1
if (i == 0)
definitions.getModule(name)
else {
@@ -602,7 +609,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
}
/** Returns the file with the given suffix for the given class. */
- def getFile(clazz: Symbol, suffix: String) = {
+ def getFile(clazz: Symbol, suffix: String): File = {
val outdirname = settings.outdir.value
var outdir = new File(if (outdirname == "") "." else outdirname)
val filename = clazz.fullNameString('.')
@@ -616,25 +623,11 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
}
new File(outdir, filename.substring(start) + suffix)
}
-/*
- private def writeSymblFile(clazz: Symbol, pickled: PickleBuffer) = {
- val file = getFile(clazz, ".symbl")
- try {
- val stream = new FileOutputStream(file)
- stream.write(pickled.bytes, 0, pickled.writeIndex)
- stream.close()
- informProgress("wrote " + file)
- } catch {
- case ex: IOException =>
- if (settings.debug.value) ex.printStackTrace()
- error("could not write file " + file)
- }
- }
-*/
+
private def writeICode() {
val printer = new icodes.TextPrinter(null, icodes.linearizer)
icodes.classes.values.foreach((cls) => {
- val suffix = if (cls.symbol.hasFlag(Flags.MODULE)) "$.icode" else ".icode"
+ val suffix = if (cls.symbol hasFlag Flags.MODULE) "$.icode" else ".icode"
var file = getFile(cls.symbol, suffix)
// if (file.exists())
// file = new File(file.getParentFile(), file.getName() + "1")
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index 3d225b997d..554ec0c221 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -451,7 +451,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
if (succeeded) IR.Success else IR.Error
}
- /** A counter used for numbering objects created by bind() */
+ /** A counter used for numbering objects created by <code>bind()</code>. */
private var binderNum = 0
/** Bind a specified name to a specified value. The name may
@@ -464,7 +464,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
*/
def bind(name: String, boundType: String, value: Any): IR.Result = {
val binderName = "binder" + binderNum
- binderNum = binderNum + 1
+ binderNum += 1
compileString(
"object " + binderName +
@@ -498,9 +498,9 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
* each command is executed because of Java's demand loading.
* </p>
*/
- def close(): Unit =
+ def close() {
Interpreter.deleteRecursively(classfilePath)
-
+ }
/** A traverser that finds all mentioned identifiers, i.e. things
that need to be imported.
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index 626c41cfd9..87d0defa00 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -9,7 +9,7 @@ package scala.tools.nsc
import java.io.File
import java.lang.System
-class Settings(error: String => unit) {
+class Settings(error: String => Unit) {
def this() = this(Console.println)
private var allsettings: List[Setting] = List()
@@ -119,6 +119,7 @@ class Settings(error: String => unit) {
val inline = BooleanSetting("-Xinline", "Perform inlining when possible")
val XO = BooleanSetting("-XO", "Optimize. implies -Xinline, -Xcloselim and -Xdce")
val Xcloselim = BooleanSetting("-Xcloselim", "Perform closure elimination")
+ val Xcodebase = StringSetting ("-Xcodebase", "codebase", "Specify the URL containing the Scala libraries", "")
val Xdce = BooleanSetting("-Xdce", "Perform dead code elimination")
val Xwarndeadcode = BooleanSetting("-Xwarndeadcode", "Emit warnings for dead code")
val XbytecodeRead = BooleanSetting("-XbytecodeRead", "Enable bytecode reader.")
@@ -157,7 +158,8 @@ class Settings(error: String => unit) {
val pagebottom = StringSetting("-bottom", "pagebottom",
"Include bottom text for each page",
/*default*/"").dependsOn(doc)
- val nocomment = new BooleanSetting("-nocomment", "Suppress description and tags, generate only declarations.") {
+ val nocomment = new BooleanSetting("-nocomment",
+ "Suppress description and tags, generate only declarations.") {
override def hiddenToIDE = true; dependsOn(doc)
}
val doccharset = StringSetting("-charset", "doccharset",
diff --git a/src/compiler/scala/tools/nsc/io/AbstractFile.scala b/src/compiler/scala/tools/nsc/io/AbstractFile.scala
index 0ef0a18216..1cb30f4714 100644
--- a/src/compiler/scala/tools/nsc/io/AbstractFile.scala
+++ b/src/compiler/scala/tools/nsc/io/AbstractFile.scala
@@ -1,5 +1,5 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2006 LAMP/EPFL
+ * Copyright 2005-2007 LAMP/EPFL
* @author Martin Odersky
*/
// $Id$
@@ -7,8 +7,8 @@
package scala.tools.nsc.io
-
-import java.io.{File,InputStream,DataInputStream}
+import java.io.{DataInputStream, File, IOException, InputStream}
+import java.net.URL
object AbstractFile {
@@ -27,23 +27,41 @@ object AbstractFile {
def getDirectory(path: String): AbstractFile = getDirectory(new File(path))
/**
- * if the specified File exists and is either a directory or a
+ * If the specified File exists and is either a directory or a
* readable zip or jar archive, returns an abstract directory
- * backed by it. Otherwise, returns null.
+ * backed by it. Otherwise, returns <code>null</code>.
*
* @param file ...
* @return ...
*/
def getDirectory(file: File): AbstractFile = {
- if (file.isDirectory() && file.exists()) return new PlainFile(file);
+ if (file.isDirectory() && file.exists()) return new PlainFile(file)
if (file.isFile() && file.exists()) {
- val path = file.getPath();
+ val path = file.getPath()
if (path.endsWith(".jar") || path.endsWith(".zip"))
return ZipArchive.fromFile(file);
}
null
}
+ /**
+ * If the specified URL exists and is a readable zip or jar archive,
+ * returns an abstract directory backed by it. Otherwise, returns
+ * <code>null</code>.
+ *
+ * @param file ...
+ * @return ...
+ */
+ def getURL(url: URL): AbstractFile =
+ if (url ne null) {
+ val path = url.getPath()
+ if (path.endsWith(".jar") || path.endsWith(".zip"))
+ ZipArchive.fromURL(url)
+ else
+ null
+ }
+ else
+ null
}
/**
@@ -72,9 +90,6 @@ object AbstractFile {
*/
abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] {
- //########################################################################
- // Public Methods
-
/** Returns the name of this abstract file. */
def name: String
@@ -91,7 +106,7 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] {
def lastModified: Long
/** returns an input stream so the file can be read */
- def read : InputStream;
+ def read: InputStream
/** size of this file if it is a concrete file */
def size: Option[Int] = None
@@ -106,17 +121,17 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] {
/** returns contents of file (if applicable) in a byte array
* @throws java.io.IOException
*/
- final def toByteArray = {
+ final def toByteArray: Array[Byte] = {
val in = read
var rest = size.get
- val arr = new Array[Byte](rest);
+ val arr = new Array[Byte](rest)
while (rest > 0) {
- val res = in.read(arr, arr.length - rest, rest);
- if (res == -1)
- throw new java.io.IOException("read error");
- rest = rest - res;
+ val res = in.read(arr, arr.length - rest, rest)
+ if (res == -1)
+ throw new IOException("read error")
+ rest -= res
}
- in.close();
+ in.close()
arr
}
@@ -124,7 +139,7 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] {
def elements: Iterator[AbstractFile]
/** Returns the abstract file in this abstract directory with the specified
- * name. If there is no such file, returns null. The argument
+ * name. If there is no such file, returns <code>null</code>. The argument
* <code>directory</code> tells whether to look for a directory or
* a regular file.
*
@@ -163,5 +178,4 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] {
/** Returns the path of this abstract file. */
override def toString() = path
- //########################################################################
}
diff --git a/src/compiler/scala/tools/nsc/io/PlainFile.scala b/src/compiler/scala/tools/nsc/io/PlainFile.scala
index cff9fac410..21e3e8b6ce 100644
--- a/src/compiler/scala/tools/nsc/io/PlainFile.scala
+++ b/src/compiler/scala/tools/nsc/io/PlainFile.scala
@@ -1,5 +1,5 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2006 LAMP/EPFL
+ * Copyright 2005-2007 LAMP/EPFL
* @author Martin Odersky
*/
// $Id$
diff --git a/src/compiler/scala/tools/nsc/io/SourceReader.scala b/src/compiler/scala/tools/nsc/io/SourceReader.scala
index 50e9669c2b..2ea7ec4afe 100644
--- a/src/compiler/scala/tools/nsc/io/SourceReader.scala
+++ b/src/compiler/scala/tools/nsc/io/SourceReader.scala
@@ -1,15 +1,12 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002-2006, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-\* */
-
+/* NSC -- new Scala compiler
+ * Copyright 2005-2007 LAMP/EPFL
+ * @author Martin Odersky
+ */
// $Id$
package scala.tools.nsc.io
-
import java.io.{File, FileInputStream, InputStream, IOException}
import java.nio.{ByteBuffer, CharBuffer}
import java.nio.channels.{FileChannel, ReadableByteChannel, Channels}
diff --git a/src/compiler/scala/tools/nsc/io/VirtualFile.scala b/src/compiler/scala/tools/nsc/io/VirtualFile.scala
index 865e7f0abf..c9a15e90c1 100644
--- a/src/compiler/scala/tools/nsc/io/VirtualFile.scala
+++ b/src/compiler/scala/tools/nsc/io/VirtualFile.scala
@@ -1,5 +1,5 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2006 LAMP/EPFL
+ * Copyright 2005-2007 LAMP/EPFL
* @author Martin Odersky
*/
// $Id$
@@ -7,7 +7,7 @@
package scala.tools.nsc.io
-import java.io.{File,InputStream}
+import java.io.{File, InputStream}
/** This class implements an empty abstract regular file.
*
@@ -37,7 +37,8 @@ class VirtualFile(val name: String, _path: String) extends AbstractFile {
/** Returns null. */
final def file: File = null
- def read : InputStream = throw new Error("not suported");
+
+ def read: InputStream = throw new Error("not suported")
/** Is this abstract file a directory? */
def isDirectory: Boolean = false
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)
+ }
}
diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala
index 2707e1675d..754abfc8b8 100644
--- a/src/compiler/scala/tools/nsc/util/ClassPath.scala
+++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala
@@ -11,6 +11,7 @@
package scala.tools.nsc.util
import java.io.File
+import java.net.URL
import java.util.StringTokenizer
import scala.collection.mutable.ArrayBuffer
@@ -172,30 +173,24 @@ class ClassPath(onlyPresentation: Boolean) {
def root = new Context(entries.toList)
- def this(classpath: String) = {
+ def this(classpath: String) {
this()
addFilesInPath(classpath)
}
+ def this(source: String, output: String) {
+ this()
+ addDirsInPath(source, output)
+ }
+
def this(classpath: String, source: String, output: String,
- boot: String, extdirs: String) = {
+ boot: String, extdirs: String, codebase: String) {
this()
addFilesInPath(boot)
addArchivesInExtDirPath(extdirs)
- val clazzes = AbstractFile.getDirectory(output)
- if (clazzes eq null)
- throw new FatalError("Output location \"" + output + "\" not found")
- val strtok = new StringTokenizer(source, File.pathSeparator)
- if (!strtok.hasMoreTokens()) {
- val output0 = (new Output(clazzes, null))
- entries += output0
- }
- else while (strtok.hasMoreTokens()) {
- val sources = AbstractFile.getDirectory(strtok.nextToken())
- val output0 = (new Output(clazzes, sources))
- entries += output0
- }
+ addDirsInPath(source, output)
addFilesInPath(classpath)
+ addURLsInPath(codebase)
}
/**
@@ -203,7 +198,7 @@ class ClassPath(onlyPresentation: Boolean) {
* @param isDir ...
* @return ...
*/
- def lookupPath(path: String, isDir: Boolean) = {
+ def lookupPath(path: String, isDir: Boolean): AbstractFile = {
val ctx = root.find(path, isDir)
if (ctx eq null) null
else if (ctx.entries.isEmpty) null
@@ -215,7 +210,7 @@ class ClassPath(onlyPresentation: Boolean) {
* @param classes ...
* @param sources ...
*/
- def library(classes: String, sources: String) = {
+ def library(classes: String, sources: String) {
assert(classes ne null)
val location = AbstractFile.getDirectory(classes)
val sourceFile0 =
@@ -227,7 +222,7 @@ class ClassPath(onlyPresentation: Boolean) {
entries += new Library0()
}
- private def addFilesInPath(path: String) = {
+ private def addFilesInPath(path: String) {
val strtok = new StringTokenizer(path, File.pathSeparator)
while (strtok.hasMoreTokens()) {
val file = AbstractFile.getDirectory(strtok.nextToken())
@@ -235,7 +230,7 @@ class ClassPath(onlyPresentation: Boolean) {
}
}
- private def addArchivesInExtDirPath(path: String) = {
+ private def addArchivesInExtDirPath(path: String) {
val strtok = new StringTokenizer(path, File.pathSeparator)
while (strtok.hasMoreTokens()) {
val file = AbstractFile.getDirectory(strtok.nextToken())
@@ -251,6 +246,39 @@ class ClassPath(onlyPresentation: Boolean) {
}
}
+ private def addDirsInPath(source: String, output: String) {
+ val clazzes = AbstractFile.getDirectory(output)
+ if (clazzes eq null)
+ throw new FatalError("Output location \"" + output + "\" not found")
+ val strtok = new StringTokenizer(source, File.pathSeparator)
+ if (!strtok.hasMoreTokens()) {
+ val output0 = (new Output(clazzes, null))
+ entries += output0
+ }
+ else while (strtok.hasMoreTokens()) {
+ val sources = AbstractFile.getDirectory(strtok.nextToken())
+ val output0 = (new Output(clazzes, sources))
+ entries += output0
+ }
+ }
+
+ private val urlSeparator = " "
+ private def addURLsInPath(codebase: String) {
+ val strtok = new StringTokenizer(codebase, urlSeparator)
+ while (strtok.hasMoreTokens()) {
+ try {
+ val url = new URL(strtok.nextToken())
+ val archive = AbstractFile.getURL(url)
+ if (archive ne null) entries += (new Library(archive))
+ }
+ catch {
+ case e =>
+ Console.println("error in addURLsInPath: " + e.getMessage)//debug
+ throw e
+ }
+ }
+ }
+
override def toString() =
entries.toList.mkString("", File.pathSeparator, "")
} // class Build