Protocol.java

package emissary.core.sentinel.protocols;

import emissary.config.Configurator;
import emissary.core.Factory;
import emissary.core.sentinel.protocols.actions.Action;
import emissary.core.sentinel.protocols.actions.Notify;
import emissary.core.sentinel.protocols.rules.Rule;

import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Protocols are configured with a list of rules that trigger some action if all conditions are met.
 */
public abstract class Protocol {

    protected static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

    protected Configurator config;
    protected final Map<String, Rule> rules = new ConcurrentHashMap<>();
    protected Action action;
    protected boolean enabled = false;

    protected Protocol() {}

    public Protocol(Configurator config) {
        configure(config);
    }

    public abstract void run() throws IOException;

    protected abstract Rule<?> getRule(String ruleId) throws IOException;

    public boolean isEnabled() {
        return this.enabled && MapUtils.isNotEmpty(this.rules);
    }

    protected void configure(final Configurator config) {
        this.config = config;
        init();
    }

    /**
     * Initialize rule set and action
     */
    protected void init() {
        this.enabled = this.config.findBooleanEntry("ENABLED", false);
        this.action = (Action) Factory.create(this.config.findStringEntry("ACTION", Notify.class.getName()));

        logger.trace("Loading rules...");
        for (String ruleId : this.config.findEntries("RULE_ID")) {
            if (this.rules.containsKey(ruleId)) {
                logger.warn("Sentinel rule with ID[{}] already exists, this may result in unexpected behavior", ruleId);
            }
            try {
                final Rule<?> ruleImpl = getRule(ruleId);
                this.rules.put(ruleId, ruleImpl);
                logger.debug("Sentinel loaded rule[{}] - {}", ruleId, ruleImpl);
            } catch (Exception e) {
                logger.warn("Sentinel rule[{}] is invalid: {}", ruleId, e.getMessage());
            }
        }

        if (this.rules.isEmpty()) {
            this.enabled = false;
        }
    }

}