
scalut.daemon.Bootstrap.scala Maven / Gradle / Ivy
The newest version!
package scalut.daemon
import java.util.Scanner
import org.apache.commons.daemon.{Daemon, DaemonContext}
import scalut.util.StringHelper
import scalut.logging.LoggingProvider
import scala.concurrent.Await
import scala.concurrent.duration.Duration
import scala.util.Try
abstract class Bootstrap extends Daemon with LoggingProvider {
protected lazy val server: Server = newServer()
protected def newServer(): Server
/**
* Java Service Wrapper for Linux.
*/
def jswApplyCmd(args: Array[String]): Unit = {
val cmd =
if (args.length > 0)
args.last
else
"start"
cmd match {
case "start" => start()
case "stop" => stop()
case _ => println(s"Unknown command '$cmd'.")
}
}
/**
* Run `cmd` and wait for next command from keyboard.
*/
protected def waitKeyboardCommand(cmd: String = StringHelper.EMPTY): Unit = {
Console.in.mark(0)
val scanner = new Scanner(Console.in)
def welcome(): Unit = {
println("Type command...")
}
lazy val listener: Server.EventListener = (source: Server, event: Server.State.Type) =>
event match {
case Server.State.STARTED =>
println("Type 'stop' to stop server.")
case Server.State.STOPPED =>
server.unsubscribe(listener)
scanner.close()
case _ => // ignore
}
server.subscribe(listener)
// Уже подписаны на изменения сервера,
// запускаем первую команду и ждем...
if (StringHelper.nonEmpty(cmd))
jswApplyCmd(Array(cmd))
// Wait until receive command from keyboard
// Throw IllegalStateException when scanner closed, so surround in Try.
while (Try(scanner.hasNextLine).getOrElse(false)) {
scanner.nextLine() match {
// При destroy или stop выполнится обработчик события
// и если нужно закроет сканер.
case StringHelper.EMPTY => // ничего не делаем
case line => jswApplyCmd(Array(line))
}
if (!server.isStopped)
welcome()
}
}
/**
* For Windows.
*/
def windowsService(args: Array[String]): Unit = {
var cmd = "start"
if (args.length > 0)
cmd = args(0)
cmd match {
case "start" =>
windowsStart()
// Например, если в терминале или в IDE сделали прерывание выполнения.
//sys.addShutdownHook {windowsStop()}
case "stop" => windowsStop()
case _ =>
}
}
protected def block(): Unit = {
while (!server.isStopped) {
// don't return until stopped
this.synchronized {
try {
this.wait(30000) // wait 30 sec and check if stopped
}
catch {
case ex: InterruptedException =>
log.debug("windowsStart: Thread interrupted, probably means we're shutting down now.", ex)
}
}
}
}
protected def unblock(): Unit = {
/*while (!server.isStopped) {
this.synchronized {
try {
this.wait(1000) // wait 1 sec and check if stopped
}
catch {
case ex: InterruptedException =>
logger.debug("windowsStop: Thread interrupted, probably means we're shutting down now.", ex)
}
}
}*/
this.synchronized {
// stop the start loop
this.notify()
}
}
def windowsStart(): Unit = {
log.debug("windowsStart called")
start()
block()
}
def windowsStop(): Unit = {
log.debug("windowsStop called")
stop()
unblock()
}
// Implementing the Daemon interface is not required for Windows but is for Linux.
def init(context: DaemonContext): Unit = {
log.debug(s"Daemon initialized with arguments: ${context.getArguments}.")
}
def start(): Unit = {
log.debug("Daemon start")
if (server.isStopped) {
log.debug("Starting the Engine")
Await.result(server.start(), Duration.Inf)
log.debug("Engine started")
}
}
def stop(): Unit = {
log.debug("Daemon stop")
if (!server.isStopped) {
log.debug("Stopping the Engine")
Await.result(server.stop(), Duration.Inf)
log.debug("Engine stopped")
}
}
def destroy(): Unit = {
log.debug("Daemon destroy")
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy