package play.core.server
import java.io._
import java.util.Properties
import play.api._
import play.core._
import play.core.server._
import play.utils.Threads
import scala.util.control.NonFatal
import scala.util.Success
object ProdServerStart {
def main(args: Array[String]) {
val process = new RealServerProcess(args)
start(process)
}
def start(process: ServerProcess): ServerWithStop = {
try {
val config: ServerConfig = readServerConfigSettings(process)
val pidFile = createPidFile(process, config.configuration)
val application: Application = {
val environment = Environment(config.rootDir, process.classLoader, Mode.Prod)
val context = ApplicationLoader.createContext(environment)
val loader = ApplicationLoader(context)
loader.load(context)
}
Play.start(application)
val serverProvider: ServerProvider = ServerProvider.fromConfiguration(process.classLoader, config.configuration)
val server = serverProvider.createServer(config, application)
process.addShutdownHook {
server.stop()
pidFile.foreach(_.delete())
assert(!pidFile.exists(_.exists), "PID file should not exist!")
}
server
} catch {
case ServerStartException(message, cause) =>
process.exit(message, cause)
case NonFatal(e) =>
process.exit("Oops, cannot start the server.", cause = Some(e))
}
}
def readServerConfigSettings(process: ServerProcess): ServerConfig = {
val configuration: Configuration = {
val rootDirArg: Option[File] = process.args.headOption.map(new File(_))
val rootDirConfig = rootDirArg.fold(Map.empty[String, String])(dir => ServerConfig.rootDirConfig(dir))
Configuration.load(process.classLoader, process.properties, rootDirConfig, true)
}
val rootDir: File = {
val path = configuration.getString("play.server.dir").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 = configuration.getString("play.server.http.port").flatMap {
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 = configuration.getInt("play.server.https.port")
if (!(httpPort orElse httpsPort).isDefined) throw ServerStartException("Must provide either an HTTP or HTTPS port")
val address = configuration.getString("play.server.http.address").getOrElse("0.0.0.0")
ServerConfig(
rootDir = rootDir,
port = httpPort,
sslPort = httpsPort,
address = address,
mode = Mode.Prod,
properties = process.properties,
configuration = configuration
)
}
def createPidFile(process: ServerProcess, configuration: Configuration): Option[File] = {
val pidFilePath = configuration.getString("play.server.pidfile.path").getOrElse(throw ServerStartException("Pid file path not configured"))
if (pidFilePath == "/dev/null") None else {
val pidFile = new File(pidFilePath).getAbsoluteFile
if (pidFile.exists) {
throw ServerStartException(s"This application is already running (Or delete ${pidFile.getPath} file).")
}
val pid = process.pid getOrElse (throw ServerStartException("Couldn't determine current process's pid"))
val out = new FileOutputStream(pidFile)
try out.write(pid.getBytes) finally out.close()
Some(pidFile)
}
}
}