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

changeset 20
bd1a76c91d5b
parent 18
a94b172c3a93
child 21
b213fef2539e
--- a/src/java/de/uapcore/lightpit/ModuleManager.java	Sat Mar 31 18:11:09 2018 +0200
+++ b/src/java/de/uapcore/lightpit/ModuleManager.java	Sat Mar 31 19:35:04 2018 +0200
@@ -28,11 +28,19 @@
  */
 package de.uapcore.lightpit;
 
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
-import java.util.Objects;
+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 javax.servlet.Registration;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
@@ -55,9 +63,19 @@
     public static final String SC_ATTR_NAME = ModuleManager.class.getName();
     private ServletContext sc;
     
-    private final List<Menu> mainMenu = new ArrayList<>();
+    /**
+     * This flag is true, when synchronization is needed.
+     */
+    private 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();
@@ -108,24 +126,10 @@
         }        
     }
     
-    private void addModuleToMenu(String moduleClassName, LightPITModule moduleInfo) {
-        final Menu menu = new Menu(
-                moduleClassName,
-                new ResourceKey(moduleInfo.bundleBaseName(), moduleInfo.menuKey()),
-                moduleInfo.modulePath()
-        );
-        mainMenu.add(menu);
-    }
-    
     private void handleServletRegistration(String name, Registration reg) {
         final Optional<LightPITModule> moduleInfo = getModuleInfo(reg);
-        if (moduleInfo.isPresent()) {            
-            // TODO: implement dependency resolver
-            
-            if (!moduleInfo.get().menuKey().isEmpty()) {
-                addModuleToMenu(reg.getClassName(), moduleInfo.get());
-            }
-            
+        if (moduleInfo.isPresent()) {
+            registeredModules.put(reg.getClassName(), moduleInfo.get());            
             LOG.info("Module detected: {}", name);
         } else {
             LOG.debug("Servlet {} is no module, skipping.", name);
@@ -137,10 +141,66 @@
      */
     public void reloadAll() {
         sc.getServletRegistrations().forEach(this::handleServletRegistration);
+        
+        // TODO: implement dependency resolver
+        
         LOG.info("Modules loaded.");
     }
     
     /**
+     * Synchronizes module information with the database.
+     * 
+     * @param db interface to the database
+     */
+    public void syncWithDatabase(DatabaseFacade db) {
+        if (dirty.compareAndSet(true, false)) {
+            if (db.getDataSource().isPresent()) {
+                try (Connection conn = db.getDataSource().get().getConnection()) {
+                    PreparedStatement
+                            check = conn.prepareStatement("SELECT visible FROM lpitcore_module WHERE classname = ?"),
+                            insert = conn.prepareStatement("INSERT INTO lpitcore_module (classname, visible) VALUES (?, ?)");
+                    insert.setBoolean(2, true);
+                    // update/delete not required, we do this in the module management UI
+                    
+                    final List<Menu> updatedMenu = new ArrayList<>();
+                    
+                    for (Entry<String, LightPITModule> mod : registeredModules.entrySet()) {
+                        if (mod.getValue().systemModule()) continue;
+                        
+                        check.setString(1, mod.getKey());
+                        try (ResultSet r = check.executeQuery()) {
+                            final boolean addToMenu;
+                            if (r.next()) {
+                                addToMenu = r.getBoolean(1);
+                            } else {
+                                insert.setString(1, mod.getKey());
+                                insert.executeUpdate();
+                                addToMenu = !mod.getValue().menuKey().isEmpty();
+                            }
+                            if (addToMenu) {
+                                updatedMenu.add(new Menu(
+                                        mod.getKey(),
+                                        new ResourceKey(mod.getValue().bundleBaseName(), mod.getValue().menuKey()),
+                                        mod.getValue().modulePath()
+                                ));
+                            }
+                        }
+                    }
+                    
+                    mainMenu.removeIf((e) -> !updatedMenu.contains(e));
+                    mainMenu.addAllAbsent(updatedMenu);
+                } catch (SQLException ex) {
+                    LOG.error("Unexpected SQL Exception", ex);
+                }
+            } else {
+                LOG.warn("No datasource present. Cannot sync module information with database.");
+            }
+        } else {
+            LOG.debug("Module information clean - no synchronization required.");
+        }
+    }
+    
+    /**
      * Unloads all found modules.
      */
     public void unloadAll() {

mercurial