io.javalin.core.util.RouteOverviewUtil.kt Maven / Gradle / Ivy
/*
* Javalin - https://javalin.io
* Copyright 2017 David Åse
* Licensed under Apache 2.0: https://github.com/tipsy/javalin/blob/master/LICENSE
*/
package io.javalin.core.util
import io.javalin.Javalin
import io.javalin.apibuilder.CrudFunctionHandler
import io.javalin.core.event.HandlerMetaInfo
import io.javalin.core.event.WsHandlerMetaInfo
import io.javalin.core.security.RouteRole
import io.javalin.http.ContentType
import io.javalin.http.Context
import io.javalin.http.Handler
import java.util.*
data class RouteOverviewConfig(val path: String, val roles: Set)
class RouteOverviewRenderer(val app: Javalin) : Handler {
val handlerMetaInfoList = mutableListOf()
val wsHandlerMetaInfoList = mutableListOf()
init {
app.events { it.handlerAdded { handlerInfo -> handlerMetaInfoList.add(handlerInfo) } }
app.events { it.wsHandlerAdded { handlerInfo -> wsHandlerMetaInfoList.add(handlerInfo) } }
}
override fun handle(ctx: Context) {
if (ctx.header(Header.ACCEPT)?.lowercase(Locale.ROOT)?.contains(ContentType.JSON) == true) {
ctx.header("Content-Type", ContentType.JSON)
ctx.result(RouteOverviewUtil.createJsonOverview(handlerMetaInfoList, wsHandlerMetaInfoList))
} else {
ctx.html(RouteOverviewUtil.createHtmlOverview(handlerMetaInfoList, wsHandlerMetaInfoList))
}
}
}
object RouteOverviewUtil {
@JvmStatic
fun createHtmlOverview(handlerInfo: List, wsHandlerInfo: List): String {
return """
Method
Path
Handler
Roles
${
handlerInfo.map { (handlerType, path, handler, roles) ->
"""
$handlerType
$path
${handler.metaInfo}
$roles
"""
}.joinToString("")
}
${
wsHandlerInfo.map { (wsHandlerType, path, handler, roles) ->
"""
$wsHandlerType
$path
${handler.metaInfo}
$roles
"""
}.joinToString("")
}
"""
}
@JvmStatic
fun createJsonOverview(handlerInfo: List, wsHandlerInfo: List): String {
return """
{
"handlers": [
${
handlerInfo.map { (handlerType, path, handler, roles) ->
"""
{
"path": "$path",
"handlerType": "$handlerType",
"metaInfo": "$handler.metaInfo",
"roles": "$roles"
}
"""
}.joinToString(",")
}
],
"wsHandlers": [
${
wsHandlerInfo.map { (wsHandlerType, path, handler, roles) ->
"""
{
"path": "$path",
"handlerType": "$wsHandlerType",
"metaInfo": "$handler.metaInfo",
"roles": "$roles"
}
"""
}.joinToString(",")
}
]
}
"""
}
@JvmStatic
val Any.metaInfo: String
get() {
// this is just guesswork...
// every new version of Java or Kotlin seems to break something here
return when {
isClass -> (this as Class<*>).name + ".class"
isCrudFunction -> "ApiBuilder#crud::${(this as CrudFunctionHandler).function.value}"
isKotlinMethodReference -> {
val fieldName = this.javaClass.declaredFields.find { it.name == "function" || it.name == "\$tmp0" }!!.name
val field = this.javaClass.getDeclaredField(fieldName).apply { isAccessible = true }.get(this)
when (fieldName) {
"function" -> field.runMethod("getOwner").runMethod("getJClass").runMethod("getName").toString() + "::" + field.runMethod("getName")
else -> "${field.implementingClassName}::$lambdaSign"
}
}
isKotlinAnonymousLambda -> parentClass.name + "::" + lambdaSign
isKotlinField -> parentClass.name + "." + kotlinFieldName
hasMethodName -> parentClass.name + "::" + methodName
isJavaField -> parentClass.name + "." + javaFieldName
isJavaAnonymousLambda -> parentClass.name + "::" + lambdaSign
else -> implementingClassName + ".class"
}
}
}
private const val lambdaSign = "??? (anonymous lambda)"