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 | |
parent | 6712cfd277781008d6c66610ab23397cfcb5c850 (diff) | |
download | scala-31d539218aaddc9e225800fc9c28869f4b6b96ab.tar.gz scala-31d539218aaddc9e225800fc9c28869f4b6b96ab.tar.bz2 scala-31d539218aaddc9e225800fc9c28869f4b6b96ab.zip |
added option -Xcodebase
-rw-r--r-- | src/compiler/scala/tools/nsc/Global.scala | 71 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/Interpreter.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/Settings.scala | 6 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/AbstractFile.scala | 54 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/PlainFile.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/SourceReader.scala | 11 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/VirtualFile.scala | 7 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/ZipArchive.scala | 162 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/util/ClassPath.scala | 66 |
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 |