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

Wed, 13 May 2020 18:33:25 +0200

author
Mike Becker <universe@uap-core.de>
date
Wed, 13 May 2020 18:33:25 +0200
changeset 41
4f1c026a8aab
parent 36
0f4f8f255c32
child 45
cc7f082c5ef3
permissions
-rw-r--r--

adds files for ProjectsModule

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2018 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 org.slf4j.Logger;
    32 import org.slf4j.LoggerFactory;
    34 import javax.servlet.Registration;
    35 import javax.servlet.ServletContext;
    36 import javax.servlet.ServletContextEvent;
    37 import javax.servlet.ServletContextListener;
    38 import javax.servlet.annotation.WebListener;
    39 import java.util.*;
    41 /**
    42  * Scans registered servlets for LightPIT modules.
    43  */
    44 @WebListener
    45 public final class ModuleManager implements ServletContextListener {
    47     private static final Logger LOG = LoggerFactory.getLogger(ModuleManager.class);
    49     /**
    50      * The attribute name in the servlet context under which an instance of this class can be found.
    51      */
    52     public static final String SC_ATTR_NAME = ModuleManager.class.getName();
    53     private ServletContext sc;
    55     /**
    56      * Maps class names to module information.
    57      */
    58     private final Map<String, LightPITModule> registeredModules = new HashMap<>();
    60     /**
    61      * Contains the menu entries for the loaded modules.
    62      */
    63     private final List<MenuEntry> mainMenu = new ArrayList<>();
    65     @Override
    66     public void contextInitialized(ServletContextEvent sce) {
    67         sc = sce.getServletContext();
    68         reloadAll();
    69         sc.setAttribute(SC_ATTR_NAME, this);
    70         LOG.info("Module manager injected into ServletContext.");
    71     }
    73     @Override
    74     public void contextDestroyed(ServletContextEvent sce) {
    75         unloadAll();
    76     }
    78     private Optional<LightPITModule> getModuleInfo(Registration reg) {
    79         try {
    80             final Class<?> scclass = Class.forName(reg.getClassName());
    82             final boolean lpservlet = AbstractLightPITServlet.class.isAssignableFrom(scclass);
    83             final boolean lpmodule = scclass.isAnnotationPresent(LightPITModule.class);
    85             if (lpservlet && !lpmodule) {
    86                 LOG.warn(
    87                         "{} is a LightPIT Servlet but is missing the module annotation.",
    88                         reg.getClassName()
    89                 );
    90             } else if (!lpservlet && lpmodule) {
    91                 LOG.warn(
    92                         "{} is annotated as a LightPIT Module but does not extend {}.",
    93                         reg.getClassName(),
    94                         AbstractLightPITServlet.class.getSimpleName()
    95                 );
    96             }
    98             if (lpservlet && lpmodule) {
    99                 final LightPITModule moduleInfo = scclass.getAnnotation(LightPITModule.class);
   100                 return Optional.of(moduleInfo);
   101             } else {
   102                 return Optional.empty();
   103             }
   104         } catch (ClassNotFoundException ex) {
   105             LOG.error(
   106                     "Servlet registration refers to class {} which cannot be found by the class loader (Reason: {})",
   107                     reg.getClassName(),
   108                     ex.getMessage()
   109             );
   110             return Optional.empty();
   111         }
   112     }
   114     private void handleServletRegistration(String name, Registration reg) {
   115         final Optional<LightPITModule> moduleInfo = getModuleInfo(reg);
   116         if (moduleInfo.isPresent()) {
   117             registeredModules.put(reg.getClassName(), moduleInfo.get());
   118             LOG.info("Module detected: {}", name);
   119         } else {
   120             LOG.debug("Servlet {} is no module, skipping.", name);
   121         }
   122     }
   124     /**
   125      * Scans for modules and reloads them all.
   126      */
   127     public void reloadAll() {
   128         registeredModules.clear();
   129         sc.getServletRegistrations().forEach(this::handleServletRegistration);
   130         createMainMenu();
   132         LOG.info("Modules loaded.");
   133     }
   135     /**
   136      * Unloads all found modules.
   137      */
   138     public void unloadAll() {
   139         registeredModules.clear();
   140         LOG.info("All modules unloaded.");
   141     }
   143     /**
   144      * Populates the main menu based on the registered modules.
   145      */
   146     private void createMainMenu() {
   147         mainMenu.clear();
   148         registeredModules.entrySet()
   149                 .stream()
   150                 .filter(mod -> !mod.getValue().systemModule())
   151                 .map(mod -> new MenuEntry(
   152                         mod.getKey(),
   153                         new ResourceKey(
   154                                 mod.getValue().bundleBaseName(),
   155                                 mod.getValue().menuKey()),
   156                         mod.getValue().modulePath(),
   157                         mod.getValue().defaultPriority()))
   158                 .sorted()
   159                 .forEachOrdered(mainMenu::add);
   160     }
   162     /**
   163      * Returns the main menu.
   164      *
   165      * @return a list of menu items
   166      */
   167     public List<MenuEntry> getMainMenu() {
   168         return Collections.unmodifiableList(mainMenu);
   169     }
   170 }

mercurial