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());
}
}
});
}
}