diff --git a/Hal.iml b/Hal.iml index d611eaaf..2a2619c3 100755 --- a/Hal.iml +++ b/Hal.iml @@ -26,23 +26,7 @@ - - - - - - - - - - - - - - - - - + @@ -73,5 +57,21 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.xml b/build.xml index 4d2982d3..e059d4e4 100755 --- a/build.xml +++ b/build.xml @@ -15,7 +15,7 @@ - + diff --git a/hal-default.db b/hal-default.db index cbdd384b..4aee4afc 100755 Binary files a/hal-default.db and b/hal-default.db differ diff --git a/resource/web/plugin_config.tmpl b/resource/web/plugin_config.tmpl index a0d11cf1..c8179ac8 100644 --- a/resource/web/plugin_config.tmpl +++ b/resource/web/plugin_config.tmpl @@ -7,16 +7,37 @@ - + + {{#plugins}} + {{/plugins}}
NameName VersionActions
{{.getName()}} {{.getVersion()}} +
+ + + +
+ +
+
+
- \ No newline at end of file + + + \ No newline at end of file diff --git a/src/se/hal/HalContext.java b/src/se/hal/HalContext.java index 717d70e0..0e65ef11 100755 --- a/src/se/hal/HalContext.java +++ b/src/se/hal/HalContext.java @@ -76,8 +76,9 @@ public class HalContext { Integer.parseInt(dbConf.getProperty(PROPERTY_DB_VERSION)) : -1); logger.info("DB version: "+ dbVersion); + if(defaultDBVersion > dbVersion ) { - logger.info("Starting DB upgrade..."); + logger.info("Starting DB upgrade from v" + dbVersion + " to v" + defaultDBVersion + "..."); if(dbFile != null){ File backupDB = FileUtil.getNextFile(dbFile); logger.fine("Backing up DB to: "+ backupDB); @@ -91,6 +92,7 @@ public class HalContext { handler.setTargetDB(db); logger.fine("Performing pre-upgrade activities"); + //read upgrade path preferences from the reference database referenceDB.exec("SELECT * FROM db_version_history" + " WHERE db_version <= " + defaultDBVersion @@ -111,6 +113,7 @@ public class HalContext { handler.upgrade(); logger.fine("Performing post-upgrade activities"); + //read upgrade path preferences from the reference database referenceDB.exec("SELECT * FROM db_version_history" + " WHERE db_version <= " + defaultDBVersion @@ -225,7 +228,6 @@ public class HalContext { /** * For testing purposes. - * @param db */ public static void setDB(DBConnection db){ HalContext.db = db; diff --git a/src/se/hal/HalServer.java b/src/se/hal/HalServer.java index f35065aa..9e2b58e9 100755 --- a/src/se/hal/HalServer.java +++ b/src/se/hal/HalServer.java @@ -6,6 +6,7 @@ import se.hal.intf.HalWebPage; import se.hal.intf.HalJsonPage; import se.hal.page.*; import se.hal.struct.Event; +import se.hal.struct.PluginConfig; import se.hal.struct.Sensor; import se.hal.struct.TriggerFlow; import zutil.db.DBConnection; @@ -14,16 +15,20 @@ import zutil.log.LogUtil; import zutil.net.http.HttpServer; import zutil.net.http.page.HttpFilePage; import zutil.net.http.page.HttpRedirectPage; +import zutil.plugin.PluginData; import zutil.plugin.PluginManager; +import java.sql.SQLException; import java.util.*; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.logging.Logger; /** * Main class for Hal */ public class HalServer { + private static final Logger logger = LogUtil.getLogger(); private static ScheduledExecutorService daemonExecutor; private static List daemons = new ArrayList<>(); @@ -42,15 +47,40 @@ public class HalServer { // init DB and other configurations HalContext.initialize(); DBConnection db = HalContext.getDB(); - pluginManager = new PluginManager("./"); - // init Managers + // ------------------------------------ + // Init Plugins + // ------------------------------------ + + logger.info("Looking for plugins."); + pluginManager = new PluginManager(); + + // Disable plugins based on settings + for (PluginData plugin : getPlugins()) { + PluginConfig pluginConfig = PluginConfig.getPluginConfig(db, plugin.getName()); + + if (pluginConfig != null && !pluginConfig.isEnabled()){ + logger.info("Disabling plugin '" + plugin.getName() + "'."); + plugin.setEnabled(false); + } + } + + // ------------------------------------ + // Init Managers + // ------------------------------------ + + logger.info("Initializing managers."); + HalAlertManager.initialize(); ControllerManager.initialize(pluginManager); TriggerManager.initialize(pluginManager); - + // ------------------------------------ // Import sensors,events and triggers + // ------------------------------------ + + logger.info("Initializing Sensors and Events."); + for(Sensor sensor : Sensor.getLocalSensors(db)){ ControllerManager.getInstance().register(sensor); } @@ -63,14 +93,23 @@ public class HalServer { } + // ------------------------------------ // Init daemons + // ------------------------------------ + + logger.info("Initializing daemons."); + // We set only one thread for easier troubleshooting daemonExecutor = Executors.newScheduledThreadPool(1); - for (Iterator it=pluginManager.getObjectIterator(HalDaemon.class); it.hasNext(); ) + for (Iterator it = pluginManager.getSingletonIterator(HalDaemon.class); it.hasNext(); ) registerDaemon(it.next()); - + // ------------------------------------ // Init http server + // ------------------------------------ + + logger.info("Initializing HTTP Server."); + HalWebPage.getRootNav().createSubNav("Sensors"); HalWebPage.getRootNav().createSubNav("Events").setWeight(100); HalWebPage.getRootNav().createSubNav("Settings").setWeight(200); @@ -79,22 +118,38 @@ public class HalServer { http.setDefaultPage(new HttpFilePage(FileUtil.find("resource/web/"))); http.setPage("/", new HttpRedirectPage("/map")); http.setPage(HalAlertManager.getInstance().getUrl(), HalAlertManager.getInstance()); - for (Iterator it = pluginManager.getObjectIterator(HalJsonPage.class); it.hasNext(); ) + for (Iterator it = pluginManager.getSingletonIterator(HalJsonPage.class); it.hasNext(); ) registerPage(it.next()); - for (Iterator it = pluginManager.getObjectIterator(HalWebPage.class); it.hasNext(); ) + for (Iterator it = pluginManager.getSingletonIterator(HalWebPage.class); it.hasNext(); ) registerPage(it.next()); http.start(); } - public static PluginManager getPluginManager() { - return pluginManager; + public static void setPluginEnabled(String name, boolean enabled) throws SQLException { + DBConnection db = HalContext.getDB(); + PluginConfig pluginConfig = PluginConfig.getPluginConfig(db, name); + + if (pluginConfig == null) + pluginConfig = new PluginConfig(name); + + logger.info("Plugin '" + name + "' has been " + (enabled ? "enabled" : "disabled") + ", change will take affect after restart."); + pluginManager.getPluginData(name).setEnabled(enabled); + + pluginConfig.setEnabled(enabled); + pluginConfig.save(db); } + public static List getPlugins() { + return pluginManager.toArray(); + } + + public static void registerDaemon(HalDaemon daemon){ daemons.add(daemon); daemon.initiate(daemonExecutor); } + public static void registerPage(HalWebPage page){ pages.add(page); http.setPage(page.getId(), page); diff --git a/src/se/hal/page/PluginConfigWebPage.java b/src/se/hal/page/PluginConfigWebPage.java index 8cc01e10..bbc58b1d 100644 --- a/src/se/hal/page/PluginConfigWebPage.java +++ b/src/se/hal/page/PluginConfigWebPage.java @@ -3,6 +3,11 @@ package se.hal.page; import se.hal.HalContext; import se.hal.HalServer; import se.hal.intf.HalWebPage; +import se.hal.page.HalAlertManager.AlertLevel; +import se.hal.page.HalAlertManager.AlertTTL; +import se.hal.page.HalAlertManager.HalAlert; +import se.hal.struct.devicedata.SwitchEventData; +import zutil.ObjectUtil; import zutil.db.DBConnection; import zutil.io.file.FileUtil; import zutil.parser.Templator; @@ -27,12 +32,17 @@ public class PluginConfigWebPage extends HalWebPage { Map request) throws Exception{ - DBConnection db = HalContext.getDB(); + if (request.containsKey("action")) { + String name = request.get("action_id"); + HalServer.setPluginEnabled(name, + (request.containsKey("enabled") && "on".equals(request.get("enabled")))); - PluginManager pluginManager = HalServer.getPluginManager(); + HalAlertManager.getInstance().addAlert(new HalAlert( + AlertLevel.SUCCESS, "Successfully updated plugin " + name + ", change will take affect after restart.", AlertTTL.ONE_VIEW)); + } Templator tmpl = new Templator(FileUtil.find(TEMPLATE)); - tmpl.set("plugins", pluginManager.toArray()); + tmpl.set("plugins", HalServer.getPlugins()); return tmpl; } diff --git a/src/se/hal/struct/PluginConfig.java b/src/se/hal/struct/PluginConfig.java new file mode 100644 index 00000000..a9ea97c5 --- /dev/null +++ b/src/se/hal/struct/PluginConfig.java @@ -0,0 +1,68 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ziver Koc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package se.hal.struct; + +import zutil.db.DBConnection; +import zutil.db.bean.DBBean; +import zutil.db.bean.DBBeanSQLResultHandler; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + + +@DBBean.DBTable(value="plugin") +public class PluginConfig extends DBBean { + private String name; + private boolean enabled; + + + /** + * @return a PluginConfig bean for the specific plugin name. + */ + public static PluginConfig getPluginConfig(DBConnection db, String name) throws SQLException { + PreparedStatement stmt = db.getPreparedStatement( "SELECT plugin.* FROM plugin WHERE name == ?" ); + stmt.setString(1, name); + return DBConnection.exec(stmt, DBBeanSQLResultHandler.create(PluginConfig.class, db) ); + } + + + public PluginConfig() {} + public PluginConfig(String name) { + this.name = name; + } + + + public String getName() { + return name; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } +}