adds first part of a module manager UI

Sun, 01 Apr 2018 18:16:47 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 01 Apr 2018 18:16:47 +0200
changeset 21
b213fef2539e
parent 20
bd1a76c91d5b
child 22
5a91fb7067af

adds first part of a module manager UI

src/java/de/uapcore/lightpit/AbstractLightPITServlet.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/LightPITModule.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/ModuleManager.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/entities/CoreDAOFactory.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/entities/Module.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/entities/ModuleDao.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/entities/PostgresModuleDao.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/modules/ModuleManagerModule.java file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/resources/localization/modmgmt.properties file | annotate | diff | comparison | revisions
src/java/de/uapcore/lightpit/resources/localization/modmgmt_de.properties file | annotate | diff | comparison | revisions
web/WEB-INF/dynamic_fragments/modules.jsp file | annotate | diff | comparison | revisions
--- a/src/java/de/uapcore/lightpit/AbstractLightPITServlet.java	Sat Mar 31 19:35:04 2018 +0200
+++ b/src/java/de/uapcore/lightpit/AbstractLightPITServlet.java	Sun Apr 01 18:16:47 2018 +0200
@@ -266,10 +266,13 @@
             LOG.trace("Continuing session {} with language {}", session.getId(), sessionLocale);
         }
         
+        // set some internal request attributes
         req.setAttribute(Constants.REQ_ATTR_PATH, Functions.fullPath(req));
         req.setAttribute(Constants.REQ_ATTR_MODULE_CLASSNAME, this.getClass().getName());
         moduleInfoELProxy.ifPresent((proxy) -> req.setAttribute(Constants.REQ_ATTR_MODULE_INFO, proxy));
         
+        
+        // call the handler, if available, or send an HTTP 404 error
         Optional<HandlerMethod> mapping = findMapping(method, req);
         if (mapping.isPresent()) {
             forwardAsSepcified(mapping.get().apply(req, resp), req, resp);
--- a/src/java/de/uapcore/lightpit/LightPITModule.java	Sat Mar 31 19:35:04 2018 +0200
+++ b/src/java/de/uapcore/lightpit/LightPITModule.java	Sun Apr 01 18:16:47 2018 +0200
@@ -60,7 +60,7 @@
     String[] requires() default {};
     
     /**
-     * The path for this module, which will be used for the menu entry.
+     * The path for this module, which will also be used for the menu entry.
      * 
      * This path must adhere to the URL pattern of the Servlet but must not
      * contain any starting or trailing slashes.
@@ -70,6 +70,21 @@
     String modulePath();
     
     /**
+     * Returns the properties key for the module name.
+     * 
+     * @return the properties key
+     */
+    String nameKey() default "name";
+    
+    /**
+     * Returns the properties key for the module description.
+     * 
+     * @return the properties key
+     */
+    String descKey() default "description";
+    
+    
+    /**
      * Returns the properties key for the menu label.
      * 
      * Set this string to empty string, if the module should be hidden from
@@ -105,22 +120,26 @@
      * are proxied by this object.
      */
     public static class ELProxy {
-        private final String bundleBaseName, modulePath, menuKey, titleKey;
+        private final String bundleBaseName, modulePath, menuKey, titleKey, nameKey, descKey;
         
         public static ELProxy convert(LightPITModule annotation) {
             return new ELProxy(
                     annotation.bundleBaseName(),
                     annotation.modulePath(),
                     annotation.menuKey(),
-                    annotation.titleKey()
+                    annotation.titleKey(),
+                    annotation.nameKey(),
+                    annotation.descKey()
             );
         }
 
-        private ELProxy(String bundleBaseName, String modulePath, String menuKey, String titleKey) {
+        private ELProxy(String bundleBaseName, String modulePath, String menuKey, String titleKey, String nameKey, String descKey) {
             this.bundleBaseName = bundleBaseName;
             this.modulePath = modulePath;
             this.menuKey = menuKey;
             this.titleKey = titleKey;
+            this.nameKey = nameKey;
+            this.descKey = descKey;
         }
 
         public String getBundleBaseName() {
@@ -138,5 +157,14 @@
         public String getTitleKey() {
             return titleKey;
         }
+
+        public String getNameKey() {
+            return nameKey;
+        }
+
+        public String getDescKey() {
+            return descKey;
+        }
+        
     }
 }
--- a/src/java/de/uapcore/lightpit/ModuleManager.java	Sat Mar 31 19:35:04 2018 +0200
+++ b/src/java/de/uapcore/lightpit/ModuleManager.java	Sun Apr 01 18:16:47 2018 +0200
@@ -28,11 +28,11 @@
  */
 package de.uapcore.lightpit;
 
+import de.uapcore.lightpit.entities.CoreDAOFactory;
+import de.uapcore.lightpit.entities.ModuleDao;
 import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -41,6 +41,7 @@
 import java.util.Optional;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
 import javax.servlet.Registration;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
@@ -66,7 +67,7 @@
     /**
      * This flag is true, when synchronization is needed.
      */
-    private AtomicBoolean dirty = new AtomicBoolean(true);
+    private final AtomicBoolean dirty = new AtomicBoolean(true);
     
     private final CopyOnWriteArrayList<Menu> mainMenu = new CopyOnWriteArrayList<>();
     private final List<Menu> immutableMainMenu = Collections.unmodifiableList(mainMenu);
@@ -140,10 +141,12 @@
      * Scans for modules and reloads them all.
      */
     public void reloadAll() {
+        registeredModules.clear();
         sc.getServletRegistrations().forEach(this::handleServletRegistration);
         
         // TODO: implement dependency resolver
         
+        dirty.set(true);
         LOG.info("Modules loaded.");
     }
     
@@ -156,36 +159,20 @@
         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 ModuleDao moduleDao = CoreDAOFactory.getModuleDao(db.getSQLDialect());
                     
-                    final List<Menu> updatedMenu = new ArrayList<>();
+                    final List<Entry<String, LightPITModule>> visibleModules =
+                            moduleDao.syncRegisteredModuleClasses(conn, registeredModules.entrySet());
                     
-                    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()
-                                ));
-                            }
-                        }
-                    }
+                    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);
@@ -205,6 +192,7 @@
      */
     public void unloadAll() {
         mainMenu.clear();
+        registeredModules.clear();
         LOG.info("All modules unloaded.");
     }
 
