package be.neutrinet.ispng.config; import be.neutrinet.ispng.util.Zookeeper; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.api.CuratorWatcher; import org.apache.log4j.Logger; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.data.Stat; import java.nio.charset.Charset; import java.util.Map; import java.util.Optional; import java.util.Properties; import java.util.function.Consumer; /** * Created by wannes on 24/08/14. */ public class Config { private final static Config instance = new Config(); private final static Charset CHARSET = Charset.forName("UTF-8"); private final static String PREFIX = "/ispng/"; private CuratorFramework cf; private Config() { } public static Config get() { return instance; } public static Optional<String> get(String key) { return instance.getValue(key); } public static String get(String key, String defaultValue) { Optional<String> val = get(key); if (val.isPresent()) return val.get(); else return defaultValue; } public final void boot(Properties cfg) { this.cf = Zookeeper.get(); for (Map.Entry<Object, Object> entry : cfg.entrySet()) { write(entry.getKey().toString().replace(".", "/"), entry.getValue().toString()); } } public Optional<String> getValue(String key) { try { Stat stat = cf.checkExists().forPath(PREFIX + key); if (stat == null) return Optional.empty(); byte[] value = cf.getData().forPath(PREFIX + key); if (value == null) return Optional.empty(); return Optional.ofNullable(new String(value, CHARSET)); } catch (Exception ex) { Logger.getLogger(getClass()).error("Failed to read config from ZeeKeeper", ex); } return Optional.empty(); } public void write(String key, String value) { try { Stat stat = cf.checkExists().forPath(PREFIX + key); if (stat == null) { cf.create().creatingParentsIfNeeded().forPath(PREFIX + key, value.getBytes(CHARSET)); } else { cf.setData().forPath(PREFIX + key, value.getBytes(CHARSET)); } } catch (Exception ex) { Logger.getLogger(getClass()).error("Failed to write config to ZooKeeper", ex); } } public void getAndWatch(String key, String defaultValue, Consumer<String> listener) { try { CuratorWatcher cw = (WatchedEvent watchedEvent) -> { if (watchedEvent.getType() == Watcher.Event.EventType.NodeDataChanged) { byte[] value = cf.getData().forPath(watchedEvent.getPath()); String strVal = new String(value, CHARSET); Logger.getLogger(getClass()).debug("ZK key " + key + " changed value to " + strVal); listener.accept(strVal); } }; Stat stat = cf.checkExists().forPath(PREFIX + key); if (stat == null) cf.create().creatingParentsIfNeeded().forPath(PREFIX + key, defaultValue.getBytes(CHARSET)); cf.getData().usingWatcher(cw).forPath(PREFIX + key); listener.accept(get(key, defaultValue)); } catch (Exception ex) { Logger.getLogger(getClass()).error("Failed to add config watcher", ex); } } public void watch(String key, Consumer<String> listener) { try { CuratorWatcher cw = (WatchedEvent watchedEvent) -> { if (watchedEvent.getType() == Watcher.Event.EventType.NodeDataChanged) { byte[] value = cf.getData().forPath(watchedEvent.getPath()); listener.accept(new String(value, CHARSET)); } }; Stat stat = cf.checkExists().forPath(PREFIX + key); if (stat == null) cf.create().creatingParentsIfNeeded().forPath(PREFIX + key, null); cf.getData().usingWatcher(cw).forPath(PREFIX + key); } catch (Exception ex) { Logger.getLogger(getClass()).error("Failed to add config watcher", ex); } } public void watch(String[] keys, Consumer<String> listener) { try { CuratorWatcher cw = (WatchedEvent watchedEvent) -> { if (watchedEvent.getType() == Watcher.Event.EventType.NodeDataChanged) { byte[] value = cf.getData().forPath(watchedEvent.getPath()); listener.accept(new String(value, CHARSET)); } }; for (String key : keys) { Stat stat = cf.checkExists().forPath(PREFIX + key); if (stat == null) cf.create().creatingParentsIfNeeded().forPath(PREFIX + key, null); cf.getData().usingWatcher(cw).forPath(PREFIX + key); } } catch (Exception ex) { Logger.getLogger(getClass()).error("Failed to add config watcher", ex); } } }