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

changeset 21
b213fef2539e
parent 20
bd1a76c91d5b
child 22
5a91fb7067af
equal deleted inserted replaced
20:bd1a76c91d5b 21:b213fef2539e
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 * 27 *
28 */ 28 */
29 package de.uapcore.lightpit; 29 package de.uapcore.lightpit;
30 30
31 import de.uapcore.lightpit.entities.CoreDAOFactory;
32 import de.uapcore.lightpit.entities.ModuleDao;
31 import java.sql.Connection; 33 import java.sql.Connection;
32 import java.sql.PreparedStatement;
33 import java.sql.ResultSet;
34 import java.sql.SQLException; 34 import java.sql.SQLException;
35 import java.util.ArrayList; 35 import java.util.Collection;
36 import java.util.Collections; 36 import java.util.Collections;
37 import java.util.HashMap; 37 import java.util.HashMap;
38 import java.util.List; 38 import java.util.List;
39 import java.util.Map; 39 import java.util.Map;
40 import java.util.Map.Entry; 40 import java.util.Map.Entry;
41 import java.util.Optional; 41 import java.util.Optional;
42 import java.util.concurrent.CopyOnWriteArrayList; 42 import java.util.concurrent.CopyOnWriteArrayList;
43 import java.util.concurrent.atomic.AtomicBoolean; 43 import java.util.concurrent.atomic.AtomicBoolean;
44 import java.util.stream.Collectors;
44 import javax.servlet.Registration; 45 import javax.servlet.Registration;
45 import javax.servlet.ServletContext; 46 import javax.servlet.ServletContext;
46 import javax.servlet.ServletContextEvent; 47 import javax.servlet.ServletContextEvent;
47 import javax.servlet.ServletContextListener; 48 import javax.servlet.ServletContextListener;
48 import javax.servlet.annotation.WebListener; 49 import javax.servlet.annotation.WebListener;
64 private ServletContext sc; 65 private ServletContext sc;
65 66
66 /** 67 /**
67 * This flag is true, when synchronization is needed. 68 * This flag is true, when synchronization is needed.
68 */ 69 */
69 private AtomicBoolean dirty = new AtomicBoolean(true); 70 private final AtomicBoolean dirty = new AtomicBoolean(true);
70 71
71 private final CopyOnWriteArrayList<Menu> mainMenu = new CopyOnWriteArrayList<>(); 72 private final CopyOnWriteArrayList<Menu> mainMenu = new CopyOnWriteArrayList<>();
72 private final List<Menu> immutableMainMenu = Collections.unmodifiableList(mainMenu); 73 private final List<Menu> immutableMainMenu = Collections.unmodifiableList(mainMenu);
73 74
74 /** 75 /**
138 139
139 /** 140 /**
140 * Scans for modules and reloads them all. 141 * Scans for modules and reloads them all.
141 */ 142 */
142 public void reloadAll() { 143 public void reloadAll() {
144 registeredModules.clear();
143 sc.getServletRegistrations().forEach(this::handleServletRegistration); 145 sc.getServletRegistrations().forEach(this::handleServletRegistration);
144 146
145 // TODO: implement dependency resolver 147 // TODO: implement dependency resolver
146 148
149 dirty.set(true);
147 LOG.info("Modules loaded."); 150 LOG.info("Modules loaded.");
148 } 151 }
149 152
150 /** 153 /**
151 * Synchronizes module information with the database. 154 * Synchronizes module information with the database.
154 */ 157 */
155 public void syncWithDatabase(DatabaseFacade db) { 158 public void syncWithDatabase(DatabaseFacade db) {
156 if (dirty.compareAndSet(true, false)) { 159 if (dirty.compareAndSet(true, false)) {
157 if (db.getDataSource().isPresent()) { 160 if (db.getDataSource().isPresent()) {
158 try (Connection conn = db.getDataSource().get().getConnection()) { 161 try (Connection conn = db.getDataSource().get().getConnection()) {
159 PreparedStatement 162 final ModuleDao moduleDao = CoreDAOFactory.getModuleDao(db.getSQLDialect());
160 check = conn.prepareStatement("SELECT visible FROM lpitcore_module WHERE classname = ?"),
161 insert = conn.prepareStatement("INSERT INTO lpitcore_module (classname, visible) VALUES (?, ?)");
162 insert.setBoolean(2, true);
163 // update/delete not required, we do this in the module management UI
164 163
165 final List<Menu> updatedMenu = new ArrayList<>(); 164 final List<Entry<String, LightPITModule>> visibleModules =
165 moduleDao.syncRegisteredModuleClasses(conn, registeredModules.entrySet());
166 166
167 for (Entry<String, LightPITModule> mod : registeredModules.entrySet()) { 167 final List<Menu> updatedMenu = visibleModules
168 if (mod.getValue().systemModule()) continue; 168 .stream()
169 169 .collect(Collectors.mapping(
170 check.setString(1, mod.getKey()); 170 (mod) -> new Menu(
171 try (ResultSet r = check.executeQuery()) { 171 mod.getKey(),
172 final boolean addToMenu; 172 new ResourceKey(mod.getValue().bundleBaseName(), mod.getValue().menuKey()),
173 if (r.next()) { 173 mod.getValue().modulePath()),
174 addToMenu = r.getBoolean(1); 174 Collectors.toList())
175 } else { 175 );
176 insert.setString(1, mod.getKey());
177 insert.executeUpdate();
178 addToMenu = !mod.getValue().menuKey().isEmpty();
179 }
180 if (addToMenu) {
181 updatedMenu.add(new Menu(
182 mod.getKey(),
183 new ResourceKey(mod.getValue().bundleBaseName(), mod.getValue().menuKey()),
184 mod.getValue().modulePath()
185 ));
186 }
187 }
188 }
189 176
190 mainMenu.removeIf((e) -> !updatedMenu.contains(e)); 177 mainMenu.removeIf((e) -> !updatedMenu.contains(e));
191 mainMenu.addAllAbsent(updatedMenu); 178 mainMenu.addAllAbsent(updatedMenu);
192 } catch (SQLException ex) { 179 } catch (SQLException ex) {
193 LOG.error("Unexpected SQL Exception", ex); 180 LOG.error("Unexpected SQL Exception", ex);
203 /** 190 /**
204 * Unloads all found modules. 191 * Unloads all found modules.
205 */ 192 */
206 public void unloadAll() { 193 public void unloadAll() {
207 mainMenu.clear(); 194 mainMenu.clear();
195 registeredModules.clear();
208 LOG.info("All modules unloaded."); 196 LOG.info("All modules unloaded.");
209 } 197 }
210 198
211 /** 199 /**
212 * Returns the main menu. 200 * Returns the main menu.
213 * @return a list of menus belonging to the main menu 201 * @return a list of menus belonging to the main menu
214 */ 202 */
215 public List<Menu> getMainMenu() { 203 public List<Menu> getMainMenu() {
216 return immutableMainMenu; 204 return immutableMainMenu;
217 } 205 }
206
207 /**
208 * Returns an unmodifiable map of all registered modules.
209 *
210 * The key is the classname of the module.
211 *
212 * @return the map of registered modules
213 */
214 public Map<String, LightPITModule> getRegisteredModules() {
215 return Collections.unmodifiableMap(registeredModules);
216 }
218 } 217 }

mercurial