mirror of https://github.com/sbt/sbt.git
97 lines
3.5 KiB
Scala
97 lines
3.5 KiB
Scala
/* sbt -- Simple Build Tool
|
|
* Copyright 2008, 2009 Mark Harrah, Vesa Vilhonen
|
|
*/
|
|
package sbt
|
|
|
|
import java.io.File
|
|
import java.net.{URL, URLClassLoader}
|
|
import java.lang.reflect.{Method, Modifier}
|
|
import Modifier.{isPublic, isStatic}
|
|
import classpath.ClasspathUtilities
|
|
|
|
trait ScalaRun
|
|
{
|
|
def run(mainClass: String, classpath: Iterable[Path], 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] =
|
|
{
|
|
val scalaOptions = classpathOption(classpath) ::: mainClass :: options.toList
|
|
val exitCode = config.outputStrategy match {
|
|
case Some(strategy) => Fork.scala(config.javaHome, config.runJVMOptions, config.scalaJars, scalaOptions, config.workingDirectory, strategy)
|
|
case None => Fork.scala(config.javaHome, config.runJVMOptions, config.scalaJars, scalaOptions, config.workingDirectory, LoggedOutput(log))
|
|
}
|
|
processExitCode(exitCode, "runner")
|
|
}
|
|
private def classpathOption(classpath: Iterable[Path]) = "-cp" :: Path.makeString(classpath) :: Nil
|
|
private def processExitCode(exitCode: Int, label: String) =
|
|
{
|
|
if(exitCode == 0)
|
|
None
|
|
else
|
|
Some("Nonzero exit code returned from " + label + ": " + exitCode)
|
|
}
|
|
}
|
|
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) =
|
|
{
|
|
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)
|
|
{
|
|
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) }
|
|
}
|
|
private def invokeMain(loader: ClassLoader, main: Method, options: Seq[String])
|
|
{
|
|
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
|
|
}
|
|
}
|
|
|
|
/** 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) =
|
|
runner.run(mainClass, classpath, options, log)
|
|
|
|
/** Executes the given function, trapping calls to System.exit. */
|
|
def executeTrapExit(f: => Unit, log: Logger): Option[String] =
|
|
{
|
|
val exitCode = TrapExit(f, log)
|
|
if(exitCode == 0)
|
|
{
|
|
log.debug("Exited with code 0")
|
|
None
|
|
}
|
|
else
|
|
Some("Nonzero exit code: " + exitCode)
|
|
}
|
|
} |