diff --git a/launch/Boot.scala b/launch/Boot.scala index 2bda82e66..992f991c5 100644 --- a/launch/Boot.scala +++ b/launch/Boot.scala @@ -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] } diff --git a/launch/Launch.scala b/launch/Launch.scala index d0c7ca248..0db955cfa 100644 --- a/launch/Launch.scala +++ b/launch/Launch.scala @@ -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 + ")")) } diff --git a/launch/interface/src/main/java/xsbti/Continue.java b/launch/interface/src/main/java/xsbti/Continue.java new file mode 100644 index 000000000..6c9ebf7ee --- /dev/null +++ b/launch/interface/src/main/java/xsbti/Continue.java @@ -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 {} \ No newline at end of file