Make 'run' reuse warm Scala class loader and same JLine as sbt

This commit is contained in:
Mark Harrah 2010-03-04 13:30:13 -05:00
parent 250a05c4a3
commit 3493aa5285
4 changed files with 39 additions and 4 deletions

3
.gitignore vendored
View File

@ -1,2 +1,5 @@
LazyJettyRun6.scala
LazyJettyRun7.scala
install/project/boot/
scripted/project/boot/
project/plugins/project/

View File

@ -19,7 +19,7 @@ class SbtProject(info: ProjectInfo) extends DefaultProject(info) with test.SbtSc
//val publishTo = Resolver.file("technically", new File("/var/dbwww/repo/"))
val technically = Resolver.url("technically.us", new URL("http://databinder.net/repo/"))(Resolver.ivyStylePatterns)
override def compileOptions = Nil
override def compileOptions = CompileOption("-Xno-varargs-conversion") :: Nil
/** configuration of scripted testing **/
// Set to false to show logging as it happens without buffering, true to buffer until it completes and only show if the task fails.

View File

@ -250,7 +250,7 @@ abstract class BasicScalaProject extends ScalaProject with BasicDependencyProjec
fork match
{
case Some(fr: ForkScalaRun) => new ForkRun(fr)
case _ => new Run(buildCompiler)
case _ => new Run(buildScalaInstance)
}
}

View File

@ -10,6 +10,7 @@ import scala.tools.nsc.util.ClassPath
import java.io.File
import java.net.{URL, URLClassLoader}
import java.lang.reflect.Modifier.{isPublic, isStatic}
trait ScalaRun
{
@ -35,14 +36,45 @@ class ForkRun(config: ForkScalaRun) extends ScalaRun
Some("Nonzero exit code returned from " + label + ": " + exitCode)
}
}
class Run(compiler: xsbt.AnalyzingCompiler) extends ScalaRun
class Run(instance: xsbt.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 execute = compiler.run(Set() ++ classpath.map(_.asFile), mainClass, options, log)
log.info("Running " + mainClass + " " + options.mkString(" "))
def execute =
try { run0(mainClass, classpath, options, log) }
catch { case e: java.lang.reflect.InvocationTargetException => throw e.getCause }
Run.executeTrapExit( execute, log )
}
private def run0(mainClassName: String, classpath: Iterable[Path], options: Seq[String], log: Logger)
{
val loader = getLoader(classpath, log)
val main = getMainMethod(mainClassName, loader)
val currentThread = Thread.currentThread
val oldLoader = Thread.currentThread.getContextClassLoader()
currentThread.setContextClassLoader(loader)
try { main.invoke(null, options.toArray[String].asInstanceOf[Array[String]] ) }
finally { currentThread.setContextClassLoader(oldLoader) }
}
def getMainMethod(mainClassName: String, loader: ClassLoader) =
{
val mainClass = Class.forName(mainClassName, true, loader)
val method = mainClass.getMethod("main", classOf[Array[String]])
val modifiers = method.getModifiers
if(!isPublic(modifiers)) throw new NoSuchMethodException(mainClassName + ".main is not public")
if(!isStatic(modifiers)) throw new NoSuchMethodException(mainClassName + ".main is not static")
method
}
def getLoader(classpath: Iterable[Path], log: Logger) =
{
val classpathURLs = classpath.toSeq.map(_.asURL).toArray
log.debug(" Classpath:\n\t" + classpathURLs.mkString("\n\t"))
new URLClassLoader( classpathURLs, instance.loader)
}
}
/** This module is an interface to starting the scala interpreter or runner.*/