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

Wed, 13 May 2020 21:10:23 +0200

author
Mike Becker <universe@uap-core.de>
date
Wed, 13 May 2020 21:10:23 +0200
changeset 45
cc7f082c5ef3
parent 36
0f4f8f255c32
child 57
1262b5433644
permissions
-rw-r--r--

simplifies menu generation, adds submenus and removes VersionsModule (versions will be part of the 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.ArrayList;
    40 import java.util.Collections;
    41 import java.util.List;
    42 import java.util.Optional;
    44 /**
    45  * Scans registered servlets for LightPIT modules.
    46  */
    47 @WebListener
    48 public final class ModuleManager implements ServletContextListener {
    50     private static final Logger LOG = LoggerFactory.getLogger(ModuleManager.class);
    52     /**
    53      * The attribute name in the servlet context under which an instance of this class can be found.
    54      */
    55     public static final String SC_ATTR_NAME = ModuleManager.class.getName();
    56     private ServletContext sc;
    58     /**
    59      * Maps class names to module information.
    60      */
    61     private final List<LightPITModule> registeredModules = new ArrayList<>();
    63     /**
    64      * Contains the menu entries for the loaded modules.
    65      */
    66     private final List<MenuEntry> mainMenu = new ArrayList<>();
    68     @Override
    69     public void contextInitialized(ServletContextEvent sce) {
    70         sc = sce.getServletContext();
    71         reloadAll();
    72         sc.setAttribute(SC_ATTR_NAME, this);
    73         LOG.info("Module manager injected into ServletContext.");
    74     }
    76     @Override
    77     public void contextDestroyed(ServletContextEvent sce) {
    78         unloadAll();
    79     }
    81     private Optional<LightPITModule> getModuleInfo(Registration reg) {
    82         try {
    83             final Class<?> scclass = Class.forName(reg.getClassName());
    85             final boolean lpservlet = AbstractLightPITServlet.class.isAssignableFrom(scclass);
    86             final boolean lpmodule = scclass.isAnnotationPresent(LightPITModule.class);
    88             if (lpservlet && !lpmodule) {
    89                 LOG.warn(
    90                         "{} is a LightPIT Servlet but is missing the module annotation.",
    91                         reg.getClassName()
    92                 );
    93             } else if (!lpservlet && lpmodule) {
    94                 LOG.warn(
    95                         "{} is annotated as a LightPIT Module but does not extend {}.",
    96                         reg.getClassName(),
    97                         AbstractLightPITServlet.class.getSimpleName()
    98                 );
    99             }
   101             if (lpservlet && lpmodule) {
   102                 final LightPITModule moduleInfo = scclass.getAnnotation(LightPITModule.class);
   103                 return Optional.of(moduleInfo);
   104             } else {
   105                 return Optional.empty();
   106             }
   107         } catch (ClassNotFoundException ex) {
   108             LOG.error(
   109                     "Servlet registration refers to class {} which cannot be found by the class loader (Reason: {})",
   110                     reg.getClassName(),
   111                     ex.getMessage()
   112             );
   113             return Optional.empty();
   114         }
   115     }
   117     private void handleServletRegistration(String name, Registration reg) {
   118         final Optional<LightPITModule> moduleInfo = getModuleInfo(reg);
   119         if (moduleInfo.isPresent()) {
   120             registeredModules.add(moduleInfo.get());
   121             LOG.info("Module detected: {}", name);
   122         } else {
   123             LOG.debug("Servlet {} is no module, skipping.", name);
   124         }
   125     }
   127     /**
   128      * Scans for modules and reloads them all.
   129      */
   130     public void reloadAll() {
   131         registeredModules.clear();
   132         sc.getServletRegistrations().forEach(this::handleServletRegistration);
   133         createMainMenu();
   135         LOG.info("Modules loaded.");
   136     }
   138     /**
   139      * Unloads all found modules.
   140      */
   141     public void unloadAll() {
   142         registeredModules.clear();
   143         LOG.info("All modules unloaded.");
   144     }
   146     /**
   147      * Populates the main menu based on the registered modules.
   148      */
   149     private void createMainMenu() {
   150         mainMenu.clear();
   151         registeredModules
   152                 .stream()
   153                 .filter(mod -> !mod.systemModule())
   154                 .map(mod -> new MenuEntry(
   155                         new ResourceKey(
   156                                 mod.bundleBaseName(),
   157                                 mod.menuKey()),
   158                         mod.modulePath(),
   159                         mod.defaultPriority()))
   160                 .sorted()
   161                 .forEachOrdered(mainMenu::add);
   162     }
   164     /**
   165      * Returns the main menu.
   166      *
   167      * @return a list of menu items
   168      */
   169     public List<MenuEntry> getMainMenu() {
   170         return Collections.unmodifiableList(mainMenu);
   171     }
   172 }

mercurial