151 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			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);
 | 
						|
  }
 | 
						|
}
 |