diff options
Diffstat (limited to 'examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/ExternalJSEnv.scala')
-rw-r--r-- | examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/ExternalJSEnv.scala | 200 |
1 files changed, 0 insertions, 200 deletions
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/ExternalJSEnv.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/ExternalJSEnv.scala deleted file mode 100644 index e0aa557..0000000 --- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/ExternalJSEnv.scala +++ /dev/null @@ -1,200 +0,0 @@ -package scala.scalajs.sbtplugin.env - -import scala.scalajs.tools.io._ -import scala.scalajs.tools.classpath._ -import scala.scalajs.tools.env._ -import scala.scalajs.tools.logging._ - -import scala.scalajs.sbtplugin.JSUtils._ - -import java.io.{ Console => _, _ } -import scala.io.Source - -import scala.concurrent.{Future, Promise} -import scala.util.Try - -abstract class ExternalJSEnv( - final protected val additionalArgs: Seq[String], - final protected val additionalEnv: Map[String, String]) extends AsyncJSEnv { - - /** Printable name of this VM */ - protected def vmName: String - - /** Command to execute (on shell) for this VM */ - protected def executable: String - - protected class AbstractExtRunner(protected val classpath: CompleteClasspath, - protected val code: VirtualJSFile, protected val logger: Logger, - protected val console: JSConsole) { - - /** JS files used to setup VM */ - protected def initFiles(): Seq[VirtualJSFile] = Nil - - /** Sends required data to VM Stdin (can throw) */ - protected def sendVMStdin(out: OutputStream): Unit = {} - - /** VM arguments excluding executable. Override to adapt. - * Overrider is responsible to add additionalArgs. - */ - protected def getVMArgs(): Seq[String] = additionalArgs - - /** VM environment. Override to adapt. - * - * Default is `sys.env` and [[additionalEnv]] - */ - protected def getVMEnv(): Map[String, String] = - sys.env ++ additionalEnv - - /** Get files that are a library (i.e. that do not run anything) */ - protected def getLibJSFiles(): Seq[VirtualJSFile] = - initFiles() ++ classpath.allCode - - /** Get all files that are passed to VM (libraries and code) */ - protected def getJSFiles(): Seq[VirtualJSFile] = - getLibJSFiles() :+ code - - /** write a single JS file to a writer using an include fct if appropriate */ - protected def writeJSFile(file: VirtualJSFile, writer: Writer): Unit = { - // The only platform-independent way to do this in JS is to dump the file. - writer.write(file.content) - writer.write('\n') - } - - /** Pipe stdin and stdout from/to VM */ - final protected def pipeVMData(vmInst: Process): Unit = { - // Send stdin to VM. - val out = vmInst.getOutputStream() - try { sendVMStdin(out) } - finally { out.close() } - - // Pipe stdout to console - pipeToConsole(vmInst.getInputStream(), console) - - // We are probably done (stdin is closed). Report any errors - val errSrc = Source.fromInputStream(vmInst.getErrorStream(), "UTF-8") - try { errSrc.getLines.foreach(err => logger.error(err)) } - finally { errSrc.close } - } - - /** Wait for the VM to terminate, verify exit code */ - final protected def waitForVM(vmInst: Process): Unit = { - // Make sure we are done. - vmInst.waitFor() - - // Get return value and return - val retVal = vmInst.exitValue - if (retVal != 0) - sys.error(s"$vmName exited with code $retVal") - } - - protected def startVM(): Process = { - val vmArgs = getVMArgs() - val vmEnv = getVMEnv() - - val allArgs = executable +: vmArgs - val pBuilder = new ProcessBuilder(allArgs: _*) - - pBuilder.environment().clear() - for ((name, value) <- vmEnv) - pBuilder.environment().put(name, value) - - pBuilder.start() - } - - /** send a bunch of JS files to an output stream */ - final protected def sendJS(files: Seq[VirtualJSFile], - out: OutputStream): Unit = { - val writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8")) - try sendJS(files, writer) - finally writer.close() - } - - /** send a bunch of JS files to a writer */ - final protected def sendJS(files: Seq[VirtualJSFile], out: Writer): Unit = - files.foreach { writeJSFile(_, out) } - - /** pipe lines from input stream to JSConsole */ - final protected def pipeToConsole(in: InputStream, console: JSConsole) = { - val source = Source.fromInputStream(in, "UTF-8") - try { source.getLines.foreach(console.log _) } - finally { source.close() } - } - - } - - protected class ExtRunner(classpath: CompleteClasspath, code: VirtualJSFile, - logger: Logger, console: JSConsole - ) extends AbstractExtRunner(classpath, code, logger, console) - with JSRunner { - - def run(): Unit = { - val vmInst = startVM() - - pipeVMData(vmInst) - waitForVM(vmInst) - } - } - - protected class AsyncExtRunner(classpath: CompleteClasspath, - code: VirtualJSFile, logger: Logger, console: JSConsole - ) extends AbstractExtRunner(classpath, code, logger, console) - with AsyncJSRunner { - - private[this] var vmInst: Process = null - private[this] var ioThreadEx: Throwable = null - private[this] val promise = Promise[Unit] - - private[this] val thread = new Thread { - override def run(): Unit = { - // This thread should not be interrupted, so it is safe to use Trys - val pipeResult = Try(pipeVMData(vmInst)) - val vmComplete = Try(waitForVM(vmInst)) - - // Store IO exception - pipeResult recover { - case e => ioThreadEx = e - } - - // Chain Try's the other way: We want VM failure first, then IO failure - promise.complete(pipeResult orElse vmComplete) - } - } - - def start(): Future[Unit] = { - require(vmInst == null, "start() may only be called once") - vmInst = startVM() - thread.start() - promise.future - } - - def stop(): Unit = { - require(vmInst != null, "start() must have been called") - vmInst.destroy() - } - - def isRunning(): Boolean = { - require(vmInst != null, "start() must have been called") - // Emulate JDK 8 Process.isAlive - try { - vmInst.exitValue() - false - } catch { - case e: IllegalThreadStateException => - true - } - } - - def await(): Unit = { - require(vmInst != null, "start() must have been called") - thread.join() - waitForVM(vmInst) - - // At this point, the VM itself didn't fail. We need to check if - // anything bad happened while piping the data from the VM - - if (ioThreadEx != null) - throw ioThreadEx - } - } - -} |