ServletServer.kt
- package com.hexagonkt.http.server.servlet
- import com.hexagonkt.core.text.AnsiColor.BLUE
- import com.hexagonkt.core.text.AnsiEffect.BOLD
- import com.hexagonkt.core.text.AnsiColor.CYAN
- import com.hexagonkt.core.text.AnsiColor.MAGENTA
- import com.hexagonkt.core.text.Ansi.RESET
- import com.hexagonkt.core.Jvm
- import com.hexagonkt.core.text.prependIndent
- import com.hexagonkt.core.require
- import com.hexagonkt.core.logging.Logger
- import com.hexagonkt.http.server.HttpServer
- import com.hexagonkt.http.server.HttpServerSettings
- import com.hexagonkt.http.handlers.HttpHandler
- import com.hexagonkt.http.handlers.OnHandler
- import jakarta.servlet.*
- import java.lang.management.ManagementFactory
- import java.util.*
- /**
- * Adapter to run a router inside a Servlets container. It is not a standard engine as it is not
- * started/stopped (not passed to an [HttpServer]).
- */
- abstract class ServletServer(
- private val handler: HttpHandler = OnHandler { this },
- private val settings: HttpServerSettings = HttpServerSettings(),
- ) : ServletContextListener {
- private companion object {
- val logger: Logger = Logger(ServletServer::class)
- }
- override fun contextInitialized(sce: ServletContextEvent) {
- val startTimestamp = System.nanoTime()
- val servletFilter = ServletFilter(handler)
- // Let's be a good JEE citizen
- val servletContext = sce.servletContext
- servletFilter.init(object : FilterConfig {
- val params = Hashtable<String, String>(1).apply { put("filterName", filterName) }
- override fun getFilterName(): String = ServletFilter::class.java.name
- override fun getServletContext(): ServletContext = servletContext
- override fun getInitParameter(name: String): String = params.require(name)
- override fun getInitParameterNames(): Enumeration<String> = params.keys()
- })
- val filter = servletContext.addFilter("filters", servletFilter)
- filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType::class.java), true, "/*")
- logger.info { "Server started\n${createBanner(System.nanoTime() - startTimestamp)}" }
- }
- override fun contextDestroyed(sce: ServletContextEvent?) {
- logger.info { "Server context destroyed" }
- }
- private fun createBanner(startUpTimestamp: Long): String {
- val heap = ManagementFactory.getMemoryMXBean().heapMemoryUsage
- val jvmMemory = "%,d".format(heap.init / 1024)
- val usedMemory = "%,d".format(heap.used / 1024)
- val bootTime = "%01.3f".format(ManagementFactory.getRuntimeMXBean().uptime / 1e3)
- val startUpTime = "%,.0f".format(startUpTimestamp / 1e6)
- val serverAdapterValue = "$BOLD$CYAN${javaClass.simpleName}$RESET"
- val hostnameValue = "$BLUE${Jvm.hostName}$RESET"
- val cpuCountValue = "$BLUE${Jvm.cpuCount}$RESET"
- val jvmMemoryValue = "$BLUE$jvmMemory$RESET"
- val javaVersionValue = "$BOLD${BLUE}Java ${Jvm.version}$RESET [$BLUE${Jvm.name}$RESET]"
- val localeValue = "$BLUE${Jvm.localeCode}$RESET"
- val timezoneValue = "$BLUE${Jvm.timeZone.id}$RESET"
- val charsetValue = "$BLUE${Jvm.charset}$RESET"
- val bootTimeValue = "$BOLD$MAGENTA$bootTime s$RESET"
- val startUpTimeValue = "$BOLD$MAGENTA$startUpTime ms$RESET"
- val usedMemoryValue = "$BOLD$MAGENTA$usedMemory KB$RESET"
- val information = """
- Server Adapter: $serverAdapterValue
- 🖥️️ Running in '$hostnameValue' with $cpuCountValue CPUs $jvmMemoryValue KB
- 🛠 Using $javaVersionValue
- 🌍 Locale: $localeValue Timezone: $timezoneValue Charset: $charsetValue
- ⏱ Started in $bootTimeValue (server: $startUpTimeValue) using $usedMemoryValue
- 🚀 Served at a JEE Server
- """.trimIndent()
- val banner = (settings.banner?.let { "$it\n" } ?: HttpServer.banner) + information
- return banner.prependIndent()
- }
- }