All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.javalin.core.util.RouteOverviewUtil.kt Maven / Gradle / Ivy

The newest version!
/*
 * 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.Context
import io.javalin.Handler
import io.javalin.Javalin

class RouteOverviewRenderer(val app: Javalin) : Handler {
    override fun handle(ctx: Context) {
        ctx.html(RouteOverviewUtil.createHtmlOverview(app))
    }
}

object RouteOverviewUtil {

    @JvmStatic
    fun createHtmlOverview(app: Javalin): String {
        return """
        
        
        
            
                ${app.handlerMetaInfo.map { (httpMethod, path, handler, roles) ->
            """
                    
                    """
        }.joinToString("")}
            
Method Path Handler Roles
$httpMethod $path ${handler.metaInfo} $roles
""" } @JvmStatic val Any.metaInfo: String get() { // this is just guesswork... return when { isClass -> (this as Class<*>).name + ".class" isKotlinMethodReference -> { val f = this.javaClass.getDeclaredField("function") .apply { isAccessible = true } .get(this) f.runMethod("getOwner").runMethod("getJClass").runMethod("getName").toString() + "::" + f.runMethod("getName") } isKotlinAnonymousLambda -> parentClass.name + "::" + lambdaSign isKotlinField -> parentClass.name + "." + kotlinFieldName isJavaMethodReference -> parentClass.name + "::" + methodName isJavaField -> parentClass.name + "." + javaFieldName isJavaAnonymousLambda -> parentClass.name + "::" + lambdaSign else -> implementingClassName + ".class" } } } private val Any.kotlinFieldName // this is most likely a very stupid solution get() = this.javaClass.toString().removePrefix(this.parentClass.toString() + "$").takeWhile { it != '$' } private val Any.javaFieldName: String? get() = try { parentClass.declaredFields.find { it.isAccessible = true; it.get(it) == this }?.name } catch (ignored: Exception) { // Nothing really matters. null } private val Any.methodName: String? // broken in jdk9+ since ConstantPool has been removed get() { // val constantPool = Class::class.java.getDeclaredMethod("getConstantPool").apply { isAccessible = true }.invoke(javaClass) as ConstantPool // for (i in constantPool.size downTo 0) { // try { // val name = constantPool.getMemberRefInfoAt(i)[1] // // Autogenerated ($), constructor, or kotlin's check (fix maybe?) // if (name.contains("(\\$||checkParameterIsNotNull)".toRegex())) { // continue // } else { // return name // } // } catch (ignored: Exception) { // } // } return null } private const val lambdaSign = "??? (anonymous lambda)" private val Any.parentClass: Class<*> get() = Class.forName(this.javaClass.name.takeWhile { it != '$' }) private val Any.implementingClassName: String? get() = this.javaClass.name private val Any.isClass: Boolean get() = this is Class<*> private val Any.isKotlinAnonymousLambda: Boolean get() = this.javaClass.enclosingMethod != null private val Any.isKotlinMethodReference: Boolean get() = this.javaClass.declaredFields.any { it.name == "function" } private val Any.isKotlinField: Boolean get() = this.javaClass.fields.any { it.name == "INSTANCE" } private val Any.isJavaAnonymousLambda: Boolean get() = this.javaClass.isSynthetic private val Any.isJavaMethodReference: Boolean get() = this.methodName != null private val Any.isJavaField: Boolean get() = this.javaFieldName != null private fun Any.runMethod(name: String): Any = this.javaClass.getMethod(name).apply { isAccessible = true }.invoke(this)




© 2015 - 2025 Weber Informatics LLC | Privacy Policy