Files
commons/src/main/java/net/locusworks/common/configuration/ConfigurationManager.java
2019-07-21 10:52:22 -05:00

151 lines
5.4 KiB
Java

package net.locusworks.common.configuration;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import net.locusworks.common.Charsets;
import net.locusworks.common.crypto.AES;
import net.locusworks.common.exceptions.ApplicationException;
import net.locusworks.common.interfaces.PersistableRequest;
import net.locusworks.common.utils.Utils;
public class ConfigurationManager {
private Properties configuration;
private Properties defaults = null;
private Path conf = null;
protected AES aes;
private ConfigurationCallback callback;
protected void init(String baseDir, String propertiesFile, ConfigurationCallback callback) throws IOException {
init(baseDir, propertiesFile, this.getClass().getName().getBytes(Charsets.UTF_8), callback);
}
protected void init(String baseDir, String propertiesFile, byte[] aesKey, ConfigurationCallback callback) throws IOException {
aes = aesKey.length > 0 ? AES.createInstance(aesKey) : AES.createInstance();
this.callback = callback;
try {
defaults = PropertiesManager.loadConfiguration(this.getClass(), propertiesFile);
} catch (IOException ex) {
throw ex;
}
// create patchrepoConf File object
conf = Paths.get(baseDir).resolve(propertiesFile);
loadConfiguration();
}
private void loadConfiguration() {
// load the active config file
// ignore read error, we can continue with an empty configuration map
// and all default items will be added below and the file created
callbackMessage("Loading config file: " + conf);
try {
configuration = PropertiesManager.loadConfiguration(conf);
} catch (Exception e) {
callbackMessage("Config file: " + conf + " will be created from template");
configuration = new Properties();
}
Map<String, String> results = PropertiesManager.addConfiguration(configuration, defaults);
boolean changed = !results.isEmpty();
if (!results.isEmpty()) {
StringBuilder sb = new StringBuilder("Added new configuration items:\n");
for (Entry<String, String> entry : results.entrySet()) {
sb.append(String.format("%s=%s\n", entry.getKey(), entry.getValue()));
}
callbackMessage(sb.toString());
}
results = PropertiesManager.removeConfiguration(configuration, defaults);
changed |= !results.isEmpty();
if (!results.isEmpty()) {
StringBuilder sb = new StringBuilder("Added new configuration items:\n");
for (Entry<String, String> entry : results.entrySet()) {
sb.append(String.format("%s=%s\n", entry.getKey(), entry.getValue()));
}
callbackMessage(sb.toString());
}
if (changed) {
PropertiesManager.saveConfiguration(configuration, conf, "Patch Repository properties file");
}
}
/**
* Save the configuration values to file
* @param confs Configuration property values to save
* @throws Exception general exception
*/
public void saveToConf(Properties confs) throws Exception {
PropertiesManager.saveConfiguration(confs, conf, conf.getFileName().toString());
callbackMessage("Saved config file: " + conf + ", " + confs.size() + " entries");
loadConfiguration();
}
public String getPropertyValue(String key) {
return getPropertyValue(key, null);
}
public String getPropertyValue(String key, String defaultValue) {
return configuration.containsKey(key) ? configuration.getProperty(key) : defaultValue;
}
public Properties getConfiguration() {
return configuration;
}
public void saveConfiguration(PersistableRequest request, Set<String> fieldsToSave, Set<String> excryptedFields) throws Exception {
if (fieldsToSave == null || fieldsToSave.isEmpty()) {
throw ApplicationException.generic("No fields to save were defined");
}
if (excryptedFields == null) {
excryptedFields = new HashSet<>();
}
try {
Properties props = new Properties();
//copy what is current in the configuration settings into the new properties file
configuration.entrySet().forEach(item -> props.setProperty(String.valueOf(item.getKey()), String.valueOf(item.getValue())));
boolean changed = false;
for (Field f : request.getClass().getDeclaredFields()) {
f.setAccessible(true);
String fieldName = f.getName();
String fieldValue = String.valueOf(f.get(request));
//Ensures we are only saving values that are already configured
if (!fieldsToSave.contains(fieldName)) continue;
//Check to see if the old value changed
String oldValue = props.getProperty(fieldName);
if (Utils.isNotValid(oldValue, fieldValue) || oldValue.equals(fieldValue)) { continue; }
changed = true;
fieldValue = excryptedFields.contains(fieldName) ? aes.encrypt(fieldValue) : fieldValue;
props.setProperty(fieldName, fieldValue);
}
if (changed) {
saveToConf(props);
}
} catch (Exception ex) {
throw ApplicationException.actionNotPermitted(ex.getMessage());
}
}
private void callbackMessage(String msg) {
if (callback != null) callback.results(msg);
}
}