package play.core.server
import com.typesafe.config.ConfigFactory
import play.api.http.{ Port, DefaultHttpErrorHandler }
import play.api.routing.Router
import scala.language.postfixOps
import play.api._
import play.api.mvc._
import play.core.{ DefaultWebCommands, ApplicationProvider }
import scala.util.{ Try, Success, Failure }
import scala.concurrent.Future
trait WebSocketable {
def (: String): String
def check: Boolean
}
trait Server extends ServerWithStop {
def mode: Mode.Mode
def getHandlerFor(request: RequestHeader): Either[Future[Result], (RequestHeader, Handler, Application)] = {
import scala.util.control.Exception
def sendHandler: Try[(RequestHeader, Handler, Application)] = {
try {
applicationProvider.get.map { application =>
application.requestHandler.handlerForRequest(request) match {
case (requestHeader, handler) => (requestHeader, handler, application)
}
}
} catch {
case e: ThreadDeath => throw e
case e: VirtualMachineError => throw e
case e: Throwable => Failure(e)
}
}
def logExceptionAndGetResult(e: Throwable) = {
DefaultHttpErrorHandler.onServerError(request, e)
}
Exception
.allCatch[Option[Future[Result]]]
.either(applicationProvider.handleWebCommand(request).map(Future.successful))
.left.map(logExceptionAndGetResult)
.right.flatMap(maybeResult => maybeResult.toLeft(())).right.flatMap { _ =>
sendHandler match {
case Failure(e) => Left(logExceptionAndGetResult(e))
case Success(v) => Right(v)
}
}
}
def applicationProvider: ApplicationProvider
def stop() {
Logger.shutdown()
}
def httpPort: Option[Int]
def httpsPort: Option[Int]
}
object Server {
def withApplication[T](application: Application, config: ServerConfig = ServerConfig(port = Some(0), mode = Mode.Test))(block: Port => T)(implicit provider: ServerProvider): T = {
Play.start(application)
val server = provider.createServer(config, application)
try {
block(new Port((server.httpPort orElse server.httpsPort).get))
} finally {
server.stop()
}
}
def withRouter[T](config: ServerConfig = ServerConfig(port = Some(0), mode = Mode.Test))(routes: PartialFunction[RequestHeader, Handler])(block: Port => T)(implicit provider: ServerProvider): T = {
val application = new BuiltInComponentsFromContext(ApplicationLoader.Context(
Environment.simple(path = config.rootDir, mode = config.mode),
None, new DefaultWebCommands(), Configuration(ConfigFactory.load())
)) {
def router = Router.from(routes)
}.application
withApplication(application, config)(block)
}
}
private[play] object JavaServerHelper {
def forRouter(router: Router, mode: Mode.Mode, port: Int): Server = {
val r = router
val application = new BuiltInComponentsFromContext(ApplicationLoader.Context(
Environment.simple(mode = mode),
None, new DefaultWebCommands(), Configuration(ConfigFactory.load())
)) {
def router = r
}.application
Play.start(application)
implicitly[ServerProvider].createServer(ServerConfig(mode = mode, port = Some(port)), application)
}
}