removes caching of main menu

Sun, 08 Apr 2018 16:41:02 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 08 Apr 2018 16:41:02 +0200
changeset 27
1f2a96efa69f
parent 26
65d5a0ca49ae
child 28
cfc3d11884ad

removes caching of main menu

src/java/de/uapcore/lightpit/AbstractLightPITServlet.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/ModuleManager.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/entities/ModuleDao.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/java/de/uapcore/lightpit/AbstractLightPITServlet.java	Sun Apr 08 15:34:11 2018 +0200
     1.2 +++ b/src/java/de/uapcore/lightpit/AbstractLightPITServlet.java	Sun Apr 08 16:41:02 2018 +0200
     1.3 @@ -222,7 +222,7 @@
     1.4      private void forwardToFullView(HttpServletRequest req, HttpServletResponse resp)
     1.5              throws IOException, ServletException {
     1.6          
     1.7 -        req.setAttribute(Constants.REQ_ATTR_MENU, getModuleManager().getMainMenu());
     1.8 +        req.setAttribute(Constants.REQ_ATTR_MENU, getModuleManager().getMainMenu(getDatabaseFacade()));
     1.9          req.getRequestDispatcher(HTML_FULL_DISPATCHER).forward(req, resp);
    1.10      }
    1.11      
    1.12 @@ -249,7 +249,7 @@
    1.13      
    1.14      private void doProcess(HttpMethod method, HttpServletRequest req, HttpServletResponse resp)
    1.15              throws ServletException, IOException {
    1.16 -        
    1.17 +
    1.18          // Synchronize module information with database
    1.19          getModuleManager().syncWithDatabase(getDatabaseFacade());
    1.20          
     2.1 --- a/src/java/de/uapcore/lightpit/ModuleManager.java	Sun Apr 08 15:34:11 2018 +0200
     2.2 +++ b/src/java/de/uapcore/lightpit/ModuleManager.java	Sun Apr 08 16:41:02 2018 +0200
     2.3 @@ -29,6 +29,7 @@
     2.4  package de.uapcore.lightpit;
     2.5  
     2.6  import de.uapcore.lightpit.entities.CoreDAOFactory;
     2.7 +import de.uapcore.lightpit.entities.Module;
     2.8  import de.uapcore.lightpit.entities.ModuleDao;
     2.9  import java.sql.Connection;
    2.10  import java.sql.SQLException;
    2.11 @@ -36,9 +37,7 @@
    2.12  import java.util.HashMap;
    2.13  import java.util.List;
    2.14  import java.util.Map;
    2.15 -import java.util.Map.Entry;
    2.16  import java.util.Optional;
    2.17 -import java.util.concurrent.CopyOnWriteArrayList;
    2.18  import java.util.concurrent.atomic.AtomicBoolean;
    2.19  import java.util.stream.Collectors;
    2.20  import javax.servlet.Registration;
    2.21 @@ -64,18 +63,15 @@
    2.22      private ServletContext sc;
    2.23      
    2.24      /**
    2.25 +     * Maps class names to module information.
    2.26 +     */
    2.27 +    private final Map<String, LightPITModule> registeredModules = new HashMap<>();
    2.28 +    
    2.29 +    /**
    2.30       * This flag is true, when synchronization is needed.
    2.31       */
    2.32      private final AtomicBoolean dirty = new AtomicBoolean(true);
    2.33      
    2.34 -    private final CopyOnWriteArrayList<Menu> mainMenu = new CopyOnWriteArrayList<>();
    2.35 -    private final List<Menu> immutableMainMenu = Collections.unmodifiableList(mainMenu);
    2.36 -    
    2.37 -    /**
    2.38 -     * Maps class names to module information.
    2.39 -     */
    2.40 -    private final Map<String, LightPITModule> registeredModules = new HashMap<>();
    2.41 -    
    2.42      @Override
    2.43      public void contextInitialized(ServletContextEvent sce) {
    2.44          sc = sce.getServletContext();
    2.45 @@ -152,6 +148,13 @@
    2.46      /**
    2.47       * Synchronizes module information with the database.
    2.48       * 
    2.49 +     * This must be called from the {@link AbstractLightPITServlet}.
    2.50 +     * Admittedly the call will perform the synchronization once after reload
    2.51 +     * and be a no-op, afterwards.
    2.52 +     * However, we since the DatabaseFacade might be loaded after the module
    2.53 +     * manager, we must defer the synchronization to the first request
    2.54 +     * handled by the Servlet.
    2.55 +     * 
    2.56       * @param db interface to the database
    2.57       */
    2.58      public void syncWithDatabase(DatabaseFacade db) {
    2.59 @@ -159,27 +162,12 @@
    2.60              if (db.getDataSource().isPresent()) {
    2.61                  try (Connection conn = db.getDataSource().get().getConnection()) {
    2.62                      final ModuleDao moduleDao = CoreDAOFactory.getModuleDao(db.getSQLDialect());
    2.63 -                    
    2.64 -                    final List<Entry<String, LightPITModule>> visibleModules =
    2.65 -                            moduleDao.syncRegisteredModuleClasses(conn, registeredModules.entrySet());
    2.66 -                    
    2.67 -                    final List<Menu> updatedMenu = visibleModules
    2.68 -                            .stream()
    2.69 -                            .collect(Collectors.mapping(
    2.70 -                                    (mod) -> new Menu(
    2.71 -                                            mod.getKey(),
    2.72 -                                            new ResourceKey(mod.getValue().bundleBaseName(), mod.getValue().menuKey()),
    2.73 -                                            mod.getValue().modulePath()),
    2.74 -                                    Collectors.toList())
    2.75 -                            );
    2.76 -                    
    2.77 -                    mainMenu.removeIf((e) -> !updatedMenu.contains(e));
    2.78 -                    mainMenu.addAllAbsent(updatedMenu);
    2.79 +                    moduleDao.syncRegisteredModuleClasses(conn, registeredModules.entrySet());
    2.80                  } catch (SQLException ex) {
    2.81                      LOG.error("Unexpected SQL Exception", ex);
    2.82                  }
    2.83              } else {
    2.84 -                LOG.warn("No datasource present. Cannot sync module information with database.");
    2.85 +                LOG.error("No datasource present. Cannot sync module information with database.");
    2.86              }
    2.87          } else {
    2.88              LOG.trace("Module information clean - no synchronization required.");
    2.89 @@ -190,17 +178,44 @@
    2.90       * Unloads all found modules.
    2.91       */
    2.92      public void unloadAll() {
    2.93 -        mainMenu.clear();
    2.94          registeredModules.clear();
    2.95          LOG.info("All modules unloaded.");
    2.96      }
    2.97  
    2.98      /**
    2.99       * Returns the main menu.
   2.100 +     * 
   2.101 +     * @param db the interface to the database
   2.102       * @return a list of menus belonging to the main menu
   2.103       */
   2.104 -    public List<Menu> getMainMenu() {
   2.105 -        return immutableMainMenu;
   2.106 +    public List<Menu> getMainMenu(DatabaseFacade db) {
   2.107 +        // TODO: user specific menu
   2.108 +        
   2.109 +        if (db.getDataSource().isPresent()) {
   2.110 +            try (Connection conn = db.getDataSource().get().getConnection()) {
   2.111 +                final ModuleDao dao = CoreDAOFactory.getModuleDao(db.getSQLDialect());
   2.112 +                final List<Module> modules = dao.listAll(conn);
   2.113 +                
   2.114 +                final List<Menu> menu = modules
   2.115 +                    .stream()
   2.116 +                    .filter((mod) -> mod.isVisible())
   2.117 +                    .collect(Collectors.mapping(
   2.118 +                            (mod) -> new Menu(
   2.119 +                                    mod.getClassname(),
   2.120 +                                    new ResourceKey(
   2.121 +                                            registeredModules.get(mod.getClassname()).bundleBaseName(),
   2.122 +                                            registeredModules.get(mod.getClassname()).menuKey()),
   2.123 +                                    registeredModules.get(mod.getClassname()).modulePath()),
   2.124 +                            Collectors.toList())
   2.125 +                    );
   2.126 +                return menu;
   2.127 +            } catch (SQLException ex) {
   2.128 +                LOG.error("Unexpected SQLException when loading the main menu", ex);
   2.129 +                return Collections.emptyList();
   2.130 +            }
   2.131 +        } else {
   2.132 +            return Collections.emptyList();
   2.133 +        }
   2.134      }
   2.135      
   2.136      /**
     3.1 --- a/src/java/de/uapcore/lightpit/entities/ModuleDao.java	Sun Apr 08 15:34:11 2018 +0200
     3.2 +++ b/src/java/de/uapcore/lightpit/entities/ModuleDao.java	Sun Apr 08 16:41:02 2018 +0200
     3.3 @@ -34,7 +34,6 @@
     3.4  import java.sql.ResultSet;
     3.5  import java.sql.SQLException;
     3.6  import java.sql.Statement;
     3.7 -import java.util.AbstractMap;
     3.8  import java.util.ArrayList;
     3.9  import java.util.List;
    3.10  import java.util.Map;
    3.11 @@ -88,18 +87,16 @@
    3.12      }
    3.13      
    3.14      /**
    3.15 -     * Synchronizes a set of registered module classes with the database and gives a list of visible modules in return.
    3.16 +     * Synchronizes a set of registered module classes with the database.
    3.17       * 
    3.18       * Inserts module classes which are not known to the database and sets them to be visible by default.
    3.19       * Module classes known to the database, which are not in the given set, are ignored.
    3.20       * 
    3.21       * @param conn the connection to use
    3.22       * @param moduleSet the module set to synchronize
    3.23 -     * @return a list of elements from the given set, which should be visible in the menu
    3.24       * @throws SQLException
    3.25       */
    3.26 -    public final List<Map.Entry<String, LightPITModule>>
    3.27 -            syncRegisteredModuleClasses(Connection conn, Set<Map.Entry<String, LightPITModule>> moduleSet) throws SQLException {
    3.28 +    public final void syncRegisteredModuleClasses(Connection conn, Set<Map.Entry<String, LightPITModule>> moduleSet) throws SQLException {
    3.29                  
    3.30          PreparedStatement
    3.31                  check = moduleCheckStatement(conn),
    3.32 @@ -107,30 +104,17 @@
    3.33          insert.setBoolean(2, true);
    3.34          // update/delete not required, we do this in the module management UI
    3.35  
    3.36 -        final List<Map.Entry<String, LightPITModule>> visibleModules = new ArrayList<>();
    3.37 +        for (Map.Entry<String, LightPITModule> modEntry : moduleSet) {
    3.38 +            if (modEntry.getValue().systemModule()) continue;
    3.39  
    3.40 -        for (Map.Entry<String, LightPITModule> mod : moduleSet) {
    3.41 -            if (mod.getValue().systemModule()) continue;
    3.42 -
    3.43 -            check.setString(1, mod.getKey());
    3.44 +            check.setString(1, modEntry.getKey());
    3.45              try (ResultSet r = check.executeQuery()) {
    3.46 -                final boolean visible;
    3.47 -                if (r.next()) {
    3.48 -                    visible = r.getBoolean(1);
    3.49 -                } else {
    3.50 -                    insert.setString(1, mod.getKey());
    3.51 +                if (!r.next()) {
    3.52 +                    insert.setString(1, modEntry.getKey());
    3.53                      insert.executeUpdate();
    3.54 -                    visible = !mod.getValue().menuKey().isEmpty();
    3.55 -                }
    3.56 -                if (visible) {
    3.57 -                    visibleModules.add(new AbstractMap.SimpleEntry<>(
    3.58 -                            mod.getKey(),
    3.59 -                            mod.getValue()
    3.60 -                    ));
    3.61                  }
    3.62              }
    3.63          }
    3.64 -        return visibleModules;
    3.65      }
    3.66  
    3.67      /**
    3.68 @@ -144,8 +128,7 @@
    3.69       */
    3.70      public List<Module> listAll(Connection conn) throws SQLException {
    3.71          List<Module> list = new ArrayList<>();
    3.72 -        try (
    3.73 -                Statement stmt = conn.createStatement();
    3.74 +        try (Statement stmt = conn.createStatement();
    3.75                  ResultSet result = stmt.executeQuery("SELECT * FROM lpitcore_module")) {
    3.76              while (result.next()) {
    3.77                  final Module mod = new Module();

mercurial