@@ -215,4 +203,15 @@
     public List<Menu> getMainMenu() {
         return immutableMainMenu;
     }
+    
+    /**
+     * Returns an unmodifiable map of all registered modules.
+     * 
+     * The key is the classname of the module.
+     * 
+     * @return the map of registered modules
+     */
+    public Map<String, LightPITModule> getRegisteredModules() {
+        return Collections.unmodifiableMap(registeredModules);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java/de/uapcore/lightpit/entities/CoreDAOFactory.java	Sun Apr 01 18:16:47 2018 +0200
@@ -0,0 +1,47 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ * 
+ * Copyright 2017 Mike Becker. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * 
+ */
+package de.uapcore.lightpit.entities;
+
+import de.uapcore.lightpit.DatabaseFacade;
+
+public final class CoreDAOFactory {
+    
+    private CoreDAOFactory() {}
+    
+    private static class PostgresDaos {
+        static final ModuleDao MODULE_DAO = new PostgresModuleDao();
+    }
+    
+    public static ModuleDao getModuleDao(DatabaseFacade.Dialect dialect) {
+        switch (dialect) {
+            case Postgres: return PostgresDaos.MODULE_DAO;
+            default: assert(false); return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java/de/uapcore/lightpit/entities/Module.java	Sun Apr 01 18:16:47 2018 +0200
@@ -0,0 +1,90 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ * 
+ * Copyright 2017 Mike Becker. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * 
+ */
+package de.uapcore.lightpit.entities;
+
+import de.uapcore.lightpit.LightPITModule;
+
+public class Module {
+    private int modID;
+    private String classname;
+    private boolean visible;
+    
+    private LightPITModule.ELProxy annotatedInfos;
+
+    public int getModID() {
+        return modID;
+    }
+
+    public void setModID(int modID) {
+        this.modID = modID;
+    }
+
+    public String getClassname() {
+        return classname;
+    }
+
+    public void setClassname(String classname) {
+        this.classname = classname;
+    }
+
+    public boolean isVisible() {
+        return visible;
+    }
+
+    public void setVisible(boolean visible) {
+        this.visible = visible;
+    }
+
+    public LightPITModule.ELProxy getAnnotatedInfos() {
+        return annotatedInfos;
+    }
+
+    public void setAnnotatedInfos(LightPITModule.ELProxy annotatedInfos) {
+        this.annotatedInfos = annotatedInfos;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 3;
+        hash = 41 * hash + this.modID;
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        } else {
+            return this.modID == ((Module) obj).modID;
+        }
+    }    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java/de/uapcore/lightpit/entities/ModuleDao.java	Sun Apr 01 18:16:47 2018 +0200
@@ -0,0 +1,147 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ * 
+ * Copyright 2017 Mike Becker. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * 
+ */
+package de.uapcore.lightpit.entities;
+
+import de.uapcore.lightpit.LightPITModule;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public abstract class ModuleDao {
+    
+    /**
+     * Must return a prepared statement for a single object query with the specified properties.
+     * 
+     * <ul>
+     * <li>Parameter 1: classname</li>
+     * <li>Result field 1: visible</li>
+     * </ul>
+     * 
+     * @param conn the connection to use
+     * @return the prepared statement
+     * @throws SQLException 
+     */
+    protected PreparedStatement moduleCheckStatement(Connection conn) throws SQLException {
+        return conn.prepareStatement("SELECT visible FROM lpitcore_module WHERE classname = ?");
+    }
+    
+    /**
+     * Must return a prepared statement for insertion with the specified properties.
+     * 
+     * <ul>
+     * <li>Parameter 1: classname</li>
+     * <li>Parameter 2: visible</li>
+     * </ul>
+     * 
+     * @param conn the connection to use
+     * @return the prepared statement
+     * @throws SQLException 
+     */
+    protected PreparedStatement moduleInsertStatement(Connection conn) throws SQLException {
+        return conn.prepareStatement("INSERT INTO lpitcore_module (classname, visible) VALUES (?, ?)");
+    }
+    
+    /**
+     * Synchronizes a set of registered module classes with the database and gives a list of visible modules in return.
+     * 
+     * Inserts module classes which are not known to the database and sets them to be visible by default.
+     * Module classes known to the database, which are not in the given set, are ignored.
+     * 
+     * @param conn the connection to use
+     * @param moduleSet the module set to synchronize
+     * @return a list of elements from the given set, which should be visible in the menu
+     * @throws SQLException
+     */
+    public final List<Map.Entry<String, LightPITModule>>
+            syncRegisteredModuleClasses(Connection conn, Set<Map.Entry<String, LightPITModule>> moduleSet) throws SQLException {
+                
+        PreparedStatement
+                check = moduleCheckStatement(conn),
+                insert = moduleInsertStatement(conn);
+        insert.setBoolean(2, true);
+        // update/delete not required, we do this in the module management UI
+
+        final List<Map.Entry<String, LightPITModule>> visibleModules = new ArrayList<>();
+
+        for (Map.Entry<String, LightPITModule> mod : moduleSet) {
+            if (mod.getValue().systemModule()) continue;
+
+            check.setString(1, mod.getKey());
+            try (ResultSet r = check.executeQuery()) {
+                final boolean visible;
+                if (r.next()) {
+                    visible = r.getBoolean(1);
+                } else {
+                    insert.setString(1, mod.getKey());
+                    insert.executeUpdate();
+                    visible = !mod.getValue().menuKey().isEmpty();
+                }
+                if (visible) {
+                    visibleModules.add(new AbstractMap.SimpleEntry<>(
+                            mod.getKey(),
+                            mod.getValue()
+                    ));
+                }
+            }
+        }
+        return visibleModules;
+    }
+
+    /**
+     * Returns a list of all modules known by the database.
+     * 
+     * Keep in mind, that system modules are never known to the database.
+     * 
+     * @param conn the connection to use
+     * @return a list of all modules known by the database
+     * @throws SQLException 
+     */
+    public List<Module> listAll(Connection conn) throws SQLException {
+        List<Module> list = new ArrayList<>();
+        try (
+                Statement stmt = conn.createStatement();
+                ResultSet result = stmt.executeQuery("SELECT * FROM lpitcore_module")) {
+            while (result.next()) {
+                final Module mod = new Module();
+                mod.setModID(result.getInt("modid"));
+                mod.setClassname(result.getString("classname"));
+                mod.setVisible(result.getBoolean("visible"));
+                list.add(mod);
+            }
+        }
+        return list;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java/de/uapcore/lightpit/entities/PostgresModuleDao.java	Sun Apr 01 18:16:47 2018 +0200
@@ -0,0 +1,33 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ * 
+ * Copyright 2017 Mike Becker. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * 
+ */
+package de.uapcore.lightpit.entities;
+
+public class PostgresModuleDao extends ModuleDao {
+    // No overrides needed.
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java/de/uapcore/lightpit/modules/ModuleManagerModule.java	Sun Apr 01 18:16:47 2018 +0200
@@ -0,0 +1,94 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ * 
+ * Copyright 2017 Mike Becker. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * 
+ */
+package de.uapcore.lightpit.modules;
+
+import de.uapcore.lightpit.LightPITModule;
+import de.uapcore.lightpit.AbstractLightPITServlet;
+import de.uapcore.lightpit.HttpMethod;
+import de.uapcore.lightpit.LightPITModule.ELProxy;
+import de.uapcore.lightpit.RequestMapping;
+import de.uapcore.lightpit.ResponseType;
+import de.uapcore.lightpit.entities.CoreDAOFactory;
+import de.uapcore.lightpit.entities.Module;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.sql.DataSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Entry point for the application.
+ */
+@LightPITModule(
+        bundleBaseName = "de.uapcore.lightpit.resources.localization.modmgmt",
+        modulePath = "modmgmt"
+)
+@WebServlet(
+        name = "ModuleManagerModule",
+        urlPatterns = "/modmgmt/*"
+)
+public final class ModuleManagerModule extends AbstractLightPITServlet {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(ModuleManagerModule.class);
+    
+    private static final String REQ_ATTR_MODULES = "modules";
+    
+    
+    @RequestMapping(method = HttpMethod.GET)
+    public ResponseType handle(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+        
+        Optional<DataSource> ds = getDatabaseFacade().getDataSource();
+        if (ds.isPresent()) {
+            try (Connection conn = ds.get().getConnection()) {
+                final List<Module> modules = CoreDAOFactory.getModuleDao(getDatabaseFacade().getSQLDialect()).listAll(conn);
+                
+                final Map<String, LightPITModule> registeredModules = getModuleManager().getRegisteredModules();
+                modules.forEach((mod) -> mod.setAnnotatedInfos(ELProxy.convert(registeredModules.get(mod.getClassname()))));
+                
+                req.setAttribute(REQ_ATTR_MODULES, modules);
+                setDynamicFragment(req, "modules");                
+                return ResponseType.HTML_FULL;
+            } catch (SQLException ex) {
+                LOG.error("Unexpected SQL Exception", ex);
+                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                return ResponseType.NONE;
+            }
+        } else {
+            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            return ResponseType.NONE;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java/de/uapcore/lightpit/resources/localization/modmgmt.properties	Sun Apr 01 18:16:47 2018 +0200
@@ -0,0 +1,24 @@
+# Copyright 2017 Mike Becker. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+
+menuLabel = Modules
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java/de/uapcore/lightpit/resources/localization/modmgmt_de.properties	Sun Apr 01 18:16:47 2018 +0200
@@ -0,0 +1,24 @@
+# Copyright 2017 Mike Becker. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+
+menuLabel = Module
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/WEB-INF/dynamic_fragments/modules.jsp	Sun Apr 01 18:16:47 2018 +0200
@@ -0,0 +1,52 @@
+<%-- 
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 2017 Mike Becker. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+--%>
+<%@page pageEncoding="UTF-8" session="true" %>
+<%@page import="de.uapcore.lightpit.Constants" %>
+<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+
+<%-- TODO: a lot of work --%>
+<table>
+    <tr>
+        <th>Module</th>
+        <th>Path</th>
+        <th>Description</th>
+        <th>Active</th>
+        <th>Class</th>
+        <th>Resource Bundle</th>
+    </tr>
+    <c:forEach items="${modules}" var="module">
+        <tr>
+            <td>${module.annotatedInfos.nameKey}</td>
+            <td>${module.annotatedInfos.modulePath}</td>
+            <td>${module.annotatedInfos.descKey}</td>
+            <td align="center">${module.visible}</td>
+            <td>${module.classname}</td>
+            <td>${module.annotatedInfos.bundleBaseName}</td>
+        </tr>
+    </c:forEach>
+</table>
\ No newline at end of file

mercurial