diff --git a/run/Run.scala b/run/Run.scala
index 344fe9ea2..60581374c 100644
--- a/run/Run.scala
+++ b/run/Run.scala
@@ -11,11 +11,11 @@ import classpath.ClasspathUtilities
trait ScalaRun
{
- def run(mainClass: String, classpath: Iterable[Path], options: Seq[String], log: Logger): Option[String]
+ def run(mainClass: String, classpath: Seq[File], options: Seq[String], log: Logger): Option[String]
}
class ForkRun(config: ForkScalaRun) extends ScalaRun
{
- def run(mainClass: String, classpath: Iterable[Path], options: Seq[String], log: Logger): Option[String] =
+ def run(mainClass: String, classpath: Seq[File], options: Seq[String], log: Logger): Option[String] =
{
val scalaOptions = classpathOption(classpath) ::: mainClass :: options.toList
val exitCode = config.outputStrategy match {
@@ -24,7 +24,7 @@ class ForkRun(config: ForkScalaRun) extends ScalaRun
}
processExitCode(exitCode, "runner")
}
- private def classpathOption(classpath: Iterable[Path]) = "-cp" :: Path.makeString(classpath) :: Nil
+ private def classpathOption(classpath: Seq[File]) = "-cp" :: Path.makeString(classpath) :: Nil
private def processExitCode(exitCode: Int, label: String) =
{
if(exitCode == 0)
@@ -36,7 +36,7 @@ class ForkRun(config: ForkScalaRun) extends ScalaRun
class Run(instance: ScalaInstance) extends ScalaRun
{
/** Runs the class 'mainClass' using the given classpath and options using the scala runner.*/
- def run(mainClass: String, classpath: Iterable[Path], options: Seq[String], log: Logger) =
+ def run(mainClass: String, classpath: Seq[File], options: Seq[String], log: Logger) =
{
log.info("Running " + mainClass + " " + options.mkString(" "))
@@ -46,16 +46,12 @@ class Run(instance: ScalaInstance) extends ScalaRun
Run.executeTrapExit( execute, log )
}
- private def run0(mainClassName: String, classpath: Iterable[Path], options: Seq[String], log: Logger)
+ private def run0(mainClassName: String, classpath: Seq[File], options: Seq[String], log: Logger)
{
log.debug(" Classpath:\n\t" + classpath.mkString("\n\t"))
- val (loader, tempDir) = ClasspathUtilities.makeLoader(classpath, instance)
- try
- {
- val main = getMainMethod(mainClassName, loader)
- invokeMain(loader, main, options)
- }
- finally { IO.delete(tempDir asFile) }
+ val loader = ClasspathUtilities.makeLoader(classpath, instance)
+ val main = getMainMethod(mainClassName, loader)
+ invokeMain(loader, main, options)
}
private def invokeMain(loader: ClassLoader, main: Method, options: Seq[String])
{
@@ -79,7 +75,7 @@ class Run(instance: ScalaInstance) extends ScalaRun
/** This module is an interface to starting the scala interpreter or runner.*/
object Run
{
- def run(mainClass: String, classpath: Iterable[Path], options: Seq[String], log: Logger)(implicit runner: ScalaRun) =
+ def run(mainClass: String, classpath: Seq[File], options: Seq[String], log: Logger)(implicit runner: ScalaRun) =
runner.run(mainClass, classpath, options, log)
/** Executes the given function, trapping calls to System.exit. */
diff --git a/util/classpath/ClasspathUtilities.scala b/util/classpath/ClasspathUtilities.scala
index c966697b9..5e27b215b 100644
--- a/util/classpath/ClasspathUtilities.scala
+++ b/util/classpath/ClasspathUtilities.scala
@@ -4,6 +4,7 @@
package sbt
package classpath
+import java.lang.ref.{Reference, SoftReference, WeakReference}
import java.io.File
import java.net.{URI, URL, URLClassLoader}
import java.util.Collections
@@ -13,12 +14,14 @@ import IO.{createTemporaryDirectory, write}
object ClasspathUtilities
{
- def toClasspath(finder: PathFinder): Array[URL] = finder.getURLs
- def toClasspath(paths: Iterable[Path]): Array[URL] = Path.getURLs(paths)
- def toLoader(finder: PathFinder): ClassLoader = toLoader(finder.get)
- def toLoader(finder: PathFinder, parent: ClassLoader): ClassLoader = toLoader(finder.get, parent)
- def toLoader(paths: Iterable[Path]): ClassLoader = toLoader(paths, rootLoader)
- def toLoader(paths: Iterable[Path], parent: ClassLoader): ClassLoader = new URLClassLoader(toClasspath(paths), parent)
+ def toLoader(finder: PathFinder): ClassLoader = toLoader(finder, rootLoader)
+ def toLoader(finder: PathFinder, parent: ClassLoader): ClassLoader = new URLClassLoader(finder.getURLs, parent)
+
+ def toLoader(paths: Seq[File]): ClassLoader = toLoader(paths, rootLoader)
+ def toLoader(paths: Seq[File], parent: ClassLoader): ClassLoader = new URLClassLoader(Path.toURLs(paths), parent)
+
+ def toLoader(paths: Seq[File], parent: ClassLoader, resourceMap: Map[String,String]): ClassLoader =
+ new URLClassLoader(Path.toURLs(paths), parent) with RawResources { override def resources = resourceMap }
lazy val rootLoader =
{
@@ -33,28 +36,20 @@ object ClasspathUtilities
final val AppClassPath = "app.class.path"
final val BootClassPath = "boot.class.path"
- def createClasspathResources(classpath: Iterable[Path], instance: ScalaInstance, baseDir: Path): Iterable[Path] =
- createClasspathResources(classpath ++ Path.fromFiles(instance.jars), Path.fromFiles(instance.jars), baseDir)
+ def createClasspathResources(classpath: Seq[File], instance: ScalaInstance): Map[String,String] =
+ createClasspathResources(classpath ++ instance.jars, instance.jars)
- def createClasspathResources(appPaths: Iterable[Path], bootPaths: Iterable[Path], baseDir: Path): Iterable[Path] =
+ def createClasspathResources(appPaths: Seq[File], bootPaths: Seq[File]): Map[String, String] =
{
- def writePaths(name: String, paths: Iterable[Path]): Unit =
- write(baseDir / name asFile, Path.makeString(paths))
- writePaths(AppClassPath, appPaths)
- writePaths(BootClassPath, bootPaths)
- appPaths ++ Seq(baseDir)
+ def make(name: String, paths: Seq[File]) = name -> Path.makeString(paths)
+ Map( make(AppClassPath, appPaths), make(BootClassPath, bootPaths) )
}
- /** The client is responsible for cleaning up the temporary directory.*/
- def makeLoader[T](classpath: Iterable[Path], instance: ScalaInstance): (ClassLoader, Path) =
+ def makeLoader[T](classpath: Seq[File], instance: ScalaInstance): ClassLoader =
makeLoader(classpath, instance.loader, instance)
- /** The client is responsible for cleaning up the temporary directory.*/
- def makeLoader[T](classpath: Iterable[Path], parent: ClassLoader, instance: ScalaInstance): (ClassLoader, Path) =
- {
- val dir = Path.fromFile(createTemporaryDirectory)
- val modifiedClasspath = createClasspathResources(classpath, instance, dir)
- (toLoader(modifiedClasspath, parent), dir)
- }
+
+ def makeLoader[T](classpath: Seq[File], parent: ClassLoader, instance: ScalaInstance): ClassLoader =
+ toLoader(classpath, parent, createClasspathResources(classpath, instance))
private[sbt] def printSource(c: Class[_]) =
println(c.getName + " loader=" +c.getClassLoader + " location=" + IO.classLocationFile(c))
diff --git a/util/classpath/RawURL.scala b/util/classpath/RawURL.scala
new file mode 100644
index 000000000..645dcb10d
--- /dev/null
+++ b/util/classpath/RawURL.scala
@@ -0,0 +1,54 @@
+/* sbt -- Simple Build Tool
+ * Copyright 2010 Mark Harrah
+ */
+package sbt
+package classpath
+
+ import java.io.{ByteArrayInputStream, InputStream}
+ import java.net.{Proxy, URL, URLConnection, URLStreamHandler}
+ import java.util.Enumeration
+
+object RawURL
+{
+ def apply(file: String, value: String): URL =
+ apply(file, value.getBytes)
+ def apply(file: String, value: Array[Byte]): URL =
+ apply(file)(new ByteArrayInputStream(value))
+ def apply(file: String)(value: => InputStream): URL =
+ new URL("raw", null, -1, file, new RawStreamHandler(value))
+
+ private[this] final class RawStreamHandler(value: => InputStream) extends URLStreamHandler
+ {
+ override protected def openConnection(url: URL, p: Proxy): URLConnection =
+ openConnection(url)
+ override protected def openConnection(url: URL): URLConnection =
+ new URLConnection(url)
+ {
+ private lazy val in = value
+ def connect() { in }
+ override def getInputStream = in
+ }
+ }
+}
+
+trait RawResources extends FixedResources
+{
+ protected def resources: Map[String, String]
+ override protected final val resourceURL = resources.transform(RawURL.apply)
+}
+trait FixedResources extends ClassLoader
+{
+ protected def resourceURL: Map[String, URL]
+ override def findResource(s: String): URL = resourceURL.getOrElse(s, super.findResource(s))
+
+ import java.util.Collections.{enumeration, singletonList}
+ override def findResources(s: String): Enumeration[URL] =
+ {
+ val sup = super.findResources(s)
+ resourceURL.get(s) match
+ {
+ case Some(url) => new DualEnumeration(enumeration(singletonList(url)), sup)
+ case None => sup
+ }
+ }
+}
\ No newline at end of file
diff --git a/util/io/Path.scala b/util/io/Path.scala
index ca66c9684..e198552cc 100644
--- a/util/io/Path.scala
+++ b/util/io/Path.scala
@@ -148,6 +148,9 @@ object Path extends PathExtra
/** Constructs a String representation of Paths. The absolute path String of each Path is
* separated by the given separator String.*/
def makeString(paths: Iterable[Path], sep: String): String = paths.map(_.absolutePath).mkString(sep)
+
+ def makeString(paths: Seq[File]): String = makeString(paths, pathSeparator)
+ def makeString(paths: Seq[File], sep: String): String = paths.map(_.getAbsolutePath).mkString(sep)
/** Constructs a String representation of Paths. The relative path String of each Path is
* separated by the platform's path separator.*/
@@ -262,6 +265,8 @@ object Path extends PathExtra
def getFiles(files: Traversable[Path]): immutable.Set[File] = files.map(_.asFile).toSet
def getURLs(files: Traversable[Path]): Array[URL] = files.map(_.asURL).toArray
+
+ def toURLs(files: Seq[File]): Array[URL] = files.map(_.toURI.toURL).toArray
}
/** A path finder constructs a set of paths. The set is evaluated by a call to the get