fixes #226. allow launched applications to signal the launcher's job is complete by returning Continue

This commit is contained in:
Mark Harrah 2011-10-14 19:52:54 -04:00
parent 2c9e943daa
commit bb84e32291
3 changed files with 25 additions and 18 deletions

View File

@ -16,27 +16,28 @@ object Boot
}
// this arrangement is because Scala 2.7.7 does not properly optimize away
// the tail recursion in a catch statement
final def run(args: Array[String]): Unit = run(runImpl(args))
private def runImpl(args: Array[String]): Array[String] =
{
final def run(args: Array[String]): Unit = runImpl(args) match {
case Some(newArgs) => run(newArgs)
case None => ()
}
private def runImpl(args: Array[String]): Option[Array[String]] =
try
{
Launch(args.toList)
System.exit(0).asInstanceOf[Nothing]
}
Launch(args.toList) map exit
catch
{
case b: BootException => errorAndExit(b.toString)
case r: xsbti.RetrieveException => errorAndExit("Error: " + r.getMessage)
case r: xsbti.FullReload => r.arguments
case r: xsbti.FullReload => Some(r.arguments)
case e =>
e.printStackTrace
errorAndExit(Pre.prefixError(e.toString))
}
}
private def errorAndExit(msg: String): Nothing =
{
System.out.println(msg)
System.exit(1).asInstanceOf[Nothing]
exit(1)
}
private def exit(code: Int): Nothing =
System.exit(code).asInstanceOf[Nothing]
}

View File

@ -11,17 +11,17 @@ import scala.collection.immutable.List
object Launch
{
def apply(arguments: List[String]): Unit = apply( (new File("")).getAbsoluteFile , arguments )
def apply(arguments: List[String]): Option[Int] = apply( (new File("")).getAbsoluteFile , arguments )
def apply(currentDirectory: File, arguments: List[String]): Unit =
def apply(currentDirectory: File, arguments: List[String]): Option[Int] =
Configuration.find(arguments, currentDirectory) match { case (configLocation, newArguments) => configured(currentDirectory, configLocation, newArguments) }
def configured(currentDirectory: File, configLocation: URL, arguments: List[String]): Unit =
def configured(currentDirectory: File, configLocation: URL, arguments: List[String]): Option[Int] =
{
val config = Configuration.parse(configLocation, currentDirectory)
Find(config, currentDirectory) match { case (resolved, baseDirectory) => parsed(baseDirectory, resolved, arguments) }
}
def parsed(currentDirectory: File, parsed: LaunchConfiguration, arguments: List[String]): Unit =
def parsed(currentDirectory: File, parsed: LaunchConfiguration, arguments: List[String]): Option[Int] =
{
val propertiesFile = parsed.boot.properties
import parsed.boot.{enableQuick, promptCreate, promptFill}
@ -31,7 +31,7 @@ object Launch
Initialize.fill(propertiesFile, parsed.appProperties)
initialized(currentDirectory, parsed, arguments)
}
def initialized(currentDirectory: File, parsed: LaunchConfiguration, arguments: List[String]): Unit =
def initialized(currentDirectory: File, parsed: LaunchConfiguration, arguments: List[String]): Option[Int] =
{
parsed.logging.debug("Parsed configuration: " + parsed)
val resolved = ResolveValues(parsed)
@ -39,7 +39,7 @@ object Launch
explicit(currentDirectory, resolved, arguments)
}
def explicit(currentDirectory: File, explicit: LaunchConfiguration, arguments: List[String]): Unit =
def explicit(currentDirectory: File, explicit: LaunchConfiguration, arguments: List[String]): Option[Int] =
launch( run(Launcher(explicit)) ) (
new RunConfiguration(explicit.getScalaVersion, explicit.app.toID, currentDirectory, arguments) )
@ -63,11 +63,12 @@ object Launch
}
if(f.exists) f.delete()
}
final def launch(run: RunConfiguration => xsbti.MainResult)(config: RunConfiguration)
final def launch(run: RunConfiguration => xsbti.MainResult)(config: RunConfiguration): Option[Int] =
{
run(config) match
{
case e: xsbti.Exit => System.exit(e.code)
case e: xsbti.Exit => Some(e.code)
case c: xsbti.Continue => None
case r: xsbti.Reboot => launch(run)(new RunConfiguration(r.scalaVersion, r.app, r.baseDirectory, r.arguments.toList))
case x => throw new BootException("Invalid main result: " + x + (if(x eq null) "" else " (class: " + x.getClass + ")"))
}

View File

@ -0,0 +1,5 @@
package xsbti;
/** A launched application returns an instance of this class in order to communicate to the launcher
* that the application's main thread is finished and the launcher's work is complete, but it should not exit.*/
public interface Continue extends MainResult {}