adds dynamic fragments to LightPIT request handling framework + basic language recognition code

Tue, 26 Dec 2017 17:36:47 +0100

author
Mike Becker <universe@uap-core.de>
date
Tue, 26 Dec 2017 17:36:47 +0100
changeset 13
f4608ad6c947
parent 12
005d27918b57
child 14
2b270c714678

adds dynamic fragments to LightPIT request handling framework + basic language recognition code

src/java/de/uapcore/lightpit/AbstractLightPITServlet.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/Constants.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/Functions.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/modules/LanguageModule.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/resources/localization/language.properties file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/resources/localization/language_de.properties file | annotate | diff | comparison | revisions
src/java/logging.properties file | annotate | diff | comparison | revisions
web/META-INF/context.xml file | annotate | diff | comparison | revisions
web/WEB-INF/dynamic_fragments/language.jsp file | annotate | diff | comparison | revisions
web/WEB-INF/jsp/html_full.jsp file | annotate | diff | comparison | revisions
web/WEB-INF/web.xml file | annotate | diff | comparison | revisions
web/language.css file | annotate | diff | comparison | revisions
     1.1 --- a/src/java/de/uapcore/lightpit/AbstractLightPITServlet.java	Sat Dec 23 17:28:19 2017 +0100
     1.2 +++ b/src/java/de/uapcore/lightpit/AbstractLightPITServlet.java	Tue Dec 26 17:36:47 2017 +0100
     1.3 @@ -31,13 +31,17 @@
     1.4  import java.io.IOException;
     1.5  import java.lang.reflect.Method;
     1.6  import java.lang.reflect.Modifier;
     1.7 +import java.util.Arrays;
     1.8  import java.util.HashMap;
     1.9 +import java.util.List;
    1.10 +import java.util.Locale;
    1.11  import java.util.Map;
    1.12  import java.util.Optional;
    1.13  import javax.servlet.ServletException;
    1.14  import javax.servlet.http.HttpServlet;
    1.15  import javax.servlet.http.HttpServletRequest;
    1.16  import javax.servlet.http.HttpServletResponse;
    1.17 +import javax.servlet.http.HttpSession;
    1.18  import org.slf4j.Logger;
    1.19  import org.slf4j.LoggerFactory;
    1.20  
    1.21 @@ -49,6 +53,8 @@
    1.22      
    1.23      private static final Logger LOG = LoggerFactory.getLogger(AbstractLightPITServlet.class);
    1.24      
    1.25 +    private static final String HTML_FULL_DISPATCHER = Functions.jspPath("html_full");
    1.26 +    
    1.27      /**
    1.28       * Store a reference to the annotation for quicker access.
    1.29       */
    1.30 @@ -164,29 +170,43 @@
    1.31          LOG.trace("{} destroyed", getServletName());
    1.32      }
    1.33      
    1.34 +    /**
    1.35 +     * Sets the name of the dynamic fragment.
    1.36 +     * 
    1.37 +     * It is sufficient to specify the name without any extension. The extension
    1.38 +     * is added automatically if not specified.
    1.39 +     * 
    1.40 +     * The fragment must be located in the dynamic fragments folder.
    1.41 +     * 
    1.42 +     * @param req the servlet request object
    1.43 +     * @param fragmentName the name of the fragment
    1.44 +     * @see Constants#DYN_FRAGMENT_PATH_PREFIX
    1.45 +     */
    1.46 +    public void setDynamicFragment(HttpServletRequest req, String fragmentName) {
    1.47 +        req.setAttribute(Constants.REQ_ATTR_FRAGMENT, Functions.dynFragmentPath(fragmentName));
    1.48 +    }
    1.49      
    1.50      /**
    1.51 -     * Sets several requests attributes, that can be used by the JSP.
    1.52 +     * Specifies the name of an additional stylesheet used by the module.
    1.53 +     * 
    1.54 +     * Setting an additional stylesheet is optional, but quite common for HTML
    1.55 +     * output.
    1.56 +     * 
    1.57 +     * It is sufficient to specify the name without any extension. The extension
    1.58 +     * is added automatically if not specified.
    1.59       * 
    1.60       * @param req the servlet request object
    1.61 -     * @see Constants#REQ_ATTR_PATH
    1.62 -     * @see Constants#REQ_ATTR_MODULE_CLASSNAME
    1.63 -     * @see Constants#REQ_ATTR_MODULE_INFO
    1.64 +     * @param stylesheet the name of the stylesheet
    1.65       */
    1.66 -    private void setGenericRequestAttributes(HttpServletRequest req) {
    1.67 -        req.setAttribute(Constants.REQ_ATTR_PATH, Functions.fullPath(req));
    1.68 -
    1.69 -        req.setAttribute(Constants.REQ_ATTR_MODULE_CLASSNAME, this.getClass().getName());
    1.70 -
    1.71 -        moduleInfoELProxy.ifPresent((proxy) -> req.setAttribute(Constants.REQ_ATTR_MODULE_INFO, proxy));
    1.72 +    public void setStylesheet(HttpServletRequest req, String stylesheet) {
    1.73 +        req.setAttribute(Constants.REQ_ATTR_STYLESHEET, Functions.enforceExt(stylesheet, ".css"));
    1.74      }
    1.75      
    1.76      private void forwardToFullView(HttpServletRequest req, HttpServletResponse resp)
    1.77              throws IOException, ServletException {
    1.78          
    1.79 -        setGenericRequestAttributes(req);
    1.80          req.setAttribute(Constants.REQ_ATTR_MENU, getModuleManager().getMainMenu());
    1.81 -        req.getRequestDispatcher(Functions.jspPath("full.jsp")).forward(req, resp);
    1.82 +        req.getRequestDispatcher(HTML_FULL_DISPATCHER).forward(req, resp);
    1.83      }
    1.84      
    1.85      private Optional<HandlerMethod> findMapping(HttpMethod method, HttpServletRequest req) {
    1.86 @@ -212,6 +232,22 @@
    1.87      
    1.88      private void doProcess(HttpMethod method, HttpServletRequest req, HttpServletResponse resp)
    1.89              throws ServletException, IOException {
    1.90 +        
    1.91 +        HttpSession session = req.getSession();
    1.92 +        
    1.93 +        // choose the requested language as session language (if available) or fall back to english, otherwise
    1.94 +        if (session.getAttribute(Constants.SESSION_ATTR_LANGUAGE) == null) {
    1.95 +            Optional<List<String>> availableLanguages = Functions.availableLanguages(getServletContext()).map(Arrays::asList);
    1.96 +            Optional<Locale> reqLocale = Optional.of(req.getLocale());
    1.97 +            Locale sessionLocale = reqLocale.filter((rl) -> availableLanguages.map((al) -> al.contains(rl.getLanguage())).orElse(false)).orElse(Locale.ENGLISH);
    1.98 +            session.setAttribute(Constants.SESSION_ATTR_LANGUAGE, sessionLocale);
    1.99 +            LOG.debug("Settng language for new session {}: {}", session.getId(), sessionLocale.getDisplayLanguage());
   1.100 +        }
   1.101 +        
   1.102 +        req.setAttribute(Constants.REQ_ATTR_PATH, Functions.fullPath(req));
   1.103 +        req.setAttribute(Constants.REQ_ATTR_MODULE_CLASSNAME, this.getClass().getName());
   1.104 +        moduleInfoELProxy.ifPresent((proxy) -> req.setAttribute(Constants.REQ_ATTR_MODULE_INFO, proxy));
   1.105 +        
   1.106          Optional<HandlerMethod> mapping = findMapping(method, req);
   1.107          if (mapping.isPresent()) {
   1.108              forwardAsSepcified(mapping.get().apply(req, resp), req, resp);
     2.1 --- a/src/java/de/uapcore/lightpit/Constants.java	Sat Dec 23 17:28:19 2017 +0100
     2.2 +++ b/src/java/de/uapcore/lightpit/Constants.java	Tue Dec 26 17:36:47 2017 +0100
     2.3 @@ -31,11 +31,23 @@
     2.4  import static de.uapcore.lightpit.Functions.fqn;
     2.5  
     2.6  /**
     2.7 - * Contains all constants used by the this application.
     2.8 + * Contains all non-local scope constants used by the this application.
     2.9 + * 
    2.10 + * Constants with (class) local scope are defined in their respective classes.
    2.11   */
    2.12  public final class Constants {
    2.13      public static final String JSP_PATH_PREFIX = "/WEB-INF/jsp/";
    2.14      
    2.15 +    public static final String JSPF_PATH_PREFIX = "/WEB-INF/jspf/";
    2.16 +    
    2.17 +    public static final String DYN_FRAGMENT_PATH_PREFIX = "/WEB-INF/dynamic_fragments/";
    2.18 +    
    2.19 +    
    2.20 +    /**
    2.21 +     * Name for the context parameter specifying the available languages.
    2.22 +     */
    2.23 +    public static final String CTX_ATTR_LANGUAGES = "available-languages";
    2.24 +    
    2.25      /**
    2.26       * Key for the request attribute containing the class name of the currently dispatching module.
    2.27       */
    2.28 @@ -55,6 +67,22 @@
    2.29       * Key for the request attribute containing the full path information (servlet path + path info).
    2.30       */
    2.31      public static final String REQ_ATTR_PATH = fqn(AbstractLightPITServlet.class, "path");
    2.32 +
    2.33 +    /**
    2.34 +     * Key for the name of the fragment which should be rendered.
    2.35 +     */    
    2.36 +    public static final String REQ_ATTR_FRAGMENT = fqn(AbstractLightPITServlet.class, "fragment");
    2.37 +    
    2.38 +    /**
    2.39 +     * Key for the name of the additional stylesheet used by a module.
    2.40 +     */    
    2.41 +    public static final String REQ_ATTR_STYLESHEET = fqn(AbstractLightPITServlet.class, "extraCss");
    2.42 +    
    2.43 +    
    2.44 +    /**
    2.45 +     * Key for the current language selection within the session.
    2.46 +     */
    2.47 +    public static final String SESSION_ATTR_LANGUAGE = fqn(AbstractLightPITServlet.class, "language");
    2.48      
    2.49      /**
    2.50       * This class is not instantiatable.
     3.1 --- a/src/java/de/uapcore/lightpit/Functions.java	Sat Dec 23 17:28:19 2017 +0100
     3.2 +++ b/src/java/de/uapcore/lightpit/Functions.java	Tue Dec 26 17:36:47 2017 +0100
     3.3 @@ -29,6 +29,7 @@
     3.4  package de.uapcore.lightpit;
     3.5  
     3.6  import java.util.Optional;
     3.7 +import javax.servlet.ServletContext;
     3.8  import javax.servlet.http.HttpServletRequest;
     3.9  import org.slf4j.Logger;
    3.10  import org.slf4j.LoggerFactory;
    3.11 @@ -40,8 +41,24 @@
    3.12      
    3.13      private static final Logger LOG = LoggerFactory.getLogger(Functions.class);
    3.14  
    3.15 +    public static Optional<String[]> availableLanguages(ServletContext ctx) {
    3.16 +        return Optional.ofNullable(ctx.getInitParameter(Constants.CTX_ATTR_LANGUAGES)).map((x) -> x.split("\\s*,\\s*"));
    3.17 +    }
    3.18 +    
    3.19 +    public static String enforceExt(String filename, String ext) {
    3.20 +        return filename.endsWith(ext) ? filename : filename + ext;
    3.21 +    }
    3.22 +
    3.23      public static String jspPath(String filename) {
    3.24 -        return Constants.JSP_PATH_PREFIX + filename;
    3.25 +        return enforceExt(Constants.JSP_PATH_PREFIX + filename, ".jsp");
    3.26 +    }
    3.27 +    
    3.28 +    public static String jspfPath(String filename) {
    3.29 +        return enforceExt(Constants.JSPF_PATH_PREFIX + filename, ".jspf");
    3.30 +    }
    3.31 +    
    3.32 +    public static String dynFragmentPath(String filename) {
    3.33 +        return enforceExt(Constants.DYN_FRAGMENT_PATH_PREFIX + filename, ".jsp");
    3.34      }
    3.35      
    3.36      public static String fqn(String base, String name) {
     4.1 --- a/src/java/de/uapcore/lightpit/modules/LanguageModule.java	Sat Dec 23 17:28:19 2017 +0100
     4.2 +++ b/src/java/de/uapcore/lightpit/modules/LanguageModule.java	Tue Dec 26 17:36:47 2017 +0100
     4.3 @@ -30,12 +30,22 @@
     4.4  
     4.5  import de.uapcore.lightpit.LightPITModule;
     4.6  import de.uapcore.lightpit.AbstractLightPITServlet;
     4.7 +import de.uapcore.lightpit.Constants;
     4.8 +import de.uapcore.lightpit.Functions;
     4.9  import de.uapcore.lightpit.HttpMethod;
    4.10  import javax.servlet.annotation.WebServlet;
    4.11  import javax.servlet.http.HttpServletRequest;
    4.12  import javax.servlet.http.HttpServletResponse;
    4.13  import de.uapcore.lightpit.RequestMapping;
    4.14  import de.uapcore.lightpit.ResponseType;
    4.15 +import java.util.ArrayList;
    4.16 +import java.util.IllformedLocaleException;
    4.17 +import java.util.List;
    4.18 +import java.util.Locale;
    4.19 +import java.util.Optional;
    4.20 +import javax.servlet.ServletException;
    4.21 +import org.slf4j.Logger;
    4.22 +import org.slf4j.LoggerFactory;
    4.23  
    4.24  
    4.25  @LightPITModule(
    4.26 @@ -48,9 +58,42 @@
    4.27  )
    4.28  public final class LanguageModule extends AbstractLightPITServlet {
    4.29      
    4.30 +    private static final Logger LOG = LoggerFactory.getLogger(LanguageModule.class);
    4.31 +    
    4.32 +    private List<Locale> languages = new ArrayList<>();
    4.33 +
    4.34 +    @Override
    4.35 +    public void init() throws ServletException {
    4.36 +        super.init();
    4.37 +        
    4.38 +        Optional<String[]> langs = Functions.availableLanguages(getServletContext());
    4.39 +        if (langs.isPresent()) {
    4.40 +            for (String lang : langs.get()) {
    4.41 +                try {
    4.42 +                    Locale locale = Locale.forLanguageTag(lang);
    4.43 +                    if (locale.getLanguage().isEmpty()) {
    4.44 +                        throw new IllformedLocaleException();
    4.45 +                    }
    4.46 +                    languages.add(locale);
    4.47 +                } catch (IllformedLocaleException ex) {
    4.48 +                    LOG.warn("Specified lanaguge {} in context parameter cannot be mapped to an existing locale - skipping.", lang);
    4.49 +                }
    4.50 +            }
    4.51 +            
    4.52 +        } else {
    4.53 +            languages.add(Locale.ENGLISH);
    4.54 +            LOG.warn("Context parameter 'available-languges' not found. Only english will be available.");
    4.55 +        }
    4.56 +    }
    4.57 +    
    4.58      @RequestMapping(method = HttpMethod.GET)
    4.59      public ResponseType handle(HttpServletRequest req, HttpServletResponse resp) {
    4.60 +
    4.61 +        req.setAttribute("languages", languages);
    4.62 +        req.setAttribute("browserLanguage", req.getLocale());
    4.63          
    4.64 +        setStylesheet(req, "language");
    4.65 +        setDynamicFragment(req, "language");
    4.66          return ResponseType.HTML_FULL;
    4.67      }
    4.68  }
     5.1 --- a/src/java/de/uapcore/lightpit/resources/localization/language.properties	Sat Dec 23 17:28:19 2017 +0100
     5.2 +++ b/src/java/de/uapcore/lightpit/resources/localization/language.properties	Tue Dec 26 17:36:47 2017 +0100
     5.3 @@ -22,3 +22,5 @@
     5.4  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
     5.5  
     5.6  menuLabel = Languages
     5.7 +submit = Switch language
     5.8 +browserLanguage = Browser language
     6.1 --- a/src/java/de/uapcore/lightpit/resources/localization/language_de.properties	Sat Dec 23 17:28:19 2017 +0100
     6.2 +++ b/src/java/de/uapcore/lightpit/resources/localization/language_de.properties	Tue Dec 26 17:36:47 2017 +0100
     6.3 @@ -22,3 +22,5 @@
     6.4  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
     6.5  
     6.6  menuLabel = Sprache
     6.7 +submit = Sprache ausw\u00e4hlen
     6.8 +browserLanguage = Browsersprache
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/java/logging.properties	Tue Dec 26 17:36:47 2017 +0100
     7.3 @@ -0,0 +1,27 @@
     7.4 +# Copyright 2017 Mike Becker. All rights reserved.
     7.5 +#
     7.6 +# Redistribution and use in source and binary forms, with or without
     7.7 +# modification, are permitted provided that the following conditions are met:
     7.8 +#
     7.9 +# 1. Redistributions of source code must retain the above copyright
    7.10 +# notice, this list of conditions and the following disclaimer.
    7.11 +#
    7.12 +# 2. Redistributions in binary form must reproduce the above copyright
    7.13 +# notice, this list of conditions and the following disclaimer in the
    7.14 +# documentation and/or other materials provided with the distribution.
    7.15 +#
    7.16 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    7.17 +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    7.18 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    7.19 +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    7.20 +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    7.21 +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    7.22 +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    7.23 +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    7.24 +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    7.25 +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
    7.26 +
    7.27 +
    7.28 +handlers= java.util.logging.ConsoleHandler
    7.29 +
    7.30 +.level = DEBUG
     8.1 --- a/web/META-INF/context.xml	Sat Dec 23 17:28:19 2017 +0100
     8.2 +++ b/web/META-INF/context.xml	Tue Dec 26 17:36:47 2017 +0100
     8.3 @@ -1,2 +1,2 @@
     8.4  <?xml version="1.0" encoding="UTF-8"?>
     8.5 -<Context path="/lightpit"/>
     8.6 +<Context path="/lightpit" />
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/web/WEB-INF/dynamic_fragments/language.jsp	Tue Dec 26 17:36:47 2017 +0100
     9.3 @@ -0,0 +1,46 @@
     9.4 +<%-- 
     9.5 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     9.6 +
     9.7 +Copyright 2017 Mike Becker. All rights reserved.
     9.8 +
     9.9 +Redistribution and use in source and binary forms, with or without
    9.10 +modification, are permitted provided that the following conditions are met:
    9.11 +
    9.12 +1. Redistributions of source code must retain the above copyright
    9.13 +notice, this list of conditions and the following disclaimer.
    9.14 +
    9.15 +2. Redistributions in binary form must reproduce the above copyright
    9.16 +notice, this list of conditions and the following disclaimer in the
    9.17 +documentation and/or other materials provided with the distribution.
    9.18 +
    9.19 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    9.20 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    9.21 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    9.22 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    9.23 +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    9.24 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    9.25 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    9.26 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    9.27 +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    9.28 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
    9.29 +--%>
    9.30 +<%@page pageEncoding="UTF-8" session="true" %>
    9.31 +<%@page import="de.uapcore.lightpit.Constants" %>
    9.32 +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    9.33 +<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    9.34 +
    9.35 +<c:set scope="page" var="currentLanguage" value="${sessionScope[Constants.SESSION_ATTR_LANGUAGE]}" />
    9.36 +
    9.37 +<fmt:bundle basename="${requestScope[Constants.REQ_ATTR_MODULE_INFO].bundleBaseName}">
    9.38 +<form method="POST"id="lang-selector">
    9.39 +    <c:forEach items="${languages}" var="l">
    9.40 +        <label>
    9.41 +            <input type="radio" name="language" value="${l.language}"
    9.42 +                   <c:if test="${l.language eq currentLanguage.language}">checked</c:if>/>
    9.43 +            ${l.displayLanguage}
    9.44 +            (${l.getDisplayLanguage(currentLanguage)}<c:if test="${not empty browserLanguage and l.language eq browserLanguage.language}">&nbsp;-&nbsp;<fmt:message key="browserLanguage"/></c:if>)
    9.45 +        </label>
    9.46 +    </c:forEach>
    9.47 +    <input type="submit" value="<fmt:message key="submit" />"/>
    9.48 +</form>
    9.49 +</fmt:bundle>
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/web/WEB-INF/jsp/html_full.jsp	Tue Dec 26 17:36:47 2017 +0100
    10.3 @@ -0,0 +1,85 @@
    10.4 +<%-- 
    10.5 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    10.6 +
    10.7 +Copyright 2017 Mike Becker. All rights reserved.
    10.8 +
    10.9 +Redistribution and use in source and binary forms, with or without
   10.10 +modification, are permitted provided that the following conditions are met:
   10.11 +
   10.12 +1. Redistributions of source code must retain the above copyright
   10.13 +notice, this list of conditions and the following disclaimer.
   10.14 +
   10.15 +2. Redistributions in binary form must reproduce the above copyright
   10.16 +notice, this list of conditions and the following disclaimer in the
   10.17 +documentation and/or other materials provided with the distribution.
   10.18 +
   10.19 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   10.20 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   10.21 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   10.22 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
   10.23 +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   10.24 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   10.25 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   10.26 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   10.27 +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   10.28 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
   10.29 +--%>
   10.30 +<%@page contentType="text/html" pageEncoding="UTF-8" trimDirectiveWhitespaces="true" session="true" %>
   10.31 +<%@page import="de.uapcore.lightpit.Constants" %>
   10.32 +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
   10.33 +<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
   10.34 +<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
   10.35 +
   10.36 +<%-- Define an alias for the main menu --%>
   10.37 +<c:set scope="page" var="mainMenu" value="${requestScope[Constants.REQ_ATTR_MENU]}"/>
   10.38 +
   10.39 +<%-- Define an alias for the fragment name --%>
   10.40 +<c:set scope="page" var="fragment" value="${requestScope[Constants.REQ_ATTR_FRAGMENT]}"/>
   10.41 +
   10.42 +<%-- Define an alias for the additional stylesheet --%>
   10.43 +<c:set scope="page" var="extraCss" value="${requestScope[Constants.REQ_ATTR_STYLESHEET]}"/>
   10.44 +
   10.45 +<%-- Define an alias for the module info --%>
   10.46 +<c:set scope="page" var="moduleInfo" value="${requestScope[Constants.REQ_ATTR_MODULE_INFO]}"/>
   10.47 +
   10.48 +<!DOCTYPE html>
   10.49 +<html>
   10.50 +    <head>
   10.51 +        <base href="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
   10.52 +        <title>LightPIT -
   10.53 +            <fmt:bundle basename="${moduleInfo.bundleBaseName}">
   10.54 +                <fmt:message key="${moduleInfo.titleKey}" />
   10.55 +            </fmt:bundle>
   10.56 +        </title>
   10.57 +        <meta charset="UTF-8">
   10.58 +        <link rel="stylesheet" href="lightpit.css" type="text/css">
   10.59 +        <c:if test="${not empty extraCss}">
   10.60 +        <link rel="stylesheet" href="${extraCss}" type="text/css">
   10.61 +        </c:if>
   10.62 +    </head>
   10.63 +    <body>
   10.64 +        <div id="mainMenu">
   10.65 +            <c:forEach var="menu" items="${mainMenu}">
   10.66 +                <div class="menuEntry"
   10.67 +                     <c:if test="${requestScope[Constants.REQ_ATTR_MODULE_CLASSNAME] eq menu.moduleClassName}">
   10.68 +                         data-active
   10.69 +                     </c:if>
   10.70 +                >
   10.71 +                    <a href="${menu.pathName}">
   10.72 +                    <fmt:bundle basename="${menu.resourceKey.bundle}">
   10.73 +                        <fmt:message key="${menu.resourceKey.key}" />
   10.74 +                    </fmt:bundle>
   10.75 +                    </a>
   10.76 +                </div>
   10.77 +            </c:forEach>
   10.78 +        </div>
   10.79 +        <div id="subMenu">
   10.80 +            
   10.81 +        </div>
   10.82 +        <div id="content-area">
   10.83 +            <c:if test="${not empty fragment}">
   10.84 +            <c:import url="${fragment}" />
   10.85 +            </c:if>
   10.86 +        </div>
   10.87 +    </body>
   10.88 +</html>
    11.1 --- a/web/WEB-INF/web.xml	Sat Dec 23 17:28:19 2017 +0100
    11.2 +++ b/web/WEB-INF/web.xml	Tue Dec 26 17:36:47 2017 +0100
    11.3 @@ -5,4 +5,8 @@
    11.4              30
    11.5          </session-timeout>
    11.6      </session-config>
    11.7 +    <context-param>
    11.8 +        <param-name>available-languages</param-name>
    11.9 +        <param-value>en,de</param-value>
   11.10 +    </context-param>
   11.11  </web-app>
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/web/language.css	Tue Dec 26 17:36:47 2017 +0100
    12.3 @@ -0,0 +1,39 @@
    12.4 +/*
    12.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    12.6 + * 
    12.7 + * Copyright 2017 Mike Becker. All rights reserved.
    12.8 + * 
    12.9 + * Redistribution and use in source and binary forms, with or without
   12.10 + * modification, are permitted provided that the following conditions are met:
   12.11 + *
   12.12 + *   1. Redistributions of source code must retain the above copyright
   12.13 + *      notice, this list of conditions and the following disclaimer.
   12.14 + *
   12.15 + *   2. Redistributions in binary form must reproduce the above copyright
   12.16 + *      notice, this list of conditions and the following disclaimer in the
   12.17 + *      documentation and/or other materials provided with the distribution.
   12.18 + *
   12.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   12.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   12.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   12.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   12.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   12.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   12.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   12.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   12.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   12.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   12.29 + * POSSIBILITY OF SUCH DAMAGE.
   12.30 + * 
   12.31 + */
   12.32 +
   12.33 +#lang-selector {
   12.34 +    max-width: 30%;
   12.35 +    display: flex;
   12.36 +    flex-basis: content;
   12.37 +    flex-direction: column;
   12.38 +}
   12.39 +
   12.40 +input {
   12.41 +    margin: .5em;
   12.42 +}

mercurial