51 */ |
51 */ |
52 public abstract class AbstractLightPITServlet extends HttpServlet { |
52 public abstract class AbstractLightPITServlet extends HttpServlet { |
53 |
53 |
54 private static final Logger LOG = LoggerFactory.getLogger(AbstractLightPITServlet.class); |
54 private static final Logger LOG = LoggerFactory.getLogger(AbstractLightPITServlet.class); |
55 |
55 |
56 private static final String SITE_JSP = Functions.jspPath("site"); |
56 private static final String SITE_JSP = jspPath("site"); |
57 |
57 |
58 |
58 |
59 @FunctionalInterface |
59 @FunctionalInterface |
60 protected interface SQLFindFunction<K, T> { |
60 protected interface SQLFindFunction<K, T> { |
61 T apply(K key) throws SQLException; |
61 T apply(K key) throws SQLException; |
100 * @param connection the SQL connection |
100 * @param connection the SQL connection |
101 * @return a set of data access objects |
101 * @return a set of data access objects |
102 */ |
102 */ |
103 private DataAccessObjects createDataAccessObjects(Connection connection) throws SQLException { |
103 private DataAccessObjects createDataAccessObjects(Connection connection) throws SQLException { |
104 final var df = (DataSourceProvider) getServletContext().getAttribute(DataSourceProvider.Companion.getSC_ATTR_NAME()); |
104 final var df = (DataSourceProvider) getServletContext().getAttribute(DataSourceProvider.Companion.getSC_ATTR_NAME()); |
105 if (df.getDialect() == DatabaseDialect.Postgres) { |
105 if (df.getDialect() == DataSourceProvider.Dialect.Postgres) { |
106 return new PGDataAccessObjects(connection); |
106 return new PGDataAccessObjects(connection); |
107 } |
107 } |
108 throw new UnsupportedOperationException("Non-exhaustive if-else - this is a bug."); |
108 throw new UnsupportedOperationException("Non-exhaustive if-else - this is a bug."); |
109 } |
109 } |
110 |
110 |
236 * @param req the servlet request object |
236 * @param req the servlet request object |
237 * @param pageName the name of the content page |
237 * @param pageName the name of the content page |
238 * @see Constants#REQ_ATTR_CONTENT_PAGE |
238 * @see Constants#REQ_ATTR_CONTENT_PAGE |
239 */ |
239 */ |
240 protected void setContentPage(HttpServletRequest req, String pageName) { |
240 protected void setContentPage(HttpServletRequest req, String pageName) { |
241 req.setAttribute(Constants.REQ_ATTR_CONTENT_PAGE, Functions.jspPath(pageName)); |
241 req.setAttribute(Constants.REQ_ATTR_CONTENT_PAGE, jspPath(pageName)); |
242 } |
242 } |
243 |
243 |
244 /** |
244 /** |
245 * Sets the navigation menu. |
245 * Sets the navigation menu. |
246 * |
246 * |
247 * @param req the servlet request object |
247 * @param req the servlet request object |
248 * @param jspName the name of the menu's jsp file |
248 * @param jspName the name of the menu's jsp file |
249 * @see Constants#REQ_ATTR_NAVIGATION |
249 * @see Constants#REQ_ATTR_NAVIGATION |
250 */ |
250 */ |
251 protected void setNavigationMenu(HttpServletRequest req, String jspName) { |
251 protected void setNavigationMenu(HttpServletRequest req, String jspName) { |
252 req.setAttribute(Constants.REQ_ATTR_NAVIGATION, Functions.jspPath(jspName)); |
252 req.setAttribute(Constants.REQ_ATTR_NAVIGATION, jspPath(jspName)); |
253 } |
253 } |
254 |
254 |
255 /** |
255 /** |
256 * @param req the servlet request object |
256 * @param req the servlet request object |
257 * @param location the location where to redirect |
257 * @param location the location where to redirect |
258 * @see Constants#REQ_ATTR_REDIRECT_LOCATION |
258 * @see Constants#REQ_ATTR_REDIRECT_LOCATION |
259 */ |
259 */ |
260 protected void setRedirectLocation(HttpServletRequest req, String location) { |
260 protected void setRedirectLocation(HttpServletRequest req, String location) { |
261 if (location.startsWith("./")) { |
261 if (location.startsWith("./")) { |
262 location = location.replaceFirst("\\./", Functions.baseHref(req)); |
262 location = location.replaceFirst("\\./", baseHref(req)); |
263 } |
263 } |
264 req.setAttribute(Constants.REQ_ATTR_REDIRECT_LOCATION, location); |
264 req.setAttribute(Constants.REQ_ATTR_REDIRECT_LOCATION, location); |
265 } |
265 } |
266 |
266 |
267 /** |
267 /** |
275 * |
275 * |
276 * @param req the servlet request object |
276 * @param req the servlet request object |
277 * @param stylesheet the name of the stylesheet |
277 * @param stylesheet the name of the stylesheet |
278 */ |
278 */ |
279 public void setStylesheet(HttpServletRequest req, String stylesheet) { |
279 public void setStylesheet(HttpServletRequest req, String stylesheet) { |
280 req.setAttribute(Constants.REQ_ATTR_STYLESHEET, Functions.enforceExt(stylesheet, ".css")); |
280 req.setAttribute(Constants.REQ_ATTR_STYLESHEET, enforceExt(stylesheet, ".css")); |
281 } |
281 } |
282 |
282 |
283 /** |
283 /** |
284 * Sets the view model object. |
284 * Sets the view model object. |
285 * The type must match the expected type in the JSP file. |
285 * The type must match the expected type in the JSP file. |
382 |
382 |
383 protected void renderSite(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { |
383 protected void renderSite(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { |
384 req.getRequestDispatcher(SITE_JSP).forward(req, resp); |
384 req.getRequestDispatcher(SITE_JSP).forward(req, resp); |
385 } |
385 } |
386 |
386 |
|
387 protected Optional<String[]> availableLanguages() { |
|
388 return Optional.ofNullable(getServletContext().getInitParameter(Constants.CTX_ATTR_LANGUAGES)).map((x) -> x.split("\\s*,\\s*")); |
|
389 } |
|
390 |
|
391 private static String baseHref(HttpServletRequest req) { |
|
392 return String.format("%s://%s:%d%s/", |
|
393 req.getScheme(), |
|
394 req.getServerName(), |
|
395 req.getServerPort(), |
|
396 req.getContextPath()); |
|
397 } |
|
398 |
|
399 private static String enforceExt(String filename, String ext) { |
|
400 return filename.endsWith(ext) ? filename : filename + ext; |
|
401 } |
|
402 |
|
403 private static String jspPath(String filename) { |
|
404 return enforceExt(Constants.JSP_PATH_PREFIX + filename, ".jsp"); |
|
405 } |
|
406 |
387 private void doProcess(HttpMethod method, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { |
407 private void doProcess(HttpMethod method, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { |
388 |
408 |
389 // choose the requested language as session language (if available) or fall back to english, otherwise |
409 // choose the requested language as session language (if available) or fall back to english, otherwise |
390 HttpSession session = req.getSession(); |
410 HttpSession session = req.getSession(); |
391 if (session.getAttribute(Constants.SESSION_ATTR_LANGUAGE) == null) { |
411 if (session.getAttribute(Constants.SESSION_ATTR_LANGUAGE) == null) { |
392 Optional<List<String>> availableLanguages = Functions.availableLanguages(getServletContext()).map(Arrays::asList); |
412 Optional<List<String>> availableLanguages = availableLanguages().map(Arrays::asList); |
393 Optional<Locale> reqLocale = Optional.of(req.getLocale()); |
413 Optional<Locale> reqLocale = Optional.of(req.getLocale()); |
394 Locale sessionLocale = reqLocale.filter((rl) -> availableLanguages.map((al) -> al.contains(rl.getLanguage())).orElse(false)).orElse(Locale.ENGLISH); |
414 Locale sessionLocale = reqLocale.filter((rl) -> availableLanguages.map((al) -> al.contains(rl.getLanguage())).orElse(false)).orElse(Locale.ENGLISH); |
395 session.setAttribute(Constants.SESSION_ATTR_LANGUAGE, sessionLocale); |
415 session.setAttribute(Constants.SESSION_ATTR_LANGUAGE, sessionLocale); |
396 LOG.debug("Setting language for new session {}: {}", session.getId(), sessionLocale.getDisplayLanguage()); |
416 LOG.debug("Setting language for new session {}: {}", session.getId(), sessionLocale.getDisplayLanguage()); |
397 } else { |
417 } else { |
399 resp.setLocale(sessionLocale); |
419 resp.setLocale(sessionLocale); |
400 LOG.trace("Continuing session {} with language {}", session.getId(), sessionLocale); |
420 LOG.trace("Continuing session {} with language {}", session.getId(), sessionLocale); |
401 } |
421 } |
402 |
422 |
403 // set some internal request attributes |
423 // set some internal request attributes |
404 final String fullPath = Functions.fullPath(req); |
424 final String fullPath = req.getServletPath() + Optional.ofNullable(req.getPathInfo()).orElse(""); |
405 req.setAttribute(Constants.REQ_ATTR_BASE_HREF, Functions.baseHref(req)); |
425 req.setAttribute(Constants.REQ_ATTR_BASE_HREF, baseHref(req)); |
406 req.setAttribute(Constants.REQ_ATTR_PATH, fullPath); |
426 req.setAttribute(Constants.REQ_ATTR_PATH, fullPath); |
407 req.setAttribute(Constants.REQ_ATTR_RESOURCE_BUNDLE, getResourceBundleName()); |
427 req.setAttribute(Constants.REQ_ATTR_RESOURCE_BUNDLE, getResourceBundleName()); |
408 |
428 |
409 // if this is an error path, bypass the normal flow |
429 // if this is an error path, bypass the normal flow |
410 if (fullPath.startsWith("/error/")) { |
430 if (fullPath.startsWith("/error/")) { |