ServletServer.kt
- package com.hexagontk.http.server.servlet
- import com.hexagontk.core.text.AnsiColor.BLUE
- import com.hexagontk.core.text.AnsiEffect.BOLD
- import com.hexagontk.core.text.AnsiColor.CYAN
- import com.hexagontk.core.text.AnsiColor.MAGENTA
- import com.hexagontk.core.text.Ansi.RESET
- import com.hexagontk.core.Platform
- import com.hexagontk.core.Platform.cpuCount
- import com.hexagontk.core.Platform.hostName
- import com.hexagontk.core.Platform.localeCode
- import com.hexagontk.core.Platform.name
- import com.hexagontk.core.Platform.timeZone
- import com.hexagontk.core.Platform.totalMemory
- import com.hexagontk.core.Platform.usedMemory
- import com.hexagontk.core.Platform.version
- import com.hexagontk.core.text.prependIndent
- import com.hexagontk.core.require
- import com.hexagontk.http.server.HttpServer
- import com.hexagontk.http.server.serverBanner
- import com.hexagontk.http.handlers.HttpHandler
- import com.hexagontk.http.handlers.OnHandler
- import jakarta.servlet.*
- 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 },
- ) : ServletContextListener {
- override fun contextInitialized(sce: ServletContextEvent) {
- 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, "/*")
- }
- fun createBanner(
- startUpTimestamp: Long = -1, banner: String = serverBanner, detailed: Boolean = false
- ): String {
- val server = "$BOLD$CYAN${javaClass.simpleName}$RESET"
- val java = "$BOLD${BLUE}Java $version$RESET [$BLUE$name$RESET]"
- val locale = "$BLUE$localeCode$RESET"
- val timezone = "$BLUE${timeZone.id}$RESET"
- val charsetValue = "$BLUE${Platform.charset}$RESET"
- val start = if (startUpTimestamp < 0) "<undefined>" else startUpTimestamp.toString()
- val startTime = "$BOLD$MAGENTA in $start ms$RESET"
- val information = if (detailed)
- detailBanner(server, java, locale, timezone, charsetValue, startTime)
- else
- """
- Server Adapter: $server
- 🛠 Using $java
- 🌍 Locale: $locale Timezone: $timezone Charset: $charsetValue
- ⏱️ Started$startTime
- 🚀 Served at a JEE Server
- """
- val fullBanner = banner + information.trimIndent()
- return "\n" + fullBanner.prependIndent()
- }
- private fun detailBanner(
- server: String,
- java: String,
- locale: String,
- timezone: String,
- charsetValue: String,
- startTime: String
- ): String {
- val bootTime = "%01.3f".format(Platform.uptime() / 1e3)
- val uptimeValue = "$BOLD$MAGENTA$bootTime s$RESET"
- val jvmMemoryValue = "$BLUE${totalMemory()} KB$RESET"
- val usedMemoryValue = "$BOLD$MAGENTA${usedMemory()} KB$RESET"
- val hostnameValue = "$BLUE$hostName$RESET"
- val cpuCountValue = "$BLUE$cpuCount$RESET"
- return """
- Server Adapter: $server
- 🖥️️ Running in '$hostnameValue' with $cpuCountValue CPUs $jvmMemoryValue of memory
- 🛠 Using $java
- 🌍 Locale: $locale Timezone: $timezone Charset: $charsetValue
- ⏱️ Started$startTime (uptime: $uptimeValue) using $usedMemoryValue
- 🚀 Served at a JEE Server
- """
- }
- }