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

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)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy