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

changeset 184
e8eecee6aadf
parent 179
623c340058f3
child 195
9c7aff3cbb14
--- a/src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt	Sat Jan 23 14:47:59 2021 +0100
+++ b/src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt	Fri Apr 02 11:59:14 2021 +0200
@@ -25,45 +25,106 @@
 
 package de.uapcore.lightpit
 
+import de.uapcore.lightpit.dao.DataAccessObject
+import de.uapcore.lightpit.viewmodel.NavMenu
+import de.uapcore.lightpit.viewmodel.View
+import javax.servlet.http.HttpServletRequest
+import javax.servlet.http.HttpServletResponse
+import javax.servlet.http.HttpSession
 import kotlin.math.min
 
-/**
- * Maps requests to methods.
- *
- * This annotation is used to annotate methods within classes which
- * override [AbstractServlet].
- */
-@MustBeDocumented
-@Retention(AnnotationRetention.RUNTIME)
-@Target(AnnotationTarget.FUNCTION)
-annotation class RequestMapping(
+typealias MappingMethod = (HttpRequest, DataAccessObject) -> Unit
+typealias PathParameters = Map<String, String>
+
+class HttpRequest(
+    val request: HttpServletRequest,
+    val response: HttpServletResponse,
+    val pathParams: PathParameters = emptyMap()
+) {
+    val session: HttpSession = request.session
+
+    val remoteUser: String? = request.remoteUser
+
+    /**
+     * The name of the content page.
+     *
+     * @see Constants#REQ_ATTR_CONTENT_PAGE
+     */
+    var contentPage = ""
+        set(value) {
+            field = value
+            request.setAttribute(Constants.REQ_ATTR_CONTENT_PAGE, jspPath(value))
+        }
+
+    /**
+     * A list of additional style sheets.
+     *
+     * @see Constants#REQ_ATTR_STYLESHEET
+     */
+    var styleSheets = emptyList<String>()
+        set(value) {
+            field = value
+            request.setAttribute(Constants.REQ_ATTR_STYLESHEET,
+                value.map { it.withExt(".css") }
+            )
+        }
 
     /**
-     * Specifies the HTTP method.
+     * The name of the navigation menu JSP.
      *
-     * @return the HTTP method handled by the annotated Java method
+     * @see Constants#REQ_ATTR_NAVIGATION
      */
-    val method: HttpMethod,
+    var navigationMenu: NavMenu? = null
+        set(value) {
+            field = value
+            request.setAttribute(Constants.REQ_ATTR_NAVIGATION, navigationMenu)
+        }
+
+    var redirectLocation = ""
+        set(value) {
+            field = value
+            request.setAttribute(Constants.REQ_ATTR_REDIRECT_LOCATION, baseHref + value)
+        }
 
     /**
-     * Specifies the request path relative to the module path.
-     * The trailing slash is important.
-     * A node may start with a dollar ($) sign.
-     * This part of the path is then treated as an path parameter.
-     * Path parameters can be obtained by including the [PathParameters] type in the signature.
+     * The view object.
      *
-     * @return the request path the annotated method should handle
+     * @see Constants#REQ_ATTR_VIEWMODEL
+     */
+    var view: View? = null
+        set(value) {
+            field = value
+            request.setAttribute(Constants.REQ_ATTR_VIEWMODEL, value)
+        }
+
+    /**
+     * The base path of this application.
      */
-    val requestPath: String = "/"
-)
+    val baseHref get() = "${request.scheme}://${request.serverName}:${request.serverPort}${request.contextPath}/"
+
+    private fun String.withExt(ext: String) = if (endsWith(ext)) this else plus(ext)
+    private fun jspPath(name: String) = Constants.JSP_PATH_PREFIX.plus(name).withExt(".jsp")
+
+    fun param(name: String): String? = request.getParameter(name)
+    fun paramArray(name: String): Array<String> = request.getParameterValues(name) ?: emptyArray()
 
-class PathParameters : HashMap<String, String>()
+    fun render(page: String? = null) {
+        page?.let { contentPage = it }
+        request.getRequestDispatcher(jspPath("site")).forward(request, response)
+    }
+
+    fun renderCommit(location: String? = null) {
+        location?.let { redirectLocation = it }
+        contentPage = Constants.JSP_COMMIT_SUCCESSFUL
+        render()
+    }
+}
 
 /**
  * A path pattern optionally containing placeholders.
  *
  * The special directories . and .. are disallowed in the pattern.
- * Placeholders start with a $ sign.
+ * Placeholders start with a % sign.
  *
  * @param pattern the pattern
  */
@@ -91,7 +152,7 @@
         for (i in nodePatterns.indices) {
             val pattern = nodePatterns[i]
             val node = nodes[i]
-            if (pattern.startsWith("$")) continue
+            if (pattern.startsWith("%")) continue
             if (pattern != node) return false
         }
         return true
@@ -106,12 +167,12 @@
      * @see .matches
      */
     fun obtainPathParameters(path: String): PathParameters {
-        val params = PathParameters()
+        val params = mutableMapOf<String, String>()
         val nodes = parse(path)
         for (i in 0 until min(nodes.size, nodePatterns.size)) {
             val pattern = nodePatterns[i]
             val node = nodes[i]
-            if (pattern.startsWith("$")) {
+            if (pattern.startsWith("%")) {
                 params[pattern.substring(1)] = node
             }
         }
@@ -121,8 +182,8 @@
     override fun hashCode(): Int {
         val str = StringBuilder()
         for (node in nodePatterns) {
-            if (node.startsWith("$")) {
-                str.append("/$")
+            if (node.startsWith("%")) {
+                str.append("/%")
             } else {
                 str.append('/')
                 str.append(node)
@@ -138,7 +199,7 @@
             for (i in nodePatterns.indices) {
                 val left = nodePatterns[i]
                 val right = other.nodePatterns[i]
-                if (left.startsWith("$") && right.startsWith("$")) continue
+                if (left.startsWith("%") && right.startsWith("%")) continue
                 if (left != right) return false
             }
             return true

mercurial