ServletServer.kt

  1. package com.hexagontk.http.server.servlet

  2. import com.hexagontk.core.text.AnsiColor.BLUE
  3. import com.hexagontk.core.text.AnsiEffect.BOLD
  4. import com.hexagontk.core.text.AnsiColor.CYAN
  5. import com.hexagontk.core.text.AnsiColor.MAGENTA
  6. import com.hexagontk.core.text.Ansi.RESET
  7. import com.hexagontk.core.Platform
  8. import com.hexagontk.core.Platform.cpuCount
  9. import com.hexagontk.core.Platform.hostName
  10. import com.hexagontk.core.Platform.localeCode
  11. import com.hexagontk.core.Platform.name
  12. import com.hexagontk.core.Platform.timeZone
  13. import com.hexagontk.core.Platform.totalMemory
  14. import com.hexagontk.core.Platform.usedMemory
  15. import com.hexagontk.core.Platform.version
  16. import com.hexagontk.core.text.prependIndent
  17. import com.hexagontk.core.require
  18. import com.hexagontk.http.server.HttpServer
  19. import com.hexagontk.http.server.serverBanner
  20. import com.hexagontk.http.handlers.HttpHandler
  21. import com.hexagontk.http.handlers.OnHandler
  22. import jakarta.servlet.*
  23. import java.util.*

  24. /**
  25.  * Adapter to run a router inside a Servlets container. It is not a standard engine as it is not
  26.  * started/stopped (not passed to an [HttpServer]).
  27.  */
  28. abstract class ServletServer(
  29.     private val handler: HttpHandler = OnHandler { this },
  30. ) : ServletContextListener {

  31.     override fun contextInitialized(sce: ServletContextEvent) {
  32.         val servletFilter = ServletFilter(handler)
  33.         // Let's be a good JEE citizen
  34.         val servletContext = sce.servletContext
  35.         servletFilter.init(object : FilterConfig {
  36.             val params = Hashtable<String, String>(1).apply { put("filterName", filterName) }
  37.             override fun getFilterName(): String = ServletFilter::class.java.name
  38.             override fun getServletContext(): ServletContext = servletContext
  39.             override fun getInitParameter(name: String): String = params.require(name)
  40.             override fun getInitParameterNames(): Enumeration<String> = params.keys()
  41.         })
  42.         val filter = servletContext.addFilter("filters", servletFilter)
  43.         filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType::class.java), true, "/*")
  44.     }

  45.     fun createBanner(
  46.         startUpTimestamp: Long = -1, banner: String = serverBanner, detailed: Boolean = false
  47.     ): String {
  48.         val server = "$BOLD$CYAN${javaClass.simpleName}$RESET"
  49.         val java = "$BOLD${BLUE}Java $version$RESET [$BLUE$name$RESET]"
  50.         val locale = "$BLUE$localeCode$RESET"
  51.         val timezone = "$BLUE${timeZone.id}$RESET"
  52.         val charsetValue = "$BLUE${Platform.charset}$RESET"
  53.         val start = if (startUpTimestamp < 0) "<undefined>" else startUpTimestamp.toString()
  54.         val startTime = "$BOLD$MAGENTA in $start ms$RESET"

  55.         val information = if (detailed)
  56.             detailBanner(server, java, locale, timezone, charsetValue, startTime)
  57.         else
  58.             """

  59.             Server Adapter: $server

  60.             🛠 Using $java
  61.             🌍 Locale: $locale Timezone: $timezone Charset: $charsetValue

  62.             ⏱️ Started$startTime
  63.             🚀 Served at a JEE Server

  64.             """

  65.         val fullBanner = banner + information.trimIndent()
  66.         return "\n" + fullBanner.prependIndent()
  67.     }

  68.     private fun detailBanner(
  69.         server: String,
  70.         java: String,
  71.         locale: String,
  72.         timezone: String,
  73.         charsetValue: String,
  74.         startTime: String
  75.     ): String {
  76.         val bootTime = "%01.3f".format(Platform.uptime() / 1e3)
  77.         val uptimeValue = "$BOLD$MAGENTA$bootTime s$RESET"
  78.         val jvmMemoryValue = "$BLUE${totalMemory()} KB$RESET"
  79.         val usedMemoryValue = "$BOLD$MAGENTA${usedMemory()} KB$RESET"
  80.         val hostnameValue = "$BLUE$hostName$RESET"
  81.         val cpuCountValue = "$BLUE$cpuCount$RESET"

  82.         return """

  83.             Server Adapter: $server

  84.             🖥️️ Running in '$hostnameValue' with $cpuCountValue CPUs $jvmMemoryValue of memory
  85.             🛠 Using $java
  86.             🌍 Locale: $locale Timezone: $timezone Charset: $charsetValue

  87.             ⏱️ Started$startTime (uptime: $uptimeValue) using $usedMemoryValue
  88.             🚀 Served at a JEE Server

  89.             """
  90.     }
  91. }