diff options
author | Paul Phillips <paulp@improving.org> | 2010-09-07 17:48:09 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-09-07 17:48:09 +0000 |
commit | 6dfcae30bfcdc93509755185f814c8e318a64012 (patch) | |
tree | 713036c0fa3b3504fd7ca8e9d991f33cc9dbeae0 /src/compiler | |
parent | b5c20527352085b01457e9104137de7b28eafdff (diff) | |
download | scala-6dfcae30bfcdc93509755185f814c8e318a64012.tar.gz scala-6dfcae30bfcdc93509755185f814c8e318a64012.tar.bz2 scala-6dfcae30bfcdc93509755185f814c8e318a64012.zip |
Some modifications to repl classloading to make...
Some modifications to repl classloading to make it usable in managed
classloader environments. Contributed by mark harrah. Review by rytz.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/Interpreter.scala | 15 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/InterpreterLoop.scala | 3 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/settings/MutableSettings.scala | 28 |
3 files changed, 39 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala index 7dd6d3ba04..3be1b44a4c 100644 --- a/src/compiler/scala/tools/nsc/Interpreter.scala +++ b/src/compiler/scala/tools/nsc/Interpreter.scala @@ -229,7 +229,9 @@ class Interpreter(val settings: Settings, out: PrintWriter) { private def methodByName(c: Class[_], name: String): reflect.Method = c.getMethod(name, classOf[Object]) - protected def parentClassLoader: ClassLoader = this.getClass.getClassLoader() + protected def parentClassLoader: ClassLoader = + settings.explicitParentLoader.getOrElse( this.getClass.getClassLoader() ) + def getInterpreterClassLoader() = classLoader // Set the current Java "context" class loader to this interpreter's class loader @@ -1267,15 +1269,16 @@ object Interpreter { } } } - def breakIf(assertion: => Boolean, args: DebugParam[_]*): Unit = - if (assertion) break(args.toList) + // provide the enclosing type T + // in order to set up the interpreter's classpath and parent class loader properly + def breakIf[T: Manifest](assertion: => Boolean, args: DebugParam[_]*): Unit = + if (assertion) break[T](args.toList) // start a repl, binding supplied args - def break(args: List[DebugParam[_]]): Unit = { + def break[T: Manifest](args: List[DebugParam[_]]): Unit = { val intLoop = new InterpreterLoop intLoop.settings = new Settings(Console.println) - // XXX come back to the dot handling - intLoop.settings.classpath.value = "." + intLoop.settings.embeddedDefaults[T] intLoop.createInterpreter intLoop.in = InteractiveReader.createDefault(intLoop.interpreter) diff --git a/src/compiler/scala/tools/nsc/InterpreterLoop.scala b/src/compiler/scala/tools/nsc/InterpreterLoop.scala index f68ce4a5b4..bdcd7b9f58 100644 --- a/src/compiler/scala/tools/nsc/InterpreterLoop.scala +++ b/src/compiler/scala/tools/nsc/InterpreterLoop.scala @@ -117,7 +117,8 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite settings.classpath append addedClasspath interpreter = new Interpreter(settings, out) { - override protected def parentClassLoader = classOf[InterpreterLoop].getClassLoader + override protected def parentClassLoader = + settings.explicitParentLoader.getOrElse( classOf[InterpreterLoop].getClassLoader ) } interpreter.setContextClassLoader() // interpreter.quietBind("settings", "scala.tools.nsc.InterpreterSettings", interpreter.isettings) diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index 1e0e00e01d..c15a4279fb 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -11,6 +11,7 @@ package settings import io.{AbstractFile, VirtualDirectory} import scala.tools.util.StringOps import scala.collection.mutable.ListBuffer +import scala.io.Source /** A mutable Settings object. */ @@ -160,6 +161,33 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal doArgs(args) } + /** Initializes these settings for embedded use by type `T`. + * The class loader defining `T` should provide resources `app.class.path` + * and `boot.class.path`. These resources should contain the application + * and boot classpaths in the same form as would be passed on the command line.*/ + def embeddedDefaults[T: Manifest]: Unit = + embeddedDefaults(implicitly[Manifest[T]].erasure.getClassLoader) + + /** Initializes these settings for embedded use by a class from the given class loader. + * The class loader for `T` should provide resources `app.class.path` + * and `boot.class.path`. These resources should contain the application + * and boot classpaths in the same form as would be passed on the command line.*/ + def embeddedDefaults(loader: ClassLoader) { + explicitParentLoader = Option(loader) // for the Interpreter parentClassLoader + getClasspath("app", loader) foreach { classpath.value = _ } + getClasspath("boot", loader) foreach { bootclasspath append _ } + } + + /** The parent loader to use for the interpreter.*/ + private[nsc] var explicitParentLoader: Option[ClassLoader] = None + + /** Retrieves the contents of resource "${id}.class.path" from `loader` + * (wrapped in Some) or None if the resource does not exist.*/ + private def getClasspath(id: String, loader: ClassLoader): Option[String] = + Option(loader).flatMap(ld => Option(ld.getResource(id + ".class.path"))).map { cp => + Source.fromURL(cp).mkString + } + // a wrapper for all Setting creators to keep our list up to date private def add[T <: Setting](s: T): T = { allSettings += s |