io.squark.yggdrasil.core.cdi.ServletBeanObserver.kt Maven / Gradle / Ivy
package io.squark.yggdrasil.core.cdi
import io.undertow.servlet.Servlets
import io.undertow.servlet.api.FilterInfo
import io.undertow.servlet.api.ListenerInfo
import io.undertow.servlet.api.ServletContainerInitializerInfo
import io.undertow.servlet.api.ServletInfo
import org.jboss.resteasy.plugins.server.servlet.HttpServlet30Dispatcher
import java.lang.reflect.Modifier
import java.util.EventListener
import javax.enterprise.context.ApplicationScoped
import javax.enterprise.event.Observes
import javax.enterprise.inject.spi.AnnotatedType
import javax.enterprise.inject.spi.Extension
import javax.enterprise.inject.spi.ProcessAnnotatedType
import javax.enterprise.inject.spi.WithAnnotations
import javax.servlet.DispatcherType
import javax.servlet.Filter
import javax.servlet.Servlet
import javax.servlet.ServletContainerInitializer
import javax.servlet.annotation.HandlesTypes
import javax.servlet.annotation.WebFilter
import javax.servlet.annotation.WebListener
import javax.servlet.annotation.WebServlet
import kotlin.reflect.KClass
/**
* CDI Extension to observe for Servlet beans.
*
* Created by Erik Håkansson on 2017-04-05.
* Copyright 2017
*/
@ApplicationScoped class ServletBeanObserver : Extension {
//Blacklisted, most likely due to other initialization.
private val blackListedServlets = setOf>(HttpServlet30Dispatcher::class.java)
internal val servlets: MutableList = mutableListOf()
internal val filters: MutableList, Array>> = mutableListOf()
internal val listeners: MutableList = mutableListOf()
internal val servletContainerInitializers: MutableList = mutableListOf()
/**
* Method that observes for Servlet beans
*/
fun observeWebServlets(@WithAnnotations(WebServlet::class) @Observes event: ProcessAnnotatedType) {
if (!blackListedServlets.contains(event.annotatedType.javaClass)) {
servlets += toServletInfo(event.annotatedType)
}
}
/**
* Method that observes for Filter beans
*/
fun observeWebFilters(@WithAnnotations(WebFilter::class) @Observes event: ProcessAnnotatedType) {
filters += toFilterInfo(event.annotatedType)
}
/**
* Method that observes for EventListener beans
*/
fun observeWebListeners(@WithAnnotations(
WebListener::class) @Observes event: ProcessAnnotatedType) {
listeners += toListenerInfo(event.annotatedType)
}
/**
* Method that observes for ServletContainerInitializer beans
*/
fun observerServletContainerInitializers(@Observes event: ProcessAnnotatedType) {
if (!event.annotatedType.javaClass.isInterface && !Modifier.isAbstract(event.annotatedType.javaClass.modifiers))
servletContainerInitializers += toServletContainerInitializerInfo(event.annotatedType)
}
private fun toServletContainerInitializerInfo(
annotatedType: AnnotatedType): ServletContainerInitializerInfo {
val handlesTypesAnnotation: HandlesTypes? = annotatedType.getAnnotation(HandlesTypes::class.java)
val arrayOfKClasses: Array>? = handlesTypesAnnotation?.value
val arrayOfClasses = arrayOfKClasses?.map { it.java }
return ServletContainerInitializerInfo(annotatedType.javaClass, arrayOfClasses?.toSet())
}
private fun toListenerInfo(annotatedType: AnnotatedType): ListenerInfo {
return Servlets.listener(annotatedType.javaClass)
}
private fun toServletInfo(annotatedType: AnnotatedType): ServletInfo {
val webServletAnnotation = annotatedType.getAnnotation(WebServlet::class.java)
val servletInfo = Servlets.servlet(webServletAnnotation.name, annotatedType.javaClass)
servletInfo.addMappings(webServletAnnotation.value.asList())
servletInfo.addMappings(webServletAnnotation.urlPatterns.asList())
for (initParam in webServletAnnotation.initParams) servletInfo.initParams += initParam.name to initParam.value
servletInfo.let {
it.loadOnStartup = webServletAnnotation.loadOnStartup
it.isAsyncSupported = webServletAnnotation.asyncSupported
}
return servletInfo
}
private fun toFilterInfo(
annotatedType: AnnotatedType): Triple, Array> {
val webFilterAnnotation = annotatedType.getAnnotation(WebFilter::class.java)
val filterInfo = Servlets.filter(webFilterAnnotation.filterName, annotatedType.javaClass)
for (initParam in webFilterAnnotation.initParams) filterInfo.initParams += initParam.name to initParam.value
val filterMappingInfos = mutableListOf()
filterMappingInfos += webFilterAnnotation.value.map { FilterMappingInfo(FilterMappingType.URL, it) }
filterMappingInfos += webFilterAnnotation.urlPatterns.map { FilterMappingInfo(FilterMappingType.URL, it) }
filterMappingInfos += webFilterAnnotation.servletNames.map { FilterMappingInfo(FilterMappingType.Servlet, it) }
filterInfo.isAsyncSupported = webFilterAnnotation.asyncSupported
return Triple(filterInfo, filterMappingInfos, webFilterAnnotation.dispatcherTypes)
}
internal enum class FilterMappingType {
URL, Servlet
}
internal data class FilterMappingInfo(val type: FilterMappingType, val mapping: String)
}