src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt

changeset 184
e8eecee6aadf
parent 179
623c340058f3
child 195
9c7aff3cbb14
     1.1 --- a/src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt	Sat Jan 23 14:47:59 2021 +0100
     1.2 +++ b/src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt	Fri Apr 02 11:59:14 2021 +0200
     1.3 @@ -25,45 +25,106 @@
     1.4  
     1.5  package de.uapcore.lightpit
     1.6  
     1.7 +import de.uapcore.lightpit.dao.DataAccessObject
     1.8 +import de.uapcore.lightpit.viewmodel.NavMenu
     1.9 +import de.uapcore.lightpit.viewmodel.View
    1.10 +import javax.servlet.http.HttpServletRequest
    1.11 +import javax.servlet.http.HttpServletResponse
    1.12 +import javax.servlet.http.HttpSession
    1.13  import kotlin.math.min
    1.14  
    1.15 -/**
    1.16 - * Maps requests to methods.
    1.17 - *
    1.18 - * This annotation is used to annotate methods within classes which
    1.19 - * override [AbstractServlet].
    1.20 - */
    1.21 -@MustBeDocumented
    1.22 -@Retention(AnnotationRetention.RUNTIME)
    1.23 -@Target(AnnotationTarget.FUNCTION)
    1.24 -annotation class RequestMapping(
    1.25 +typealias MappingMethod = (HttpRequest, DataAccessObject) -> Unit
    1.26 +typealias PathParameters = Map<String, String>
    1.27 +
    1.28 +class HttpRequest(
    1.29 +    val request: HttpServletRequest,
    1.30 +    val response: HttpServletResponse,
    1.31 +    val pathParams: PathParameters = emptyMap()
    1.32 +) {
    1.33 +    val session: HttpSession = request.session
    1.34 +
    1.35 +    val remoteUser: String? = request.remoteUser
    1.36  
    1.37      /**
    1.38 -     * Specifies the HTTP method.
    1.39 +     * The name of the content page.
    1.40       *
    1.41 -     * @return the HTTP method handled by the annotated Java method
    1.42 +     * @see Constants#REQ_ATTR_CONTENT_PAGE
    1.43       */
    1.44 -    val method: HttpMethod,
    1.45 +    var contentPage = ""
    1.46 +        set(value) {
    1.47 +            field = value
    1.48 +            request.setAttribute(Constants.REQ_ATTR_CONTENT_PAGE, jspPath(value))
    1.49 +        }
    1.50  
    1.51      /**
    1.52 -     * Specifies the request path relative to the module path.
    1.53 -     * The trailing slash is important.
    1.54 -     * A node may start with a dollar ($) sign.
    1.55 -     * This part of the path is then treated as an path parameter.
    1.56 -     * Path parameters can be obtained by including the [PathParameters] type in the signature.
    1.57 +     * A list of additional style sheets.
    1.58       *
    1.59 -     * @return the request path the annotated method should handle
    1.60 +     * @see Constants#REQ_ATTR_STYLESHEET
    1.61       */
    1.62 -    val requestPath: String = "/"
    1.63 -)
    1.64 +    var styleSheets = emptyList<String>()
    1.65 +        set(value) {
    1.66 +            field = value
    1.67 +            request.setAttribute(Constants.REQ_ATTR_STYLESHEET,
    1.68 +                value.map { it.withExt(".css") }
    1.69 +            )
    1.70 +        }
    1.71  
    1.72 -class PathParameters : HashMap<String, String>()
    1.73 +    /**
    1.74 +     * The name of the navigation menu JSP.
    1.75 +     *
    1.76 +     * @see Constants#REQ_ATTR_NAVIGATION
    1.77 +     */
    1.78 +    var navigationMenu: NavMenu? = null
    1.79 +        set(value) {
    1.80 +            field = value
    1.81 +            request.setAttribute(Constants.REQ_ATTR_NAVIGATION, navigationMenu)
    1.82 +        }
    1.83 +
    1.84 +    var redirectLocation = ""
    1.85 +        set(value) {
    1.86 +            field = value
    1.87 +            request.setAttribute(Constants.REQ_ATTR_REDIRECT_LOCATION, baseHref + value)
    1.88 +        }
    1.89 +
    1.90 +    /**
    1.91 +     * The view object.
    1.92 +     *
    1.93 +     * @see Constants#REQ_ATTR_VIEWMODEL
    1.94 +     */
    1.95 +    var view: View? = null
    1.96 +        set(value) {
    1.97 +            field = value
    1.98 +            request.setAttribute(Constants.REQ_ATTR_VIEWMODEL, value)
    1.99 +        }
   1.100 +
   1.101 +    /**
   1.102 +     * The base path of this application.
   1.103 +     */
   1.104 +    val baseHref get() = "${request.scheme}://${request.serverName}:${request.serverPort}${request.contextPath}/"
   1.105 +
   1.106 +    private fun String.withExt(ext: String) = if (endsWith(ext)) this else plus(ext)
   1.107 +    private fun jspPath(name: String) = Constants.JSP_PATH_PREFIX.plus(name).withExt(".jsp")
   1.108 +
   1.109 +    fun param(name: String): String? = request.getParameter(name)
   1.110 +    fun paramArray(name: String): Array<String> = request.getParameterValues(name) ?: emptyArray()
   1.111 +
   1.112 +    fun render(page: String? = null) {
   1.113 +        page?.let { contentPage = it }
   1.114 +        request.getRequestDispatcher(jspPath("site")).forward(request, response)
   1.115 +    }
   1.116 +
   1.117 +    fun renderCommit(location: String? = null) {
   1.118 +        location?.let { redirectLocation = it }
   1.119 +        contentPage = Constants.JSP_COMMIT_SUCCESSFUL
   1.120 +        render()
   1.121 +    }
   1.122 +}
   1.123  
   1.124  /**
   1.125   * A path pattern optionally containing placeholders.
   1.126   *
   1.127   * The special directories . and .. are disallowed in the pattern.
   1.128 - * Placeholders start with a $ sign.
   1.129 + * Placeholders start with a % sign.
   1.130   *
   1.131   * @param pattern the pattern
   1.132   */
   1.133 @@ -91,7 +152,7 @@
   1.134          for (i in nodePatterns.indices) {
   1.135              val pattern = nodePatterns[i]
   1.136              val node = nodes[i]
   1.137 -            if (pattern.startsWith("$")) continue
   1.138 +            if (pattern.startsWith("%")) continue
   1.139              if (pattern != node) return false
   1.140          }
   1.141          return true
   1.142 @@ -106,12 +167,12 @@
   1.143       * @see .matches
   1.144       */
   1.145      fun obtainPathParameters(path: String): PathParameters {
   1.146 -        val params = PathParameters()
   1.147 +        val params = mutableMapOf<String, String>()
   1.148          val nodes = parse(path)
   1.149          for (i in 0 until min(nodes.size, nodePatterns.size)) {
   1.150              val pattern = nodePatterns[i]
   1.151              val node = nodes[i]
   1.152 -            if (pattern.startsWith("$")) {
   1.153 +            if (pattern.startsWith("%")) {
   1.154                  params[pattern.substring(1)] = node
   1.155              }
   1.156          }
   1.157 @@ -121,8 +182,8 @@
   1.158      override fun hashCode(): Int {
   1.159          val str = StringBuilder()
   1.160          for (node in nodePatterns) {
   1.161 -            if (node.startsWith("$")) {
   1.162 -                str.append("/$")
   1.163 +            if (node.startsWith("%")) {
   1.164 +                str.append("/%")
   1.165              } else {
   1.166                  str.append('/')
   1.167                  str.append(node)
   1.168 @@ -138,7 +199,7 @@
   1.169              for (i in nodePatterns.indices) {
   1.170                  val left = nodePatterns[i]
   1.171                  val right = other.nodePatterns[i]
   1.172 -                if (left.startsWith("$") && right.startsWith("$")) continue
   1.173 +                if (left.startsWith("%") && right.startsWith("%")) continue
   1.174                  if (left != right) return false
   1.175              }
   1.176              return true

mercurial