src/java/de/uapcore/lightpit/ModuleManager.java

Sun, 17 Dec 2017 01:45:28 +0100

author
Mike Becker <universe@uap-core.de>
date
Sun, 17 Dec 2017 01:45:28 +0100
changeset 11
737ab27e37b3
parent 10
89e3e6e28b69
child 18
a94b172c3a93
permissions
-rw-r--r--

implements simple request mapper

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  * 
     4  * Copyright 2017 Mike Becker. All rights reserved.
     5  * 
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  *   1. Redistributions of source code must retain the above copyright
    10  *      notice, this list of conditions and the following disclaimer.
    11  *
    12  *   2. Redistributions in binary form must reproduce the above copyright
    13  *      notice, this list of conditions and the following disclaimer in the
    14  *      documentation and/or other materials provided with the distribution.
    15  *
    16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    26  * POSSIBILITY OF SUCH DAMAGE.
    27  * 
    28  */
    29 package de.uapcore.lightpit;
    31 import java.util.ArrayList;
    32 import java.util.Collections;
    33 import java.util.List;
    34 import java.util.Optional;
    35 import javax.servlet.Registration;
    36 import javax.servlet.ServletContext;
    37 import javax.servlet.ServletContextEvent;
    38 import javax.servlet.ServletContextListener;
    39 import javax.servlet.annotation.WebListener;
    40 import org.slf4j.Logger;
    41 import org.slf4j.LoggerFactory;
    43 /**
    44  * Scans registered servlets for LightPIT modules.
    45  */
    46 @WebListener
    47 public final class ModuleManager implements ServletContextListener {
    49     private static final Logger LOG = LoggerFactory.getLogger(ModuleManager.class);
    51     /**
    52      * The attribute name in the servlet context under which an instance of this class can be found.
    53      */
    54     public static final String SC_ATTR_NAME = ModuleManager.class.getName();
    55     private ServletContext sc;
    57     private final List<Menu> mainMenu = new ArrayList<>();
    58     private final List<Menu> immutableMainMenu = Collections.unmodifiableList(mainMenu);
    60     @Override
    61     public void contextInitialized(ServletContextEvent sce) {
    62         sc = sce.getServletContext();
    63         reloadAll();
    64         sc.setAttribute(SC_ATTR_NAME, this);
    65         LOG.info("Module manager injected into ServletContext.");
    66     }
    68     @Override
    69     public void contextDestroyed(ServletContextEvent sce) {
    70         unloadAll();
    71     }
    73     private Optional<LightPITModule> getModuleInfo(Registration reg) {
    74         try {
    75             final Class scclass = Class.forName(reg.getClassName());
    77             final boolean lpservlet = AbstractLightPITServlet.class.isAssignableFrom(scclass);
    78             final boolean lpmodule = scclass.isAnnotationPresent(LightPITModule.class);
    80             if (lpservlet && !lpmodule) {
    81                 LOG.warn(
    82                     "{} is a LightPIT Servlet but is missing the module annotation.",
    83                     reg.getClassName()
    84                 );
    85             } else if (!lpservlet && lpmodule) {
    86                 LOG.warn(
    87                     "{} is annotated as a LightPIT Module but does not extend {}.",
    88                     reg.getClassName(),
    89                     AbstractLightPITServlet.class.getSimpleName()
    90                 );
    91             }
    93             if (lpservlet && lpmodule) {
    94                 final Class<? extends AbstractLightPITServlet> clazz = scclass;
    95                 final LightPITModule moduleInfo = clazz.getAnnotation(LightPITModule.class);
    96                 return Optional.of(moduleInfo);
    97             } else {
    98                 return Optional.empty();
    99             }
   100         } catch (ClassNotFoundException ex) {
   101             LOG.error(
   102                     "Servlet registration refers to class {} which cannot be found by the class loader (Reason: {})",
   103                     reg.getClassName(),
   104                     ex.getMessage()
   105             );
   106             return Optional.empty();
   107         }        
   108     }
   110     private void addModuleToMenu(String moduleClassName, LightPITModule moduleInfo) {
   111         final Menu menu = new Menu(
   112                 moduleClassName,
   113                 new ResourceKey(moduleInfo.bundleBaseName(), moduleInfo.menuKey()),
   114                 moduleInfo.modulePath()
   115         );
   116         mainMenu.add(menu);
   117     }
   119     private void handleServletRegistration(String name, Registration reg) {
   120         final Optional<LightPITModule> moduleInfo = getModuleInfo(reg);
   121         if (moduleInfo.isPresent()) {
   123             // TODO: remove this call and add the module to some dependency resolver, first
   124             addModuleToMenu(reg.getClassName(), moduleInfo.get());
   126             LOG.info("Module detected: {}", name);
   127         } else {
   128             LOG.debug("Servlet {} is no module, skipping.", name);
   129         }
   130     }
   132     /**
   133      * Scans for modules and reloads them all.
   134      */
   135     public void reloadAll() {
   136         sc.getServletRegistrations().forEach(this::handleServletRegistration);
   137         LOG.info("Modules loaded.");
   138     }
   140     /**
   141      * Unloads all found modules.
   142      */
   143     public void unloadAll() {
   144         mainMenu.clear();
   145         LOG.info("All modules unloaded.");
   146     }
   148     /**
   149      * Returns the main menu.
   150      * @return a list of menus belonging to the main menu
   151      */
   152     public List<Menu> getMainMenu() {
   153         return immutableMainMenu;
   154     }
   155 }

mercurial