32 import java.util.* |
32 import java.util.* |
33 import javax.servlet.http.HttpServlet |
33 import javax.servlet.http.HttpServlet |
34 import javax.servlet.http.HttpServletRequest |
34 import javax.servlet.http.HttpServletRequest |
35 import javax.servlet.http.HttpServletResponse |
35 import javax.servlet.http.HttpServletResponse |
36 |
36 |
37 abstract class AbstractServlet : LoggingTrait, HttpServlet() { |
37 abstract class AbstractServlet : HttpServlet() { |
|
38 |
|
39 protected val logger = MyLogger() |
38 |
40 |
39 /** |
41 /** |
40 * Contains the GET request mappings. |
42 * Contains the GET request mappings. |
41 */ |
43 */ |
42 private val getMappings = mutableMapOf<PathPattern, MappingMethod>() |
44 private val getMappings = mutableMapOf<PathPattern, MappingMethod>() |
66 val candidates = mappings.filter { it.key.matches(requestPath) } |
68 val candidates = mappings.filter { it.key.matches(requestPath) } |
67 return if (candidates.isEmpty()) { |
69 return if (candidates.isEmpty()) { |
68 Pair(PathPattern(requestPath), ::notFound) |
70 Pair(PathPattern(requestPath), ::notFound) |
69 } else { |
71 } else { |
70 if (candidates.size > 1) { |
72 if (candidates.size > 1) { |
71 logger().warn("Ambiguous mapping for request path '{}'", requestPath) |
73 logger.warn("Ambiguous mapping for request path '{0}'", requestPath) |
72 } |
74 } |
73 candidates.entries.first().toPair() |
75 candidates.entries.first().toPair() |
74 } |
76 } |
75 } |
77 } |
76 |
78 |
80 resp: HttpServletResponse, |
82 resp: HttpServletResponse, |
81 dao: DataAccessObject |
83 dao: DataAccessObject |
82 ) { |
84 ) { |
83 val params = mapping.first.obtainPathParameters(sanitizedRequestPath(req)) |
85 val params = mapping.first.obtainPathParameters(sanitizedRequestPath(req)) |
84 val method = mapping.second |
86 val method = mapping.second |
85 logger().trace("invoke {}", method) |
87 logger.trace("invoke {0}", method) |
86 method(HttpRequest(req, resp, params), dao) |
88 method(HttpRequest(req, resp, params), dao) |
87 } |
89 } |
88 |
90 |
89 private fun sanitizedRequestPath(req: HttpServletRequest) = req.pathInfo ?: "/" |
91 private fun sanitizedRequestPath(req: HttpServletRequest) = req.pathInfo ?: "/" |
90 |
92 |
103 val availableLanguages = availableLanguages() |
105 val availableLanguages = availableLanguages() |
104 val reqLocale = req.locale |
106 val reqLocale = req.locale |
105 val sessionLocale = if (availableLanguages.contains(reqLocale)) reqLocale else availableLanguages.first() |
107 val sessionLocale = if (availableLanguages.contains(reqLocale)) reqLocale else availableLanguages.first() |
106 session.setAttribute(Constants.SESSION_ATTR_LANGUAGE, sessionLocale) |
108 session.setAttribute(Constants.SESSION_ATTR_LANGUAGE, sessionLocale) |
107 resp.locale = sessionLocale |
109 resp.locale = sessionLocale |
108 logger().debug( |
110 logger.debug( |
109 "Setting language for new session {}: {}", session.id, sessionLocale.displayLanguage |
111 "Setting language for new session {0}: {1}", session.id, sessionLocale.displayLanguage |
110 ) |
112 ) |
111 } else { |
113 } else { |
112 val sessionLocale = session.getAttribute(Constants.SESSION_ATTR_LANGUAGE) as Locale |
114 val sessionLocale = session.getAttribute(Constants.SESSION_ATTR_LANGUAGE) as Locale |
113 resp.locale = sessionLocale |
115 resp.locale = sessionLocale |
114 logger().trace("Continuing session {} with language {}", session.id, sessionLocale) |
116 logger.trace("Continuing session {0} with language {1}", session.id, sessionLocale) |
115 } |
117 } |
116 |
118 |
117 // set some internal request attributes |
119 // set some internal request attributes |
118 val http = HttpRequest(req, resp) |
120 val http = HttpRequest(req, resp) |
119 val fullPath = req.servletPath + Optional.ofNullable(req.pathInfo).orElse("") |
121 val fullPath = req.servletPath + Optional.ofNullable(req.pathInfo).orElse("") |
148 try { |
150 try { |
149 connection.autoCommit = false |
151 connection.autoCommit = false |
150 invokeMapping(findMapping(mappings, req), req, resp, dao) |
152 invokeMapping(findMapping(mappings, req), req, resp, dao) |
151 connection.commit() |
153 connection.commit() |
152 } catch (ex: SQLException) { |
154 } catch (ex: SQLException) { |
153 logger().warn("Database transaction failed (Code {}): {}", ex.errorCode, ex.message) |
155 logger.warn("Database transaction failed (Code {0}): {1}", ex.errorCode, ex.message) |
154 logger().debug("Details: ", ex) |
156 logger.debug("Details: ", ex) |
155 resp.sendError( |
157 resp.sendError( |
156 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, |
158 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, |
157 "Unhandled Transaction Error - Code: " + ex.errorCode |
159 "Unhandled Transaction Error - Code: " + ex.errorCode |
158 ) |
160 ) |
159 connection.rollback() |
161 connection.rollback() |
160 } |
162 } |
161 } |
163 } |
162 } catch (ex: SQLException) { |
164 } catch (ex: SQLException) { |
163 logger().error("Severe Database Exception (Code {}): {}", ex.errorCode, ex.message) |
165 logger.error("Severe Database Exception (Code {0}): {1}", ex.errorCode, ex.message) |
164 logger().debug("Details: ", ex) |
166 logger.debug("Details: ", ex) |
165 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Database Error - Code: " + ex.errorCode) |
167 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Database Error - Code: " + ex.errorCode) |
166 } |
168 } |
167 } |
169 } |
168 |
170 |
169 override fun doGet(req: HttpServletRequest, resp: HttpServletResponse) { |
171 override fun doGet(req: HttpServletRequest, resp: HttpServletResponse) { |