All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.swisspush.gateleen.routing.RuleProvider Maven / Gradle / Ivy

The newest version!
package org.swisspush.gateleen.routing;

import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import io.vertx.core.eventbus.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.swisspush.gateleen.core.storage.ResourceStorage;
import org.swisspush.gateleen.core.util.Address;
import org.swisspush.gateleen.core.util.ResourcesUtils;
import org.swisspush.gateleen.validation.ValidationException;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Provides a central access to the routing rules.
 * Loads routing rules from storage and creates {@link Rule} instances. Also provides the ability to
 * register for routing rules changes.
 * @author https://github.com/mcweba [Marc-Andre Weber]
 */
public class RuleProvider {

    private Logger log = LoggerFactory.getLogger(RuleProvider.class);

    private String rulesPath;
    private String routingRulesSchema;
    private ResourceStorage storage;
    final Map properties;
    private int routeMultiplier;

    private List observers = new ArrayList<>();

    public RuleProvider(Vertx vertx, String rulesPath, ResourceStorage storage, Map properties) {
        this(vertx, rulesPath, storage, properties, Router.DEFAULT_ROUTER_MULTIPLIER);
    }

    public RuleProvider(Vertx vertx, String rulesPath, ResourceStorage storage, Map properties, int routeMultiplier) {
        this.rulesPath = rulesPath;
        this.storage = storage;
        this.properties = properties;
        this.routeMultiplier = routeMultiplier;
        routingRulesSchema = ResourcesUtils.loadResource("gateleen_routing_schema_routing_rules", true);

        notifyRuleChangesObservers();

        log.info("Register on vertx event bus to receive routing rules updates");
        vertx.eventBus().consumer(Address.RULE_UPDATE_ADDRESS, (Handler>) event -> notifyRuleChangesObservers());
    }

    /**
     * Implementations of this interface are notified when the routing rules have changed. Use {@link RuleProvider#registerObserver(RuleChangesObserver)} to
     * register for updates
     */
    public interface RuleChangesObserver {
        void rulesChanged(List rules);
    }

    /**
     * Registers an observer to be notified on routing rules changes.
     *
     * @param observer Observer to be notified on routing rules changes
     */
    public void registerObserver(RuleChangesObserver observer){
        observers.add(observer);
    }

    /**
     * Get the routing rules from storage (async)
     *
     * @return a {@link Promise} containing a list of {@link Rule} objects (when successful)
     */
    public Future> getRules(){
        Promise> promise = Promise.promise();
        storage.get(rulesPath, buffer -> {
            if (buffer != null) {
                try {
                    List rules = new RuleFactory(properties, routingRulesSchema).parseRules(buffer, routeMultiplier);
                    promise.complete(rules);
                } catch (ValidationException e) {
                    log.error("Could parse routing rules", e);
                    promise.fail(e);
                }
            } else {
                promise.fail("Could not get URL '" + (rulesPath == null ? "" : rulesPath) + "' (getting rules).");
            }
        });
        return promise.future();
    }

    private void notifyRuleChangesObservers(){
        getRules().onComplete(event -> {
            if(event.failed()){
                log.error(event.cause().getMessage());
            } else {
                log.info("About to notify observers interested in changed routing rules");
                for (RuleChangesObserver observer : observers) {
                    observer.rulesChanged(event.result());
                }
            }
        });
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy