1.1 --- a/src/java/de/uapcore/lightpit/ModuleManager.java Sun Apr 08 15:34:11 2018 +0200 1.2 +++ b/src/java/de/uapcore/lightpit/ModuleManager.java Sun Apr 08 16:41:02 2018 +0200 1.3 @@ -29,6 +29,7 @@ 1.4 package de.uapcore.lightpit; 1.5 1.6 import de.uapcore.lightpit.entities.CoreDAOFactory; 1.7 +import de.uapcore.lightpit.entities.Module; 1.8 import de.uapcore.lightpit.entities.ModuleDao; 1.9 import java.sql.Connection; 1.10 import java.sql.SQLException; 1.11 @@ -36,9 +37,7 @@ 1.12 import java.util.HashMap; 1.13 import java.util.List; 1.14 import java.util.Map; 1.15 -import java.util.Map.Entry; 1.16 import java.util.Optional; 1.17 -import java.util.concurrent.CopyOnWriteArrayList; 1.18 import java.util.concurrent.atomic.AtomicBoolean; 1.19 import java.util.stream.Collectors; 1.20 import javax.servlet.Registration; 1.21 @@ -64,18 +63,15 @@ 1.22 private ServletContext sc; 1.23 1.24 /** 1.25 + * Maps class names to module information. 1.26 + */ 1.27 + private final Map<String, LightPITModule> registeredModules = new HashMap<>(); 1.28 + 1.29 + /** 1.30 * This flag is true, when synchronization is needed. 1.31 */ 1.32 private final AtomicBoolean dirty = new AtomicBoolean(true); 1.33 1.34 - private final CopyOnWriteArrayList<Menu> mainMenu = new CopyOnWriteArrayList<>(); 1.35 - private final List<Menu> immutableMainMenu = Collections.unmodifiableList(mainMenu); 1.36 - 1.37 - /** 1.38 - * Maps class names to module information. 1.39 - */ 1.40 - private final Map<String, LightPITModule> registeredModules = new HashMap<>(); 1.41 - 1.42 @Override 1.43 public void contextInitialized(ServletContextEvent sce) { 1.44 sc = sce.getServletContext(); 1.45 @@ -152,6 +148,13 @@ 1.46 /** 1.47 * Synchronizes module information with the database. 1.48 * 1.49 + * This must be called from the {@link AbstractLightPITServlet}. 1.50 + * Admittedly the call will perform the synchronization once after reload 1.51 + * and be a no-op, afterwards. 1.52 + * However, we since the DatabaseFacade might be loaded after the module 1.53 + * manager, we must defer the synchronization to the first request 1.54 + * handled by the Servlet. 1.55 + * 1.56 * @param db interface to the database 1.57 */ 1.58 public void syncWithDatabase(DatabaseFacade db) { 1.59 @@ -159,27 +162,12 @@ 1.60 if (db.getDataSource().isPresent()) { 1.61 try (Connection conn = db.getDataSource().get().getConnection()) { 1.62 final ModuleDao moduleDao = CoreDAOFactory.getModuleDao(db.getSQLDialect()); 1.63 - 1.64 - final List<Entry<String, LightPITModule>> visibleModules = 1.65 - moduleDao.syncRegisteredModuleClasses(conn, registeredModules.entrySet()); 1.66 - 1.67 - final List<Menu> updatedMenu = visibleModules 1.68 - .stream() 1.69 - .collect(Collectors.mapping( 1.70 - (mod) -> new Menu( 1.71 - mod.getKey(), 1.72 - new ResourceKey(mod.getValue().bundleBaseName(), mod.getValue().menuKey()), 1.73 - mod.getValue().modulePath()), 1.74 - Collectors.toList()) 1.75 - ); 1.76 - 1.77 - mainMenu.removeIf((e) -> !updatedMenu.contains(e)); 1.78 - mainMenu.addAllAbsent(updatedMenu); 1.79 + moduleDao.syncRegisteredModuleClasses(conn, registeredModules.entrySet()); 1.80 } catch (SQLException ex) { 1.81 LOG.error("Unexpected SQL Exception", ex); 1.82 } 1.83 } else { 1.84 - LOG.warn("No datasource present. Cannot sync module information with database."); 1.85 + LOG.error("No datasource present. Cannot sync module information with database."); 1.86 } 1.87 } else { 1.88 LOG.trace("Module information clean - no synchronization required."); 1.89 @@ -190,17 +178,44 @@ 1.90 * Unloads all found modules. 1.91 */ 1.92 public void unloadAll() { 1.93 - mainMenu.clear(); 1.94 registeredModules.clear(); 1.95 LOG.info("All modules unloaded."); 1.96 } 1.97 1.98 /** 1.99 * Returns the main menu. 1.100 + * 1.101 + * @param db the interface to the database 1.102 * @return a list of menus belonging to the main menu 1.103 */ 1.104 - public List<Menu> getMainMenu() { 1.105 - return immutableMainMenu; 1.106 + public List<Menu> getMainMenu(DatabaseFacade db) { 1.107 + // TODO: user specific menu 1.108 + 1.109 + if (db.getDataSource().isPresent()) { 1.110 + try (Connection conn = db.getDataSource().get().getConnection()) { 1.111 + final ModuleDao dao = CoreDAOFactory.getModuleDao(db.getSQLDialect()); 1.112 + final List<Module> modules = dao.listAll(conn); 1.113 + 1.114 + final List<Menu> menu = modules 1.115 + .stream() 1.116 + .filter((mod) -> mod.isVisible()) 1.117 + .collect(Collectors.mapping( 1.118 + (mod) -> new Menu( 1.119 + mod.getClassname(), 1.120 + new ResourceKey( 1.121 + registeredModules.get(mod.getClassname()).bundleBaseName(), 1.122 + registeredModules.get(mod.getClassname()).menuKey()), 1.123 + registeredModules.get(mod.getClassname()).modulePath()), 1.124 + Collectors.toList()) 1.125 + ); 1.126 + return menu; 1.127 + } catch (SQLException ex) { 1.128 + LOG.error("Unexpected SQLException when loading the main menu", ex); 1.129 + return Collections.emptyList(); 1.130 + } 1.131 + } else { 1.132 + return Collections.emptyList(); 1.133 + } 1.134 } 1.135 1.136 /**