Added the ability to enable or disable plugins on startup

This commit is contained in:
Ziver Koc 2020-06-25 23:36:37 +02:00
parent b3f28c8276
commit dc829b9487
8 changed files with 190 additions and 34 deletions

34
Hal.iml
View file

@ -26,23 +26,7 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="Zutil" exported="" />
<orderEntry type="module-library" exported="">
<library name="lib">
<CLASSES>
<root url="file://$MODULE_DIR$/lib" />
</CLASSES>
<JAVADOC />
<NATIVE>
<root url="file://$MODULE_DIR$/lib" />
</NATIVE>
<SOURCES>
<root url="jar://$USER_HOME$/.ideaLibSources/wzwave-0.0.3-sources.jar!/" />
<root url="jar://$USER_HOME$/.ideaLibSources/netty-all-4.0.46.Final-sources.jar!/" />
</SOURCES>
<jarDirectory url="file://$MODULE_DIR$/lib" recursive="false" />
</library>
</orderEntry>
<orderEntry type="module" module-name="Zutil" />
<orderEntry type="module-library" exported="">
<library>
<CLASSES>
@ -73,5 +57,21 @@
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library" exported="">
<library name="lib">
<CLASSES>
<root url="file://$MODULE_DIR$/lib" />
</CLASSES>
<JAVADOC />
<NATIVE>
<root url="file://$MODULE_DIR$/lib" />
</NATIVE>
<SOURCES>
<root url="jar://$USER_HOME$/.ideaLibSources/wzwave-0.0.3-sources.jar!/" />
<root url="jar://$USER_HOME$/.ideaLibSources/netty-all-4.0.46.Final-sources.jar!/" />
</SOURCES>
<jarDirectory url="file://$MODULE_DIR$/lib" recursive="false" />
</library>
</orderEntry>
</component>
</module>

View file

@ -15,7 +15,7 @@
<property name="releaseDir" value="${buildRoot}/release" />
<property name="reportsDir" value="${buildRoot}/reports" />
<property name="releaseJar" value="hal.jar" />
<property name="zutilVersion" value="1.0.249" />
<property name="zutilVersion" value="1.0.250" />
<!-- ________________________ CLASSPATH ________________________ -->

Binary file not shown.

View file

@ -7,16 +7,37 @@
<table class="table table-hover table-condensed">
<thead>
<th class="col-md-2">Name</th>
<th class="col-md-3">Name</th>
<th class="col-md-8">Version</th>
<th class="col-md-1 text-right">Actions</th>
</thead>
{{#plugins}}
<tr>
<td>{{.getName()}}</td>
<td>{{.getVersion()}}</td>
<td>
<form method="POST">
<input type="hidden" name="action" value="modify">
<input type="hidden" name="action_id" value="{{.getName()}}">
<div class="btn-toolbar pull-right">
<input class="toggle-switch" type="checkbox" name="enabled"
data-size="mini" data-on-color="danger"
{{#.isEnabled()}}checked{{/.isEnabled()}} >
</div>
</form>
</td>
</tr>
{{/plugins}}
</table>
</div>
</div>
</div>
</div>
<script>
$(function (){
$(".toggle-switch").on("switchChange.bootstrapSwitch", function (event, state) {
$(this).closest('form').submit();
});
});
</script>

View file

@ -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;

View file

@ -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<HalDaemon> 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<HalDaemon> it=pluginManager.getObjectIterator(HalDaemon.class); it.hasNext(); )
for (Iterator<HalDaemon> 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<HalWebPage> it = pluginManager.getObjectIterator(HalJsonPage.class); it.hasNext(); )
for (Iterator<HalWebPage> it = pluginManager.getSingletonIterator(HalJsonPage.class); it.hasNext(); )
registerPage(it.next());
for (Iterator<HalWebPage> it = pluginManager.getObjectIterator(HalWebPage.class); it.hasNext(); )
for (Iterator<HalWebPage> 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<PluginData> 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);

View file

@ -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<String, String> 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;
}

View file

@ -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;
}
}