|
Play Framework/Scala example source code file (ServerStart.scala)
The ServerStart.scala Play Framework example source code/* * Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com> */ package play.core.server import java.io._ import play.api.Mode import play.core._ import play.utils.Threads import scala.util.control.NonFatal /** * Helper for starting a Play server and application. The `main` method * is the entry point to a Play server running in production mode. The * `mainDev*` methods are used to start a server running in development * mode. */ trait ServerStart { /** * The ServerProvider to use if not overridden by a system property. */ protected def defaultServerProvider: ServerProvider /** * Creates an ApplicationProvider for prod mode. Needed so we can mock * out the ApplicationProvider for testing. */ protected def createApplicationProvider(config: ServerConfig): ApplicationProvider = { new StaticApplication(config.rootDir) } /** * Start a prod mode server from the command line. Calls `start`. */ def main(args: Array[String]) { val process = new RealServerProcess(args) start(process) } /** * Starts a Play server and application for the given process. The settings * for the server are based on values passed on the command line and in * various system properties. Crash out by exiting the given process if there * are any problems. * @param process The process (real or abstract) to use for starting the * server. */ def start(process: ServerProcess): ServerWithStop = { try { // Read settings val config = readServerConfigSettings(process) val serverProvider = readServerProviderSetting(process) // Get the party started! createPidFile(process, config.rootDir) val appProvider = createApplicationProvider(config) val server = serverProvider.createServer(config, appProvider) process.addShutdownHook { server.stop() } server } catch { case ServerStartException(message, cause) => process.exit(message, cause) case NonFatal(e) => process.exit("Oops, cannot start the server.", cause = Some(e)) } } /** * Read the server config from the current process's command * line args and system properties. */ def readServerConfigSettings(process: ServerProcess): ServerConfig = { val rootDir: File = { val argumentPath = process.args.headOption val propertyPath = process.prop("user.dir") val path = argumentPath orElse propertyPath getOrElse (throw ServerStartException("No root server path supplied")) val file = new File(path) if (!(file.exists && file.isDirectory)) { throw ServerStartException(s"Bad root server path: $path") } file } val httpPort = process.prop("http.port").fold[Option[Int]](Some(9000)) { case "disabled" => None case str => val i = try Integer.parseInt(str) catch { case _: NumberFormatException => throw ServerStartException(s"Invalid HTTP port: $str") } Some(i) } val httpsPort = process.prop("https.port").map { str => try Integer.parseInt(str) catch { case _: NumberFormatException => throw ServerStartException(s"Invalid HTTPS port: $str") } } if (!(httpPort orElse httpsPort).isDefined) throw ServerStartException("Must provide either an HTTP or HTTPS port") val address = process.prop("http.address").getOrElse("0.0.0.0") ServerConfig( rootDir = rootDir, port = httpPort, sslPort = httpsPort, address = address, mode = Mode.Prod, properties = process.properties ) } /** * Read the ServerProvider setting from the given process's * properties. If not provided, defaults to the result of * `defaultServerProvider`. */ def readServerProviderSetting(process: ServerProcess): ServerProvider = { process.prop("server.provider").map { className => val clazz = try process.classLoader.loadClass(className) catch { case _: ClassNotFoundException => throw ServerStartException(s"Couldn't find ServerProvider class '$className'") } if (!classOf[ServerProvider].isAssignableFrom(clazz)) throw ServerStartException(s"Class ${clazz.getName} must implement ServerProvider interface") val ctor = try clazz.getConstructor() catch { case _: NoSuchMethodException => throw ServerStartException(s"ServerProvider class ${clazz.getName} must have a public default constructor") } ctor.newInstance().asInstanceOf[ServerProvider] }.getOrElse(defaultServerProvider) } /** * Create a pid file for the current process, and register a hook * to delete the file on process termination. */ def createPidFile(process: ServerProcess, applicationPath: File): Unit = { val pid = process.pid getOrElse (throw ServerStartException("Couldn't determine current process's pid")) val pidFileProperty = process.prop("pidfile.path").map(new File(_)) val defaultPidFile = new File(applicationPath, "RUNNING_PID") val pidFile = (pidFileProperty getOrElse defaultPidFile).getAbsoluteFile if (pidFile.getAbsolutePath != "/dev/null") { if (pidFile.exists) { throw ServerStartException(s"This application is already running (Or delete ${pidFile.getPath} file).") } val out = new FileOutputStream(pidFile) try out.write(pid.getBytes) finally out.close() // Delete the pid file when the process shuts down process.addShutdownHook { pidFile.delete() } } } /** * Provides an HTTPS-only server for the dev environment. * * <p>This method uses simple Java types so that it can be used with reflection by code * compiled with different versions of Scala. */ def mainDevOnlyHttpsMode( buildLink: BuildLink, buildDocHandler: BuildDocHandler, httpsPort: Int): ServerWithStop = { mainDev(buildLink, buildDocHandler, None, Some(httpsPort)) } /** * Provides an HTTP server for the dev environment * * <p>This method uses simple Java types so that it can be used with reflection by code * compiled with different versions of Scala. */ def mainDevHttpMode( buildLink: BuildLink, buildDocHandler: BuildDocHandler, httpPort: Int): ServerWithStop = { mainDev(buildLink, buildDocHandler, Some(httpPort), Option(System.getProperty("https.port")).map(Integer.parseInt(_))) } private def mainDev( buildLink: BuildLink, buildDocHandler: BuildDocHandler, httpPort: Option[Int], httpsPort: Option[Int]): ServerWithStop = { Threads.withContextClassLoader(this.getClass.getClassLoader) { try { val process = new RealServerProcess(args = Seq.empty) val serverProvider = readServerProviderSetting(process) val config = ServerConfig( rootDir = buildLink.projectPath, port = httpPort, sslPort = httpsPort, mode = Mode.Dev, properties = process.properties ) val appProvider = new ReloadableApplication(buildLink, buildDocHandler) serverProvider.createServer(config, appProvider) } catch { case e: ExceptionInInitializerError => throw e.getCause } } } } final case class ServerStartException(message: String, cause: Option[Throwable] = None) extends Exception(message, cause.orNull) Other Play Framework source code examplesHere is a short list of links related to this Play Framework ServerStart.scala source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.