io.javalin.core.util.Util.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.http.Context
import io.javalin.http.InternalServerErrorResponse
import java.io.ByteArrayInputStream
import java.io.File
import java.net.URL
import java.net.URLEncoder
import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit
import java.util.*
import java.util.zip.Adler32
import java.util.zip.CheckedInputStream
object Util {
@JvmStatic
fun normalizeContextPath(contextPath: String) = ("/$contextPath").replace("/{2,}".toRegex(), "/").removeSuffix("/")
@JvmStatic
fun prefixContextPath(contextPath: String, path: String) = if (path == "*") path else ("$contextPath/$path").replace("/{2,}".toRegex(), "/")
fun classExists(className: String) = try {
Class.forName(className)
true
} catch (e: ClassNotFoundException) {
false
}
private fun serviceImplementationExists(className: String) = try {
val serviceClass = Class.forName(className)
val loader = ServiceLoader.load(serviceClass)
loader.any()
} catch (e: ClassNotFoundException) {
false
}
fun dependencyIsPresent(dependency: OptionalDependency) = try {
ensureDependencyPresent(dependency)
true
} catch (e: Exception) {
false
}
private val dependencyCheckCache = HashMap()
fun ensureDependencyPresent(dependency: OptionalDependency, startupCheck: Boolean = false) {
if (dependencyCheckCache[dependency.testClass] == true) {
return
}
if (!classExists(dependency.testClass)) {
val message = missingDependencyMessage(dependency)
if (startupCheck) {
throw IllegalStateException(message)
} else {
JavalinLogger.warn(message)
throw InternalServerErrorResponse(message)
}
}
dependencyCheckCache[dependency.testClass] = true
}
internal fun missingDependencyMessage(dependency: OptionalDependency) = """|
|-------------------------------------------------------------------
|Missing dependency '${dependency.displayName}'. Add the dependency.
|
|pom.xml:
|
| ${dependency.groupId}
| ${dependency.artifactId}
| ${dependency.version}
|
|
|build.gradle:
|implementation group: '${dependency.groupId}', name: '${dependency.artifactId}', version: '${dependency.version}'
|
|Find the latest version here:
|https://search.maven.org/search?q=${URLEncoder.encode("g:" + dependency.groupId + " AND a:" + dependency.artifactId, "UTF-8")}
|-------------------------------------------------------------------""".trimMargin()
fun pathToList(pathString: String): List = pathString.split("/").filter { it.isNotEmpty() }
@JvmStatic
fun printHelpfulMessageIfLoggerIsMissing() {
if (!loggingLibraryExists()) {
System.err.println("""
|-------------------------------------------------------------------
|${missingDependencyMessage(OptionalDependency.SLF4JSIMPLE)}
|-------------------------------------------------------------------
|OR
|-------------------------------------------------------------------
|${missingDependencyMessage(OptionalDependency.SLF4J_PROVIDER_API)} and
|${missingDependencyMessage(OptionalDependency.SLF4J_PROVIDER_SIMPLE)}
|-------------------------------------------------------------------
|Visit https://javalin.io/documentation#logging if you need more help""".trimMargin())
}
}
fun loggingLibraryExists(): Boolean {
return classExists(OptionalDependency.SLF4JSIMPLE.testClass) ||
serviceImplementationExists(OptionalDependency.SLF4J_PROVIDER_API.testClass)
}
@JvmStatic
fun logJavalinBanner(showBanner: Boolean) {
if (showBanner) JavalinLogger.info("\n" + """
| __ __ _ __ __
| / /____ _ _ __ ____ _ / /(_)____ / // /
| __ / // __ `/| | / // __ `// // // __ \ / // /_
|/ /_/ // /_/ / | |/ // /_/ // // // / / / /__ __/
|\____/ \__,_/ |___/ \__,_//_//_//_/ /_/ /_/
|
| https://javalin.io/documentation
|""".trimMargin())
}
@JvmStatic
fun logJavalinVersion() = try {
val properties = Properties().also {
val propertiesPath = "META-INF/maven/io.javalin/javalin/pom.properties"
it.load(this.javaClass.classLoader.getResourceAsStream(propertiesPath))
}
val (version, buildTime) = listOf(properties.getProperty("version")!!, properties.getProperty("buildTime")!!)
JavalinLogger.startup("You are running Javalin $version (released ${formatBuildTime(buildTime)}).")
} catch (e: Exception) {
// it's not that important
}
private fun formatBuildTime(buildTime: String): String? = try {
val (release, now) = listOf(Instant.parse(buildTime), Instant.now())
val formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy").withLocale(Locale.US).withZone(ZoneId.of("Z"))
formatter.format(release) + if (now.isAfter(release.plus(90, ChronoUnit.DAYS))) {
". Your Javalin version is ${ChronoUnit.DAYS.between(release, now)} days old. Consider checking for a newer version."
} else ""
} catch (e: Exception) {
null // it's not that important
}
fun getChecksumAndReset(inputStream: ByteArrayInputStream): String {
inputStream.mark(Int.MAX_VALUE) //it's all in memory so there is no readAheadLimit
val cis = CheckedInputStream(inputStream, Adler32())
var byte = cis.read()
while (byte > -1) {
byte = cis.read()
}
inputStream.reset()
return cis.checksum.value.toString()
}
@JvmStatic
fun getResourceUrl(path: String): URL? = this.javaClass.classLoader.getResource(path)
@JvmStatic
fun getWebjarPublicPath(ctx: Context, dependency: OptionalDependency): String {
return "${ctx.contextPath()}/webjars/${dependency.artifactId}/${dependency.version}"
}
@JvmStatic
fun assertWebjarInstalled(dependency: OptionalDependency) = try {
getWebjarResourceUrl(dependency)
} catch (e: Exception) {
JavalinLogger.warn(missingDependencyMessage(dependency))
}
@JvmStatic
fun getWebjarResourceUrl(dependency: OptionalDependency): URL? {
val webjarBaseUrl = "META-INF/resources/webjars"
return getResourceUrl("$webjarBaseUrl/${dependency.artifactId}/${dependency.version}")
}
fun getFileUrl(path: String): URL? = if (File(path).exists()) File(path).toURI().toURL() else null
fun isKotlinClass(clazz: Class<*>): Boolean {
try {
for (annotation in clazz.declaredAnnotations) {
// Note: annotation.simpleClass can be used if kotlin-reflect is available.
if (annotation.annotationClass.toString().contains("kotlin.Metadata")) {
return true
}
}
} catch (ignored: Exception) {
}
return false
}
@JvmStatic
fun getPort(e: Exception) = e.message!!.takeLastWhile { it != ':' }
fun findByClass(map: Map, T>, exceptionClass: Class): T? = map.getOrElse(exceptionClass) {
var superclass = exceptionClass.superclass
while (superclass != null) {
if (map.containsKey(superclass)) {
return map[superclass]
}
superclass = superclass.superclass
}
return null
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy