--- a/src/java/de/uapcore/lightpit/ModuleManager.java Sun Apr 08 15:34:11 2018 +0200 +++ b/src/java/de/uapcore/lightpit/ModuleManager.java Sun Apr 08 16:41:02 2018 +0200 @@ -29,6 +29,7 @@ package de.uapcore.lightpit; import de.uapcore.lightpit.entities.CoreDAOFactory; +import de.uapcore.lightpit.entities.Module; import de.uapcore.lightpit.entities.ModuleDao; import java.sql.Connection; import java.sql.SQLException; @@ -36,9 +37,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Optional; -import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import javax.servlet.Registration; @@ -64,18 +63,15 @@ private ServletContext sc; /** + * Maps class names to module information. + */ + private final Map<String, LightPITModule> registeredModules = new HashMap<>(); + + /** * This flag is true, when synchronization is needed. */ private final AtomicBoolean dirty = new AtomicBoolean(true); - private final CopyOnWriteArrayList<Menu> mainMenu = new CopyOnWriteArrayList<>(); - private final List<Menu> immutableMainMenu = Collections.unmodifiableList(mainMenu); - - /** - * Maps class names to module information. - */ - private final Map<String, LightPITModule> registeredModules = new HashMap<>(); - @Override public void contextInitialized(ServletContextEvent sce) { sc = sce.getServletContext(); @@ -152,6 +148,13 @@ /** * Synchronizes module information with the database. * + * This must be called from the {@link AbstractLightPITServlet}. + * Admittedly the call will perform the synchronization once after reload + * and be a no-op, afterwards. + * However, we since the DatabaseFacade might be loaded after the module + * manager, we must defer the synchronization to the first request + * handled by the Servlet. + * * @param db interface to the database */ public void syncWithDatabase(DatabaseFacade db) { @@ -159,27 +162,12 @@ if (db.getDataSource().isPresent()) { try (Connection conn = db.getDataSource().get().getConnection()) { final ModuleDao moduleDao = CoreDAOFactory.getModuleDao(db.getSQLDialect()); - - final List<Entry<String, LightPITModule>> visibleModules = - moduleDao.syncRegisteredModuleClasses(conn, registeredModules.entrySet()); - - final List<Menu> updatedMenu = visibleModules - .stream() - .collect(Collectors.mapping( - (mod) -> new Menu( - mod.getKey(), - new ResourceKey(mod.getValue().bundleBaseName(), mod.getValue().menuKey()), - mod.getValue().modulePath()), - Collectors.toList()) - ); - - mainMenu.removeIf((e) -> !updatedMenu.contains(e)); - mainMenu.addAllAbsent(updatedMenu); + moduleDao.syncRegisteredModuleClasses(conn, registeredModules.entrySet()); } catch (SQLException ex) { LOG.error("Unexpected SQL Exception", ex); } } else { - LOG.warn("No datasource present. Cannot sync module information with database."); + LOG.error("No datasource present. Cannot sync module information with database."); } } else { LOG.trace("Module information clean - no synchronization required."); @@ -190,17 +178,44 @@ * Unloads all found modules. */ public void unloadAll() { - mainMenu.clear(); registeredModules.clear(); LOG.info("All modules unloaded."); } /** * Returns the main menu. + * + * @param db the interface to the database * @return a list of menus belonging to the main menu */ - public List<Menu> getMainMenu() { - return immutableMainMenu; + public List<Menu> getMainMenu(DatabaseFacade db) { + // TODO: user specific menu + + if (db.getDataSource().isPresent()) { + try (Connection conn = db.getDataSource().get().getConnection()) { + final ModuleDao dao = CoreDAOFactory.getModuleDao(db.getSQLDialect()); + final List<Module> modules = dao.listAll(conn); + + final List<Menu> menu = modules + .stream() + .filter((mod) -> mod.isVisible()) + .collect(Collectors.mapping( + (mod) -> new Menu( + mod.getClassname(), + new ResourceKey( + registeredModules.get(mod.getClassname()).bundleBaseName(), + registeredModules.get(mod.getClassname()).menuKey()), + registeredModules.get(mod.getClassname()).modulePath()), + Collectors.toList()) + ); + return menu; + } catch (SQLException ex) { + LOG.error("Unexpected SQLException when loading the main menu", ex); + return Collections.emptyList(); + } + } else { + return Collections.emptyList(); + } } /**