initial implementation of triggers. issue 6
This commit is contained in:
parent
6a8040b529
commit
dd1bb75192
8 changed files with 283 additions and 11 deletions
|
|
@ -32,16 +32,17 @@ public class HalServer {
|
||||||
// init logging
|
// init logging
|
||||||
LogUtil.readConfiguration("logging.properties");
|
LogUtil.readConfiguration("logging.properties");
|
||||||
|
|
||||||
|
// init DB and other configurations
|
||||||
|
DBConnection db = HalContext.getDB();
|
||||||
|
|
||||||
// init Managers
|
// init Managers
|
||||||
PluginManager pluginManager = new PluginManager("./");
|
PluginManager pluginManager = new PluginManager("./");
|
||||||
HalContext.initialize();
|
HalContext.initialize();
|
||||||
ControllerManager.initialize(pluginManager);
|
|
||||||
HalAlertManager.initialize();
|
HalAlertManager.initialize();
|
||||||
|
ControllerManager.initialize(pluginManager);
|
||||||
|
TriggerManager.initialize(pluginManager);
|
||||||
|
|
||||||
|
|
||||||
// init DB and other configurations
|
|
||||||
DBConnection db = HalContext.getDB();
|
|
||||||
|
|
||||||
// Init sensors,events and controllers
|
// Init sensors,events and controllers
|
||||||
for(Sensor sensor : Sensor.getLocalSensors(db)){
|
for(Sensor sensor : Sensor.getLocalSensors(db)){
|
||||||
ControllerManager.getInstance().register(sensor);
|
ControllerManager.getInstance().register(sensor);
|
||||||
|
|
|
||||||
90
src/se/hal/TriggerManager.java
Executable file
90
src/se/hal/TriggerManager.java
Executable file
|
|
@ -0,0 +1,90 @@
|
||||||
|
package se.hal;
|
||||||
|
|
||||||
|
import se.hal.intf.HalAction;
|
||||||
|
import se.hal.intf.HalTrigger;
|
||||||
|
import se.hal.struct.TriggerFlow;
|
||||||
|
import zutil.log.LogUtil;
|
||||||
|
import zutil.plugin.PluginManager;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles all triggers registered on Hal
|
||||||
|
*/
|
||||||
|
public class TriggerManager {
|
||||||
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
private static TriggerManager instance;
|
||||||
|
|
||||||
|
private ArrayList<Class<? extends HalTrigger>> availableTriggers = new ArrayList<>();
|
||||||
|
private ArrayList<Class<? extends HalAction>> availableActions = new ArrayList<>();
|
||||||
|
|
||||||
|
private ArrayList<TriggerFlow> triggerFlows = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void addAvailableTrigger(Class<? extends HalTrigger> clazz) {
|
||||||
|
if ( ! availableTriggers.contains(clazz))
|
||||||
|
availableTriggers.add(clazz);
|
||||||
|
}
|
||||||
|
public List<Class<? extends HalTrigger>> getAvailableTriggers() {
|
||||||
|
return availableTriggers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAvailableAction(Class<? extends HalAction> clazz) {
|
||||||
|
if ( ! availableActions.contains(clazz))
|
||||||
|
availableActions.add(clazz);
|
||||||
|
}
|
||||||
|
public List<Class<? extends HalAction>> getAvailableActions() {
|
||||||
|
return availableActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void register(TriggerFlow flow){
|
||||||
|
if ( ! triggerFlows.contains(flow))
|
||||||
|
triggerFlows.add(flow);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main execution method.
|
||||||
|
* This method will go through all flows and evaluate them. If the
|
||||||
|
* evaluation of a trigger returns true then its execute method will be called.
|
||||||
|
*/
|
||||||
|
public synchronized void evaluateAndExecute() {
|
||||||
|
for (int i = 0; i < triggerFlows.size(); i++) { // avoid foreach as triggerFlow can change while we are running
|
||||||
|
TriggerFlow flow = triggerFlows.get(i);
|
||||||
|
if (flow.evaluate()) {
|
||||||
|
logger.fine("Flow "+ flow.getId() +" evaluated true, executing actions");
|
||||||
|
flow.execute();
|
||||||
|
flow.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void initialize(PluginManager pluginManager){
|
||||||
|
TriggerManager manager = new TriggerManager();
|
||||||
|
|
||||||
|
for (Iterator<Class<? extends HalTrigger>> it = pluginManager.getClassIterator(HalTrigger.class);
|
||||||
|
it.hasNext(); ){
|
||||||
|
manager.addAvailableTrigger(it.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Iterator<Class<? extends HalAction>> it = pluginManager.getClassIterator(HalAction.class);
|
||||||
|
it.hasNext(); ){
|
||||||
|
manager.addAvailableAction(it.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
instance = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TriggerManager getInstance(){
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
9
src/se/hal/intf/HalAction.java
Executable file
9
src/se/hal/intf/HalAction.java
Executable file
|
|
@ -0,0 +1,9 @@
|
||||||
|
package se.hal.intf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a action that will be executed
|
||||||
|
*/
|
||||||
|
public interface HalAction {
|
||||||
|
|
||||||
|
void execute();
|
||||||
|
}
|
||||||
20
src/se/hal/intf/HalTrigger.java
Executable file
20
src/se/hal/intf/HalTrigger.java
Executable file
|
|
@ -0,0 +1,20 @@
|
||||||
|
package se.hal.intf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A interfaces that declares a trigger/condition that
|
||||||
|
* needs to be validated before an action can be run
|
||||||
|
*/
|
||||||
|
public interface HalTrigger {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates if this trigger has passed. If the trigger is
|
||||||
|
* true then this method will return true until the {@link #reset()}
|
||||||
|
* method is called.
|
||||||
|
*/
|
||||||
|
boolean evaluate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the evaluation to false.
|
||||||
|
*/
|
||||||
|
void reset();
|
||||||
|
}
|
||||||
|
|
@ -68,14 +68,16 @@ public class NetScanController implements HalEventController, HalAutoScannableCo
|
||||||
public void run() {
|
public void run() {
|
||||||
try(MultiCommandExecutor executor = new MultiCommandExecutor();){
|
try(MultiCommandExecutor executor = new MultiCommandExecutor();){
|
||||||
for (Map.Entry<LocalNetworkDevice,SwitchEventData> entry : devices.entrySet()) {
|
for (Map.Entry<LocalNetworkDevice,SwitchEventData> entry : devices.entrySet()) {
|
||||||
|
LocalNetworkDevice device = entry.getKey();
|
||||||
|
SwitchEventData data = entry.getValue();
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
//logger.finest("Pinging IP "+entry.getKey().getHost());
|
//logger.finest("Pinging IP "+ device.getHost());
|
||||||
boolean online = InetScanner.isReachable(entry.getKey().getHost(), executor);
|
boolean online = InetScanner.isReachable(device.getHost(), executor);
|
||||||
if (entry.getValue() == null || entry.getValue().isOn() != online) {
|
if (data == null || data.isOn() != online) {
|
||||||
entry.setValue(
|
entry.setValue(
|
||||||
new SwitchEventData(online, System.currentTimeMillis()));
|
new SwitchEventData(online, System.currentTimeMillis()));
|
||||||
logger.fine("IP "+entry.getKey().getHost() +" state has changed to "+ entry.getValue());
|
logger.fine("IP "+device.getHost() +" state has changed to "+ data);
|
||||||
listener.reportReceived(entry.getKey(), entry.getValue());
|
listener.reportReceived(device, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
{"se.hal.intf.HalHttpPage": "se.hal.page.PCOverviewHttpPage"},
|
{"se.hal.intf.HalHttpPage": "se.hal.page.PCOverviewHttpPage"},
|
||||||
{"se.hal.intf.HalHttpPage": "se.hal.page.PCHeatMapHttpPage"},
|
{"se.hal.intf.HalHttpPage": "se.hal.page.PCHeatMapHttpPage"},
|
||||||
|
|
||||||
{"se.hal.intf.HalDaemon": "se.hal.deamon.PCDataSynchronizationClient"},
|
{"se.hal.intf.HalDaemon": "se.hal.daemon.PCDataSynchronizationClient"},
|
||||||
{"se.hal.intf.HalDaemon": "se.hal.deamon.PCDataSynchronizationDaemon"}
|
{"se.hal.intf.HalDaemon": "se.hal.daemon.PCDataSynchronizationDaemon"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
55
src/se/hal/struct/TriggerFlow.java
Executable file
55
src/se/hal/struct/TriggerFlow.java
Executable file
|
|
@ -0,0 +1,55 @@
|
||||||
|
package se.hal.struct;
|
||||||
|
|
||||||
|
import se.hal.intf.HalAction;
|
||||||
|
import se.hal.intf.HalTrigger;
|
||||||
|
import zutil.db.bean.DBBean;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class that encapsulates triggers and their actions.
|
||||||
|
* TODO: Bad class name, should be renamed when we come up with a better one
|
||||||
|
*/
|
||||||
|
public class TriggerFlow extends DBBean {
|
||||||
|
private ArrayList<HalTrigger> triggers = new ArrayList<>();
|
||||||
|
private ArrayList<HalAction> actions = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
public void addTrigger(HalTrigger trigger) {
|
||||||
|
triggers.add(trigger);
|
||||||
|
}
|
||||||
|
public void addAction(HalAction action) {
|
||||||
|
actions.add(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if any one of the triggers evaluate to true,
|
||||||
|
* false if there are no triggers added.
|
||||||
|
* Note: this method will not execute any actions
|
||||||
|
*/
|
||||||
|
public boolean evaluate(){
|
||||||
|
for(HalTrigger trigger : triggers){
|
||||||
|
if (trigger.evaluate())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the associated actions in this flow
|
||||||
|
*/
|
||||||
|
public void execute(){
|
||||||
|
for(HalAction action : actions){
|
||||||
|
action.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets all trigger evaluations
|
||||||
|
*/
|
||||||
|
public void reset() {
|
||||||
|
for(HalTrigger trigger : triggers){
|
||||||
|
trigger.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
95
test/se/hal/TriggerManagerTest.java
Executable file
95
test/se/hal/TriggerManagerTest.java
Executable file
|
|
@ -0,0 +1,95 @@
|
||||||
|
package se.hal;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import se.hal.intf.HalAction;
|
||||||
|
import se.hal.intf.HalTrigger;
|
||||||
|
import se.hal.struct.TriggerFlow;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class TriggerManagerTest {
|
||||||
|
|
||||||
|
private TriggerManager manager = new TriggerManager();
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registerAvailableTrigger(){
|
||||||
|
assertEquals(Collections.EMPTY_LIST, manager.getAvailableTriggers());
|
||||||
|
|
||||||
|
manager.addAvailableTrigger(TestTrigger.class);
|
||||||
|
manager.addAvailableTrigger(TestTrigger.class);
|
||||||
|
assertEquals(1, manager.getAvailableTriggers().size());
|
||||||
|
assertTrue(manager.getAvailableTriggers().contains(TestTrigger.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void registerAvailableAction(){
|
||||||
|
assertEquals(Collections.EMPTY_LIST, manager.getAvailableActions());
|
||||||
|
|
||||||
|
manager.addAvailableAction(TestAction.class);
|
||||||
|
manager.addAvailableAction(TestAction.class);
|
||||||
|
assertEquals(1, manager.getAvailableActions().size());
|
||||||
|
assertTrue(manager.getAvailableActions().contains(TestAction.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void register(){
|
||||||
|
registerAvailableTrigger();
|
||||||
|
|
||||||
|
TriggerFlow flow = new TriggerFlow();
|
||||||
|
flow.addTrigger(new TestTrigger(true));
|
||||||
|
TestAction action = new TestAction();
|
||||||
|
flow.addAction(action);
|
||||||
|
manager.register(flow);
|
||||||
|
manager.evaluateAndExecute();
|
||||||
|
assertEquals(1, action.nrOfExecutions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void evaluateAndExecute(){
|
||||||
|
registerAvailableTrigger();
|
||||||
|
|
||||||
|
TriggerFlow flow = new TriggerFlow();
|
||||||
|
TestTrigger trigger = new TestTrigger(true);
|
||||||
|
flow.addTrigger(trigger);
|
||||||
|
TestAction action = new TestAction();
|
||||||
|
flow.addAction(action);
|
||||||
|
manager.register(flow);
|
||||||
|
|
||||||
|
manager.evaluateAndExecute();
|
||||||
|
assertEquals("Action executed nr of times",
|
||||||
|
1, action.nrOfExecutions);
|
||||||
|
|
||||||
|
manager.evaluateAndExecute();
|
||||||
|
assertEquals("Action executed nr of times",
|
||||||
|
1, action.nrOfExecutions);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private static class TestTrigger implements HalTrigger {
|
||||||
|
boolean evaluation;
|
||||||
|
TestTrigger(boolean b){ evaluation = b; }
|
||||||
|
@Override
|
||||||
|
public boolean evaluate() { return evaluation; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() { evaluation = false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class TestAction implements HalAction {
|
||||||
|
int nrOfExecutions;
|
||||||
|
@Override
|
||||||
|
public void execute() { nrOfExecutions++; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue