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
     1.1 --- a/src/java/de/uapcore/lightpit/AbstractLightPITServlet.java	Sat Mar 31 19:35:04 2018 +0200
     1.2 +++ b/src/java/de/uapcore/lightpit/AbstractLightPITServlet.java	Sun Apr 01 18:16:47 2018 +0200
     1.3 @@ -266,10 +266,13 @@
     1.4              LOG.trace("Continuing session {} with language {}", session.getId(), sessionLocale);
     1.5          }
     1.6          
     1.7 +        // set some internal request attributes
     1.8          req.setAttribute(Constants.REQ_ATTR_PATH, Functions.fullPath(req));
     1.9          req.setAttribute(Constants.REQ_ATTR_MODULE_CLASSNAME, this.getClass().getName());
    1.10          moduleInfoELProxy.ifPresent((proxy) -> req.setAttribute(Constants.REQ_ATTR_MODULE_INFO, proxy));
    1.11          
    1.12 +        
    1.13 +        // call the handler, if available, or send an HTTP 404 error
    1.14          Optional<HandlerMethod> mapping = findMapping(method, req);
    1.15          if (mapping.isPresent()) {
    1.16              forwardAsSepcified(mapping.get().apply(req, resp), req, resp);
     2.1 --- a/src/java/de/uapcore/lightpit/LightPITModule.java	Sat Mar 31 19:35:04 2018 +0200
     2.2 +++ b/src/java/de/uapcore/lightpit/LightPITModule.java	Sun Apr 01 18:16:47 2018 +0200
     2.3 @@ -60,7 +60,7 @@
     2.4      String[] requires() default {};
     2.5      
     2.6      /**
     2.7 -     * The path for this module, which will be used for the menu entry.
     2.8 +     * The path for this module, which will also be used for the menu entry.
     2.9       * 
    2.10       * This path must adhere to the URL pattern of the Servlet but must not
    2.11       * contain any starting or trailing slashes.
    2.12 @@ -70,6 +70,21 @@
    2.13      String modulePath();
    2.14      
    2.15      /**
    2.16 +     * Returns the properties key for the module name.
    2.17 +     * 
    2.18 +     * @return the properties key
    2.19 +     */
    2.20 +    String nameKey() default "name";
    2.21 +    
    2.22 +    /**
    2.23 +     * Returns the properties key for the module description.
    2.24 +     * 
    2.25 +     * @return the properties key
    2.26 +     */
    2.27 +    String descKey() default "description";
    2.28 +    
    2.29 +    
    2.30 +    /**
    2.31       * Returns the properties key for the menu label.
    2.32       * 
    2.33       * Set this string to empty string, if the module should be hidden from
    2.34 @@ -105,22 +120,26 @@
    2.35       * are proxied by this object.
    2.36       */
    2.37      public static class ELProxy {
    2.38 -        private final String bundleBaseName, modulePath, menuKey, titleKey;
    2.39 +        private final String bundleBaseName, modulePath, menuKey, titleKey, nameKey, descKey;
    2.40          
    2.41          public static ELProxy convert(LightPITModule annotation) {
    2.42              return new ELProxy(
    2.43                      annotation.bundleBaseName(),
    2.44                      annotation.modulePath(),
    2.45                      annotation.menuKey(),
    2.46 -                    annotation.titleKey()
    2.47 +                    annotation.titleKey(),
    2.48 +                    annotation.nameKey(),
    2.49 +                    annotation.descKey()
    2.50              );
    2.51          }
    2.52  
    2.53 -        private ELProxy(String bundleBaseName, String modulePath, String menuKey, String titleKey) {
    2.54 +        private ELProxy(String bundleBaseName, String modulePath, String menuKey, String titleKey, String nameKey, String descKey) {
    2.55              this.bundleBaseName = bundleBaseName;
    2.56              this.modulePath = modulePath;
    2.57              this.menuKey = menuKey;
    2.58              this.titleKey = titleKey;
    2.59 +            this.nameKey = nameKey;
    2.60 +            this.descKey = descKey;
    2.61          }
    2.62  
    2.63          public String getBundleBaseName() {
    2.64 @@ -138,5 +157,14 @@
    2.65          public String getTitleKey() {
    2.66              return titleKey;
    2.67          }
    2.68 +
    2.69 +        public String getNameKey() {
    2.70 +            return nameKey;
    2.71 +        }
    2.72 +
    2.73 +        public String getDescKey() {
    2.74 +            return descKey;
    2.75 +        }
    2.76 +        
    2.77      }
    2.78  }
     3.1 --- a/src/java/de/uapcore/lightpit/ModuleManager.java	Sat Mar 31 19:35:04 2018 +0200
     3.2 +++ b/src/java/de/uapcore/lightpit/ModuleManager.java	Sun Apr 01 18:16:47 2018 +0200
     3.3 @@ -28,11 +28,11 @@
     3.4   */
     3.5  package de.uapcore.lightpit;
     3.6  
     3.7 +import de.uapcore.lightpit.entities.CoreDAOFactory;
     3.8 +import de.uapcore.lightpit.entities.ModuleDao;
     3.9  import java.sql.Connection;
    3.10 -import java.sql.PreparedStatement;
    3.11 -import java.sql.ResultSet;
    3.12  import java.sql.SQLException;
    3.13 -import java.util.ArrayList;
    3.14 +import java.util.Collection;
    3.15  import java.util.Collections;
    3.16  import java.util.HashMap;
    3.17  import java.util.List;
    3.18 @@ -41,6 +41,7 @@
    3.19  import java.util.Optional;
    3.20  import java.util.concurrent.CopyOnWriteArrayList;
    3.21  import java.util.concurrent.atomic.AtomicBoolean;
    3.22 +import java.util.stream.Collectors;
    3.23  import javax.servlet.Registration;
    3.24  import javax.servlet.ServletContext;
    3.25  import javax.servlet.ServletContextEvent;
    3.26 @@ -66,7 +67,7 @@
    3.27      /**
    3.28       * This flag is true, when synchronization is needed.
    3.29       */
    3.30 -    private AtomicBoolean dirty = new AtomicBoolean(true);
    3.31 +    private final AtomicBoolean dirty = new AtomicBoolean(true);
    3.32      
    3.33      private final CopyOnWriteArrayList<Menu> mainMenu = new CopyOnWriteArrayList<>();
    3.34      private final List<Menu> immutableMainMenu = Collections.unmodifiableList(mainMenu);
    3.35 @@ -140,10 +141,12 @@
    3.36       * Scans for modules and reloads them all.
    3.37       */
    3.38      public void reloadAll() {
    3.39 +        registeredModules.clear();
    3.40          sc.getServletRegistrations().forEach(this::handleServletRegistration);
    3.41          
    3.42          // TODO: implement dependency resolver
    3.43          
    3.44 +        dirty.set(true);
    3.45          LOG.info("Modules loaded.");
    3.46      }
    3.47      
    3.48 @@ -156,36 +159,20 @@
    3.49          if (dirty.compareAndSet(true, false)) {
    3.50              if (db.getDataSource().isPresent()) {
    3.51                  try (Connection conn = db.getDataSource().get().getConnection()) {
    3.52 -                    PreparedStatement
    3.53 -                            check = conn.prepareStatement("SELECT visible FROM lpitcore_module WHERE classname = ?"),
    3.54 -                            insert = conn.prepareStatement("INSERT INTO lpitcore_module (classname, visible) VALUES (?, ?)");
    3.55 -                    insert.setBoolean(2, true);
    3.56 -                    // update/delete not required, we do this in the module management UI
    3.57 +                    final ModuleDao moduleDao = CoreDAOFactory.getModuleDao(db.getSQLDialect());
    3.58                      
    3.59 -                    final List<Menu> updatedMenu = new ArrayList<>();
    3.60 +                    final List<Entry<String, LightPITModule>> visibleModules =
    3.61 +                            moduleDao.syncRegisteredModuleClasses(conn, registeredModules.entrySet());
    3.62                      
    3.63 -                    for (Entry<String, LightPITModule> mod : registeredModules.entrySet()) {
    3.64 -                        if (mod.getValue().systemModule()) continue;
    3.65 -                        
    3.66 -                        check.setString(1, mod.getKey());
    3.67 -                        try (ResultSet r = check.executeQuery()) {
    3.68 -                            final boolean addToMenu;
    3.69 -                            if (r.next()) {
    3.70 -                                addToMenu = r.getBoolean(1);
    3.71 -                            } else {
    3.72 -                                insert.setString(1, mod.getKey());
    3.73 -                                insert.executeUpdate();
    3.74 -                                addToMenu = !mod.getValue().menuKey().isEmpty();
    3.75 -                            }
    3.76 -                            if (addToMenu) {
    3.77 -                                updatedMenu.add(new Menu(
    3.78 -                                        mod.getKey(),
    3.79 -                                        new ResourceKey(mod.getValue().bundleBaseName(), mod.getValue().menuKey()),
    3.80 -                                        mod.getValue().modulePath()
    3.81 -                                ));
    3.82 -                            }
    3.83 -                        }
    3.84 -                    }
    3.85 +                    final List<Menu> updatedMenu = visibleModules
    3.86 +                            .stream()
    3.87 +                            .collect(Collectors.mapping(
    3.88 +                                    (mod) -> new Menu(
    3.89 +                                            mod.getKey(),
    3.90 +                                            new ResourceKey(mod.getValue().bundleBaseName(), mod.getValue().menuKey()),
    3.91 +                                            mod.getValue().modulePath()),
    3.92 +                                    Collectors.toList())
    3.93 +                            );
    3.94                      
    3.95                      mainMenu.removeIf((e) -> !updatedMenu.contains(e));
    3.96                      mainMenu.addAllAbsent(updatedMenu);
    3.97 @@ -205,6 +192,7 @@
    3.98       */
    3.99      public void unloadAll() {
   3.100          mainMenu.clear();
   3.101 +        registeredModules.clear();
   3.102          LOG.info("All modules unloaded.");
   3.103      }
   3.104  
   3.105 @@ -215,4 +203,15 @@
   3.106      public List<Menu> getMainMenu() {
   3.107          return immutableMainMenu;
   3.108      }
   3.109 +    
   3.110 +    /**
   3.111 +     * Returns an unmodifiable map of all registered modules.
   3.112 +     * 
   3.113 +     * The key is the classname of the module.
   3.114 +     * 
   3.115 +     * @return the map of registered modules
   3.116 +     */
   3.117 +    public Map<String, LightPITModule> getRegisteredModules() {
   3.118 +        return Collections.unmodifiableMap(registeredModules);
   3.119 +    }
   3.120  }
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/java/de/uapcore/lightpit/entities/CoreDAOFactory.java	Sun Apr 01 18:16:47 2018 +0200
     4.3 @@ -0,0 +1,47 @@
     4.4 +/*
     4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     4.6 + * 
     4.7 + * Copyright 2017 Mike Becker. All rights reserved.
     4.8 + * 
     4.9 + * Redistribution and use in source and binary forms, with or without
    4.10 + * modification, are permitted provided that the following conditions are met:
    4.11 + *
    4.12 + *   1. Redistributions of source code must retain the above copyright
    4.13 + *      notice, this list of conditions and the following disclaimer.
    4.14 + *
    4.15 + *   2. Redistributions in binary form must reproduce the above copyright
    4.16 + *      notice, this list of conditions and the following disclaimer in the
    4.17 + *      documentation and/or other materials provided with the distribution.
    4.18 + *
    4.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    4.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    4.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    4.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    4.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    4.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    4.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    4.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    4.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    4.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    4.29 + * POSSIBILITY OF SUCH DAMAGE.
    4.30 + * 
    4.31 + */
    4.32 +package de.uapcore.lightpit.entities;
    4.33 +
    4.34 +import de.uapcore.lightpit.DatabaseFacade;
    4.35 +
    4.36 +public final class CoreDAOFactory {
    4.37 +    
    4.38 +    private CoreDAOFactory() {}
    4.39 +    
    4.40 +    private static class PostgresDaos {
    4.41 +        static final ModuleDao MODULE_DAO = new PostgresModuleDao();
    4.42 +    }
    4.43 +    
    4.44 +    public static ModuleDao getModuleDao(DatabaseFacade.Dialect dialect) {
    4.45 +        switch (dialect) {
    4.46 +            case Postgres: return PostgresDaos.MODULE_DAO;
    4.47 +            default: assert(false); return null;
    4.48 +        }
    4.49 +    }
    4.50 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/java/de/uapcore/lightpit/entities/Module.java	Sun Apr 01 18:16:47 2018 +0200
     5.3 @@ -0,0 +1,90 @@
     5.4 +/*
     5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     5.6 + * 
     5.7 + * Copyright 2017 Mike Becker. All rights reserved.
     5.8 + * 
     5.9 + * Redistribution and use in source and binary forms, with or without
    5.10 + * modification, are permitted provided that the following conditions are met:
    5.11 + *
    5.12 + *   1. Redistributions of source code must retain the above copyright
    5.13 + *      notice, this list of conditions and the following disclaimer.
    5.14 + *
    5.15 + *   2. Redistributions in binary form must reproduce the above copyright
    5.16 + *      notice, this list of conditions and the following disclaimer in the
    5.17 + *      documentation and/or other materials provided with the distribution.
    5.18 + *
    5.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    5.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    5.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    5.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    5.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    5.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    5.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    5.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    5.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    5.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    5.29 + * POSSIBILITY OF SUCH DAMAGE.
    5.30 + * 
    5.31 + */
    5.32 +package de.uapcore.lightpit.entities;
    5.33 +
    5.34 +import de.uapcore.lightpit.LightPITModule;
    5.35 +
    5.36 +public class Module {
    5.37 +    private int modID;
    5.38 +    private String classname;
    5.39 +    private boolean visible;
    5.40 +    
    5.41 +    private LightPITModule.ELProxy annotatedInfos;
    5.42 +
    5.43 +    public int getModID() {
    5.44 +        return modID;
    5.45 +    }
    5.46 +
    5.47 +    public void setModID(int modID) {
    5.48 +        this.modID = modID;
    5.49 +    }
    5.50 +
    5.51 +    public String getClassname() {
    5.52 +        return classname;
    5.53 +    }
    5.54 +
    5.55 +    public void setClassname(String classname) {
    5.56 +        this.classname = classname;
    5.57 +    }
    5.58 +
    5.59 +    public boolean isVisible() {
    5.60 +        return visible;
    5.61 +    }
    5.62 +
    5.63 +    public void setVisible(boolean visible) {
    5.64 +        this.visible = visible;
    5.65 +    }
    5.66 +
    5.67 +    public LightPITModule.ELProxy getAnnotatedInfos() {
    5.68 +        return annotatedInfos;
    5.69 +    }
    5.70 +
    5.71 +    public void setAnnotatedInfos(LightPITModule.ELProxy annotatedInfos) {
    5.72 +        this.annotatedInfos = annotatedInfos;
    5.73 +    }
    5.74 +
    5.75 +    @Override
    5.76 +    public int hashCode() {
    5.77 +        int hash = 3;
    5.78 +        hash = 41 * hash + this.modID;
    5.79 +        return hash;
    5.80 +    }
    5.81 +
    5.82 +    @Override
    5.83 +    public boolean equals(Object obj) {
    5.84 +        if (this == obj) {
    5.85 +            return true;
    5.86 +        }
    5.87 +        if (obj == null || getClass() != obj.getClass()) {
    5.88 +            return false;
    5.89 +        } else {
    5.90 +            return this.modID == ((Module) obj).modID;
    5.91 +        }
    5.92 +    }    
    5.93 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/java/de/uapcore/lightpit/entities/ModuleDao.java	Sun Apr 01 18:16:47 2018 +0200
     6.3 @@ -0,0 +1,147 @@
     6.4 +/*
     6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     6.6 + * 
     6.7 + * Copyright 2017 Mike Becker. All rights reserved.
     6.8 + * 
     6.9 + * Redistribution and use in source and binary forms, with or without
    6.10 + * modification, are permitted provided that the following conditions are met:
    6.11 + *
    6.12 + *   1. Redistributions of source code must retain the above copyright
    6.13 + *      notice, this list of conditions and the following disclaimer.
    6.14 + *
    6.15 + *   2. Redistributions in binary form must reproduce the above copyright
    6.16 + *      notice, this list of conditions and the following disclaimer in the
    6.17 + *      documentation and/or other materials provided with the distribution.
    6.18 + *
    6.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    6.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    6.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    6.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    6.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    6.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    6.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    6.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    6.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    6.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    6.29 + * POSSIBILITY OF SUCH DAMAGE.
    6.30 + * 
    6.31 + */
    6.32 +package de.uapcore.lightpit.entities;
    6.33 +
    6.34 +import de.uapcore.lightpit.LightPITModule;
    6.35 +import java.sql.Connection;
    6.36 +import java.sql.PreparedStatement;
    6.37 +import java.sql.ResultSet;
    6.38 +import java.sql.SQLException;
    6.39 +import java.sql.Statement;
    6.40 +import java.util.AbstractMap;
    6.41 +import java.util.ArrayList;
    6.42 +import java.util.List;
    6.43 +import java.util.Map;
    6.44 +import java.util.Set;
    6.45 +
    6.46 +public abstract class ModuleDao {
    6.47 +    
    6.48 +    /**
    6.49 +     * Must return a prepared statement for a single object query with the specified properties.
    6.50 +     * 
    6.51 +     * <ul>
    6.52 +     * <li>Parameter 1: classname</li>
    6.53 +     * <li>Result field 1: visible</li>
    6.54 +     * </ul>
    6.55 +     * 
    6.56 +     * @param conn the connection to use
    6.57 +     * @return the prepared statement
    6.58 +     * @throws SQLException 
    6.59 +     */
    6.60 +    protected PreparedStatement moduleCheckStatement(Connection conn) throws SQLException {
    6.61 +        return conn.prepareStatement("SELECT visible FROM lpitcore_module WHERE classname = ?");
    6.62 +    }
    6.63 +    
    6.64 +    /**
    6.65 +     * Must return a prepared statement for insertion with the specified properties.
    6.66 +     * 
    6.67 +     * <ul>
    6.68 +     * <li>Parameter 1: classname</li>
    6.69 +     * <li>Parameter 2: visible</li>
    6.70 +     * </ul>
    6.71 +     * 
    6.72 +     * @param conn the connection to use
    6.73 +     * @return the prepared statement
    6.74 +     * @throws SQLException 
    6.75 +     */
    6.76 +    protected PreparedStatement moduleInsertStatement(Connection conn) throws SQLException {
    6.77 +        return conn.prepareStatement("INSERT INTO lpitcore_module (classname, visible) VALUES (?, ?)");
    6.78 +    }
    6.79 +    
    6.80 +    /**
    6.81 +     * Synchronizes a set of registered module classes with the database and gives a list of visible modules in return.
    6.82 +     * 
    6.83 +     * Inserts module classes which are not known to the database and sets them to be visible by default.
    6.84 +     * Module classes known to the database, which are not in the given set, are ignored.
    6.85 +     * 
    6.86 +     * @param conn the connection to use
    6.87 +     * @param moduleSet the module set to synchronize
    6.88 +     * @return a list of elements from the given set, which should be visible in the menu
    6.89 +     * @throws SQLException
    6.90 +     */
    6.91 +    public final List<Map.Entry<String, LightPITModule>>
    6.92 +            syncRegisteredModuleClasses(Connection conn, Set<Map.Entry<String, LightPITModule>> moduleSet) throws SQLException {
    6.93 +                
    6.94 +        PreparedStatement
    6.95 +                check = moduleCheckStatement(conn),
    6.96 +                insert = moduleInsertStatement(conn);
    6.97 +        insert.setBoolean(2, true);
    6.98 +        // update/delete not required, we do this in the module management UI
    6.99 +
   6.100 +        final List<Map.Entry<String, LightPITModule>> visibleModules = new ArrayList<>();
   6.101 +
   6.102 +        for (Map.Entry<String, LightPITModule> mod : moduleSet) {
   6.103 +            if (mod.getValue().systemModule()) continue;
   6.104 +
   6.105 +            check.setString(1, mod.getKey());
   6.106 +            try (ResultSet r = check.executeQuery()) {
   6.107 +                final boolean visible;
   6.108 +                if (r.next()) {
   6.109 +                    visible = r.getBoolean(1);
   6.110 +                } else {
   6.111 +                    insert.setString(1, mod.getKey());
   6.112 +                    insert.executeUpdate();
   6.113 +                    visible = !mod.getValue().menuKey().isEmpty();
   6.114 +                }
   6.115 +                if (visible) {
   6.116 +                    visibleModules.add(new AbstractMap.SimpleEntry<>(
   6.117 +                            mod.getKey(),
   6.118 +                            mod.getValue()
   6.119 +                    ));
   6.120 +                }
   6.121 +            }
   6.122 +        }
   6.123 +        return visibleModules;
   6.124 +    }
   6.125 +
   6.126 +    /**
   6.127 +     * Returns a list of all modules known by the database.
   6.128 +     * 
   6.129 +     * Keep in mind, that system modules are never known to the database.
   6.130 +     * 
   6.131 +     * @param conn the connection to use
   6.132 +     * @return a list of all modules known by the database
   6.133 +     * @throws SQLException 
   6.134 +     */
   6.135 +    public List<Module> listAll(Connection conn) throws SQLException {
   6.136 +        List<Module> list = new ArrayList<>();
   6.137 +        try (
   6.138 +                Statement stmt = conn.createStatement();
   6.139 +                ResultSet result = stmt.executeQuery("SELECT * FROM lpitcore_module")) {
   6.140 +            while (result.next()) {
   6.141 +                final Module mod = new Module();
   6.142 +                mod.setModID(result.getInt("modid"));
   6.143 +                mod.setClassname(result.getString("classname"));
   6.144 +                mod.setVisible(result.getBoolean("visible"));
   6.145 +                list.add(mod);
   6.146 +            }
   6.147 +        }
   6.148 +        return list;
   6.149 +    }
   6.150 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/java/de/uapcore/lightpit/entities/PostgresModuleDao.java	Sun Apr 01 18:16:47 2018 +0200
     7.3 @@ -0,0 +1,33 @@
     7.4 +/*
     7.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     7.6 + * 
     7.7 + * Copyright 2017 Mike Becker. All rights reserved.
     7.8 + * 
     7.9 + * Redistribution and use in source and binary forms, with or without
    7.10 + * modification, are permitted provided that the following conditions are met:
    7.11 + *
    7.12 + *   1. Redistributions of source code must retain the above copyright
    7.13 + *      notice, this list of conditions and the following disclaimer.
    7.14 + *
    7.15 + *   2. Redistributions in binary form must reproduce the above copyright
    7.16 + *      notice, this list of conditions and the following disclaimer in the
    7.17 + *      documentation and/or other materials provided with the distribution.
    7.18 + *
    7.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    7.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    7.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    7.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    7.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    7.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    7.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    7.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    7.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    7.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    7.29 + * POSSIBILITY OF SUCH DAMAGE.
    7.30 + * 
    7.31 + */
    7.32 +package de.uapcore.lightpit.entities;
    7.33 +
    7.34 +public class PostgresModuleDao extends ModuleDao {
    7.35 +    // No overrides needed.
    7.36 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/java/de/uapcore/lightpit/modules/ModuleManagerModule.java	Sun Apr 01 18:16:47 2018 +0200
     8.3 @@ -0,0 +1,94 @@
     8.4 +/*
     8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     8.6 + * 
     8.7 + * Copyright 2017 Mike Becker. All rights reserved.
     8.8 + * 
     8.9 + * Redistribution and use in source and binary forms, with or without
    8.10 + * modification, are permitted provided that the following conditions are met:
    8.11 + *
    8.12 + *   1. Redistributions of source code must retain the above copyright
    8.13 + *      notice, this list of conditions and the following disclaimer.
    8.14 + *
    8.15 + *   2. Redistributions in binary form must reproduce the above copyright
    8.16 + *      notice, this list of conditions and the following disclaimer in the
    8.17 + *      documentation and/or other materials provided with the distribution.
    8.18 + *
    8.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    8.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    8.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    8.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    8.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    8.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    8.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    8.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    8.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    8.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    8.29 + * POSSIBILITY OF SUCH DAMAGE.
    8.30 + * 
    8.31 + */
    8.32 +package de.uapcore.lightpit.modules;
    8.33 +
    8.34 +import de.uapcore.lightpit.LightPITModule;
    8.35 +import de.uapcore.lightpit.AbstractLightPITServlet;
    8.36 +import de.uapcore.lightpit.HttpMethod;
    8.37 +import de.uapcore.lightpit.LightPITModule.ELProxy;
    8.38 +import de.uapcore.lightpit.RequestMapping;
    8.39 +import de.uapcore.lightpit.ResponseType;
    8.40 +import de.uapcore.lightpit.entities.CoreDAOFactory;
    8.41 +import de.uapcore.lightpit.entities.Module;
    8.42 +import java.io.IOException;
    8.43 +import java.sql.Connection;
    8.44 +import java.sql.SQLException;
    8.45 +import java.util.List;
    8.46 +import java.util.Map;
    8.47 +import java.util.Optional;
    8.48 +import javax.servlet.annotation.WebServlet;
    8.49 +import javax.servlet.http.HttpServletRequest;
    8.50 +import javax.servlet.http.HttpServletResponse;
    8.51 +import javax.sql.DataSource;
    8.52 +import org.slf4j.Logger;
    8.53 +import org.slf4j.LoggerFactory;
    8.54 +
    8.55 +/**
    8.56 + * Entry point for the application.
    8.57 + */
    8.58 +@LightPITModule(
    8.59 +        bundleBaseName = "de.uapcore.lightpit.resources.localization.modmgmt",
    8.60 +        modulePath = "modmgmt"
    8.61 +)
    8.62 +@WebServlet(
    8.63 +        name = "ModuleManagerModule",
    8.64 +        urlPatterns = "/modmgmt/*"
    8.65 +)
    8.66 +public final class ModuleManagerModule extends AbstractLightPITServlet {
    8.67 +    
    8.68 +    private static final Logger LOG = LoggerFactory.getLogger(ModuleManagerModule.class);
    8.69 +    
    8.70 +    private static final String REQ_ATTR_MODULES = "modules";
    8.71 +    
    8.72 +    
    8.73 +    @RequestMapping(method = HttpMethod.GET)
    8.74 +    public ResponseType handle(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    8.75 +        
    8.76 +        Optional<DataSource> ds = getDatabaseFacade().getDataSource();
    8.77 +        if (ds.isPresent()) {
    8.78 +            try (Connection conn = ds.get().getConnection()) {
    8.79 +                final List<Module> modules = CoreDAOFactory.getModuleDao(getDatabaseFacade().getSQLDialect()).listAll(conn);
    8.80 +                
    8.81 +                final Map<String, LightPITModule> registeredModules = getModuleManager().getRegisteredModules();
    8.82 +                modules.forEach((mod) -> mod.setAnnotatedInfos(ELProxy.convert(registeredModules.get(mod.getClassname()))));
    8.83 +                
    8.84 +                req.setAttribute(REQ_ATTR_MODULES, modules);
    8.85 +                setDynamicFragment(req, "modules");                
    8.86 +                return ResponseType.HTML_FULL;
    8.87 +            } catch (SQLException ex) {
    8.88 +                LOG.error("Unexpected SQL Exception", ex);
    8.89 +                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    8.90 +                return ResponseType.NONE;
    8.91 +            }
    8.92 +        } else {
    8.93 +            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    8.94 +            return ResponseType.NONE;
    8.95 +        }
    8.96 +    }
    8.97 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/java/de/uapcore/lightpit/resources/localization/modmgmt.properties	Sun Apr 01 18:16:47 2018 +0200
     9.3 @@ -0,0 +1,24 @@
     9.4 +# Copyright 2017 Mike Becker. All rights reserved.
     9.5 +#
     9.6 +# Redistribution and use in source and binary forms, with or without
     9.7 +# modification, are permitted provided that the following conditions are met:
     9.8 +#
     9.9 +# 1. Redistributions of source code must retain the above copyright
    9.10 +# notice, this list of conditions and the following disclaimer.
    9.11 +#
    9.12 +# 2. Redistributions in binary form must reproduce the above copyright
    9.13 +# notice, this list of conditions and the following disclaimer in the
    9.14 +# documentation and/or other materials provided with the distribution.
    9.15 +#
    9.16 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    9.17 +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    9.18 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    9.19 +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    9.20 +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    9.21 +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    9.22 +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    9.23 +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    9.24 +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    9.25 +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
    9.26 +
    9.27 +menuLabel = Modules
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/java/de/uapcore/lightpit/resources/localization/modmgmt_de.properties	Sun Apr 01 18:16:47 2018 +0200
    10.3 @@ -0,0 +1,24 @@
    10.4 +# Copyright 2017 Mike Becker. All rights reserved.
    10.5 +#
    10.6 +# Redistribution and use in source and binary forms, with or without
    10.7 +# modification, are permitted provided that the following conditions are met:
    10.8 +#
    10.9 +# 1. Redistributions of source code must retain the above copyright
   10.10 +# notice, this list of conditions and the following disclaimer.
   10.11 +#
   10.12 +# 2. Redistributions in binary form must reproduce the above copyright
   10.13 +# notice, this list of conditions and the following disclaimer in the
   10.14 +# documentation and/or other materials provided with the distribution.
   10.15 +#
   10.16 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   10.17 +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   10.18 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   10.19 +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
   10.20 +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   10.21 +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   10.22 +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   10.23 +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   10.24 +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   10.25 +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
   10.26 +
   10.27 +menuLabel = Module
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/web/WEB-INF/dynamic_fragments/modules.jsp	Sun Apr 01 18:16:47 2018 +0200
    11.3 @@ -0,0 +1,52 @@
    11.4 +<%-- 
    11.5 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    11.6 +
    11.7 +Copyright 2017 Mike Becker. All rights reserved.
    11.8 +
    11.9 +Redistribution and use in source and binary forms, with or without
   11.10 +modification, are permitted provided that the following conditions are met:
   11.11 +
   11.12 +1. Redistributions of source code must retain the above copyright
   11.13 +notice, this list of conditions and the following disclaimer.
   11.14 +
   11.15 +2. Redistributions in binary form must reproduce the above copyright
   11.16 +notice, this list of conditions and the following disclaimer in the
   11.17 +documentation and/or other materials provided with the distribution.
   11.18 +
   11.19 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   11.20 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   11.21 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   11.22 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
   11.23 +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   11.24 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   11.25 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   11.26 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   11.27 +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   11.28 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
   11.29 +--%>
   11.30 +<%@page pageEncoding="UTF-8" session="true" %>
   11.31 +<%@page import="de.uapcore.lightpit.Constants" %>
   11.32 +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
   11.33 +<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
   11.34 +
   11.35 +<%-- TODO: a lot of work --%>
   11.36 +<table>
   11.37 +    <tr>
   11.38 +        <th>Module</th>
   11.39 +        <th>Path</th>
   11.40 +        <th>Description</th>
   11.41 +        <th>Active</th>
   11.42 +        <th>Class</th>
   11.43 +        <th>Resource Bundle</th>
   11.44 +    </tr>
   11.45 +    <c:forEach items="${modules}" var="module">
   11.46 +        <tr>
   11.47 +            <td>${module.annotatedInfos.nameKey}</td>
   11.48 +            <td>${module.annotatedInfos.modulePath}</td>
   11.49 +            <td>${module.annotatedInfos.descKey}</td>
   11.50 +            <td align="center">${module.visible}</td>
   11.51 +            <td>${module.classname}</td>
   11.52 +            <td>${module.annotatedInfos.bundleBaseName}</td>
   11.53 +        </tr>
   11.54 +    </c:forEach>
   11.55 +</table>
   11.56 \ No newline at end of file

mercurial