/**
* Copyright 2016-2017 Sixt GmbH & Co. Autovermietung KG
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain a
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.sixt.service.framework.configuration;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.sixt.service.framework.ServiceProperties;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
@Singleton
public class ConfigurationManager {
private static final Logger logger = LoggerFactory.getLogger(ConfigurationManager.class);
protected ServiceProperties serviceProps;
protected Multimap<String, ChangeCallback> callbackListeners;
private Map<String, String> lastProperties;
private AtomicBoolean dataReceived = new AtomicBoolean(false);
private CountDownLatch startupLatch = new CountDownLatch(1);
@Inject
public ConfigurationManager(ServiceProperties props) {
this.serviceProps = props;
this.callbackListeners = Multimaps.synchronizedMultimap(ArrayListMultimap.create());
this.lastProperties = new HashMap<>(props.getAllProperties());
}
public synchronized void processValues(Map<String, String> updatedValues) {
updatedValues.keySet().stream()
.forEach(key -> {
String newValue = updatedValues.get(key);
//process only new or updated values
if (! StringUtils.equals(newValue, lastProperties.get(key))) {
lastProperties.put(key, newValue);
notifyListeners(key, newValue);
//(allows command-line overrides)
serviceProps.addProperty(key, newValue);
}
});
dataReceived.set(true);
startupLatch.countDown();
}
public void waitForInitialConfiguration() {
logger.info("Waiting for initial service configuration");
while (!dataReceived.get()) {
try {
startupLatch.await();
} catch (InterruptedException e) {
}
}
logger.info("Received initial service configuration");
}
public void registerChangeCallback(String entry, ChangeCallback callback) {
callbackListeners.put(entry, callback);
}
private void notifyListeners(String key, String value) {
synchronized (callbackListeners) {
Collection<ChangeCallback> listeners = callbackListeners.get(key);
if (listeners != null) {
for (ChangeCallback listener : listeners) {
try {
listener.entryChanged(key, value);
} catch (Exception ex) {
logger.error("Error notifying listener of configuration change", ex);
}
}
}
}
}
}