185 @Override |
190 @Override |
186 public void destroy() { |
191 public void destroy() { |
187 mappings.clear(); |
192 mappings.clear(); |
188 LOG.trace("{} destroyed", getServletName()); |
193 LOG.trace("{} destroyed", getServletName()); |
189 } |
194 } |
190 |
195 |
191 /** |
196 /** |
192 * Sets the name of the dynamic fragment. |
197 * Sets the name of the dynamic fragment. |
193 * |
198 * <p> |
194 * It is sufficient to specify the name without any extension. The extension |
199 * It is sufficient to specify the name without any extension. The extension |
195 * is added automatically if not specified. |
200 * is added automatically if not specified. |
196 * |
201 * <p> |
197 * The fragment must be located in the dynamic fragments folder. |
202 * The fragment must be located in the dynamic fragments folder. |
198 * |
203 * |
199 * @param req the servlet request object |
204 * @param req the servlet request object |
200 * @param fragmentName the name of the fragment |
205 * @param fragmentName the name of the fragment |
201 * @see Constants#DYN_FRAGMENT_PATH_PREFIX |
206 * @see Constants#DYN_FRAGMENT_PATH_PREFIX |
202 */ |
207 */ |
203 public void setDynamicFragment(HttpServletRequest req, String fragmentName) { |
208 public void setDynamicFragment(HttpServletRequest req, String fragmentName) { |
204 req.setAttribute(Constants.REQ_ATTR_FRAGMENT, Functions.dynFragmentPath(fragmentName)); |
209 req.setAttribute(Constants.REQ_ATTR_FRAGMENT, Functions.dynFragmentPath(fragmentName)); |
205 } |
210 } |
206 |
211 |
207 /** |
212 /** |
208 * Specifies the name of an additional stylesheet used by the module. |
213 * Specifies the name of an additional stylesheet used by the module. |
209 * |
214 * <p> |
210 * Setting an additional stylesheet is optional, but quite common for HTML |
215 * Setting an additional stylesheet is optional, but quite common for HTML |
211 * output. |
216 * output. |
212 * |
217 * <p> |
213 * It is sufficient to specify the name without any extension. The extension |
218 * It is sufficient to specify the name without any extension. The extension |
214 * is added automatically if not specified. |
219 * is added automatically if not specified. |
215 * |
220 * |
216 * @param req the servlet request object |
221 * @param req the servlet request object |
217 * @param stylesheet the name of the stylesheet |
222 * @param stylesheet the name of the stylesheet |
218 */ |
223 */ |
219 public void setStylesheet(HttpServletRequest req, String stylesheet) { |
224 public void setStylesheet(HttpServletRequest req, String stylesheet) { |
220 req.setAttribute(Constants.REQ_ATTR_STYLESHEET, Functions.enforceExt(stylesheet, ".css")); |
225 req.setAttribute(Constants.REQ_ATTR_STYLESHEET, Functions.enforceExt(stylesheet, ".css")); |
221 } |
226 } |
222 |
227 |
223 private void forwardToFullView(HttpServletRequest req, HttpServletResponse resp) |
228 private void forwardToFullView(HttpServletRequest req, HttpServletResponse resp) |
224 throws IOException, ServletException { |
229 throws IOException, ServletException { |
225 |
230 |
226 req.setAttribute(Constants.REQ_ATTR_MENU, getModuleManager().getMainMenu(getDatabaseFacade())); |
231 req.setAttribute(Constants.REQ_ATTR_MENU, getModuleManager().getMainMenu(getDatabaseFacade())); |
227 req.getRequestDispatcher(HTML_FULL_DISPATCHER).forward(req, resp); |
232 req.getRequestDispatcher(HTML_FULL_DISPATCHER).forward(req, resp); |
228 } |
233 } |
229 |
234 |
230 private Optional<HandlerMethod> findMapping(HttpMethod method, HttpServletRequest req) { |
235 private Optional<HandlerMethod> findMapping(HttpMethod method, HttpServletRequest req) { |
231 return Optional.ofNullable(mappings.get(method)).map( |
236 return Optional.ofNullable(mappings.get(method)).map( |
232 (rm) -> rm.get(Optional.ofNullable(req.getPathInfo()).orElse("/")) |
237 (rm) -> rm.get(Optional.ofNullable(req.getPathInfo()).orElse("/")) |
233 ); |
238 ); |
234 } |
239 } |
235 |
240 |
236 private void forwardAsSepcified(ResponseType type, HttpServletRequest req, HttpServletResponse resp) |
241 private void forwardAsSpecified(ResponseType type, HttpServletRequest req, HttpServletResponse resp) |
237 throws ServletException, IOException { |
242 throws ServletException, IOException { |
238 switch (type) { |
243 switch (type) { |
239 case NONE: return; |
244 case NONE: |
|
245 return; |
240 case HTML_FULL: |
246 case HTML_FULL: |
241 forwardToFullView(req, resp); |
247 forwardToFullView(req, resp); |
242 return; |
248 return; |
243 // TODO: implement remaining response types |
249 // TODO: implement remaining response types |
244 default: |
250 default: |
245 // this code should be unreachable |
251 throw new AssertionError("ResponseType switch is not exhaustive - this is a bug!"); |
246 LOG.error("ResponseType switch is not exhaustive - this is a bug!"); |
252 } |
247 throw new UnsupportedOperationException(); |
253 } |
248 } |
254 |
249 } |
|
250 |
|
251 private void doProcess(HttpMethod method, HttpServletRequest req, HttpServletResponse resp) |
255 private void doProcess(HttpMethod method, HttpServletRequest req, HttpServletResponse resp) |
252 throws ServletException, IOException { |
256 throws ServletException, IOException { |
253 |
257 |
254 // Synchronize module information with database |
258 // Synchronize module information with database |
255 getModuleManager().syncWithDatabase(getDatabaseFacade()); |
259 getModuleManager().syncWithDatabase(getDatabaseFacade()); |
256 |
260 |
257 // choose the requested language as session language (if available) or fall back to english, otherwise |
261 // choose the requested language as session language (if available) or fall back to english, otherwise |
258 HttpSession session = req.getSession(); |
262 HttpSession session = req.getSession(); |
259 if (session.getAttribute(Constants.SESSION_ATTR_LANGUAGE) == null) { |
263 if (session.getAttribute(Constants.SESSION_ATTR_LANGUAGE) == null) { |
260 Optional<List<String>> availableLanguages = Functions.availableLanguages(getServletContext()).map(Arrays::asList); |
264 Optional<List<String>> availableLanguages = Functions.availableLanguages(getServletContext()).map(Arrays::asList); |
261 Optional<Locale> reqLocale = Optional.of(req.getLocale()); |
265 Optional<Locale> reqLocale = Optional.of(req.getLocale()); |
262 Locale sessionLocale = reqLocale.filter((rl) -> availableLanguages.map((al) -> al.contains(rl.getLanguage())).orElse(false)).orElse(Locale.ENGLISH); |
266 Locale sessionLocale = reqLocale.filter((rl) -> availableLanguages.map((al) -> al.contains(rl.getLanguage())).orElse(false)).orElse(Locale.ENGLISH); |
263 session.setAttribute(Constants.SESSION_ATTR_LANGUAGE, sessionLocale); |
267 session.setAttribute(Constants.SESSION_ATTR_LANGUAGE, sessionLocale); |
264 LOG.debug("Settng language for new session {}: {}", session.getId(), sessionLocale.getDisplayLanguage()); |
268 LOG.debug("Setting language for new session {}: {}", session.getId(), sessionLocale.getDisplayLanguage()); |
265 } else { |
269 } else { |
266 Locale sessionLocale = (Locale) session.getAttribute(Constants.SESSION_ATTR_LANGUAGE); |
270 Locale sessionLocale = (Locale) session.getAttribute(Constants.SESSION_ATTR_LANGUAGE); |
267 resp.setLocale(sessionLocale); |
271 resp.setLocale(sessionLocale); |
268 LOG.trace("Continuing session {} with language {}", session.getId(), sessionLocale); |
272 LOG.trace("Continuing session {} with language {}", session.getId(), sessionLocale); |
269 } |
273 } |
270 |
274 |
271 // set some internal request attributes |
275 // set some internal request attributes |
272 req.setAttribute(Constants.REQ_ATTR_PATH, Functions.fullPath(req)); |
276 req.setAttribute(Constants.REQ_ATTR_PATH, Functions.fullPath(req)); |
273 req.setAttribute(Constants.REQ_ATTR_MODULE_CLASSNAME, this.getClass().getName()); |
277 req.setAttribute(Constants.REQ_ATTR_MODULE_CLASSNAME, this.getClass().getName()); |
274 Optional.ofNullable(moduleInfoELProxy).ifPresent((proxy) -> req.setAttribute(Constants.REQ_ATTR_MODULE_INFO, proxy)); |
278 Optional.ofNullable(moduleInfoELProxy).ifPresent((proxy) -> req.setAttribute(Constants.REQ_ATTR_MODULE_INFO, proxy)); |
275 |
279 |
276 |
280 |
277 // call the handler, if available, or send an HTTP 404 error |
281 // call the handler, if available, or send an HTTP 404 error |
278 Optional<HandlerMethod> mapping = findMapping(method, req); |
282 Optional<HandlerMethod> mapping = findMapping(method, req); |
279 if (mapping.isPresent()) { |
283 if (mapping.isPresent()) { |
280 forwardAsSepcified(mapping.get().apply(req, resp), req, resp); |
284 forwardAsSpecified(mapping.get().apply(req, resp), req, resp); |
281 } else { |
285 } else { |
282 resp.sendError(HttpServletResponse.SC_NOT_FOUND); |
286 resp.sendError(HttpServletResponse.SC_NOT_FOUND); |
283 } |
287 } |
284 } |
288 } |
285 |
289 |
286 @Override |
290 @Override |
287 protected final void doGet(HttpServletRequest req, HttpServletResponse resp) |
291 protected final void doGet(HttpServletRequest req, HttpServletResponse resp) |
288 throws ServletException, IOException { |
292 throws ServletException, IOException { |
289 doProcess(HttpMethod.GET, req, resp); |
293 doProcess(HttpMethod.GET, req, resp); |
290 } |
294 } |