Package org.ejbca.config

Source Code of org.ejbca.config.ConfigurationHolder

/*************************************************************************
*                                                                       *
*  EJBCA: The OpenSource Certificate Authority                          *
*                                                                       *
*  This software is free software; you can redistribute it and/or       *
*  modify it under the terms of the GNU Lesser General Public           *
*  License as published by the Free Software Foundation; either         *
*  version 2.1 of the License, or any later version.                    *
*                                                                       *
*  See terms of license at gnu.org.                                     *
*                                                                       *
*************************************************************************/

package org.ejbca.config;

import java.io.File;
import java.net.URL;
import java.util.Iterator;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.SystemConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
import org.apache.log4j.Logger;

/**
* This is a singleton. Used to configure common-configuration with our sources.
*
* Use like this:
*   String value = ConfigurationHolder.getString("my.conf.property.key"); or
*   String value = ConfigurationHolder.getString("my.conf.property.key", "default value");
* or
*   String value = ConfigurationHolder.getExpandedString("my.conf.property.key", "default value");
* to be able to parse values containing ${property}
*
* See in-line comments below for the sources added to the configuration.
*
* @version $Id: ConfigurationHolder.java 11941 2011-05-10 13:18:35Z aveen4711 $
*/
public final class ConfigurationHolder {

  private static final Logger log = Logger.getLogger(ConfigurationHolder.class);

  private static CompositeConfiguration config = null;
  private static CompositeConfiguration configBackup = null;
 
  /** This is a singleton so it's not allowed to create an instance explicitly */
  private ConfigurationHolder() {}
 
  /** ejbca.properties must be first in this file, because CONFIGALLOWEXTERNAL is defined in there. */
  public static final String[] CONFIG_FILES = {"ejbca.properties", "web.properties", "cmp.properties", "externalra-caservice.properties",
    "ocsp.properties", "extendedkeyusage.properties", "jaxws.properties", "xkms.properties", "log.properties", "logdevices/log4j.properties", "cache.properties", "database.properties", "va.properties", "va-publisher.properties"};

  /** Configuration property that enables dynamic reading of properties from the file system. This is not allowed by default for security reasons. */
  public static final String CONFIGALLOWEXTERNAL = "allow.external-dynamic.configuration";

  public static Configuration instance() {
    if (config == null) {
      // read ejbca.properties, from config file built into jar, and see if we allow configuration by external files
      boolean allowexternal = false;
      try {
        final URL url = ConfigurationHolder.class.getResource("/conf/"+CONFIG_FILES[0]);
        if (url != null) {
          final PropertiesConfiguration pc = new PropertiesConfiguration(url);
          allowexternal = "true".equalsIgnoreCase(pc.getString(CONFIGALLOWEXTERNAL, "false"));
          log.info("Allow external re-configuration: " + allowexternal);
        }
      } catch (ConfigurationException e) {
        log.error("Error intializing configuration: ", e);
      }
      config = new CompositeConfiguration();

      // Only add these config sources if we allow external configuration
      if (allowexternal) {
        // Override with system properties, this is prio 1 if it exists (java -Dscep.test=foo)
        config.addConfiguration(new SystemConfiguration());
        log.info("Added system properties to configuration source (java -Dfoo.prop=bar).");

        // Override with file in "application server home directory"/conf, this is prio 2
        for (int i=0; i<CONFIG_FILES.length; i++) {
          File f = null;
          try {
            f = new File("conf"+File.separator+CONFIG_FILES[i]);
            final PropertiesConfiguration pc = new PropertiesConfiguration(f);
            pc.setReloadingStrategy(new FileChangedReloadingStrategy());
            config.addConfiguration(pc);
            log.info("Added file to configuration source: "+f.getAbsolutePath());
          } catch (ConfigurationException e) {
            log.error("Failed to load configuration from file " + f.getAbsolutePath());
          }
        }
        // Override with file in "/etc/ejbca/conf/, this is prio 3
        for (int i=0; i<CONFIG_FILES.length; i++) {
          File f = null;
          try {
            f = new File("/etc/ejbca/conf/" + CONFIG_FILES[i]);
            final PropertiesConfiguration pc = new PropertiesConfiguration(f);
            pc.setReloadingStrategy(new FileChangedReloadingStrategy());
            config.addConfiguration(pc);
            log.info("Added file to configuration source: "+f.getAbsolutePath());             
          } catch (ConfigurationException e) {
            log.error("Failed to load configuration from file " + f.getAbsolutePath());
          }
        }
      } // if (allowexternal)
     
      // Default values build into jar file, this is last prio used if no of the other sources override this
      for (int i=0; i<CONFIG_FILES.length; i++) {
        addConfigurationResource(CONFIG_FILES[i]);
      }
      // Load internal.properties only from built in configuration file
      try {
        final URL url = ConfigurationHolder.class.getResource("/internal.properties");
        if (url != null) {
          final PropertiesConfiguration pc = new PropertiesConfiguration(url);
          config.addConfiguration(pc);
          log.debug("Added url to configuration source: " + url);
        }
      } catch (ConfigurationException e) {
        log.error("Failed to load configuration from resource internal.properties", e);
      }
    }
    return config;
  }
 
  /** Method used primarily for JUnit testing, where we can add a new properties file (in tmp directory)
   * to the configuration.
   * @param filename the full path to the properties file used for configuration.
   */
  public static void addConfigurationFile(final String filename) {
    // Make sure the basic initialization has been done
    instance();
    File f = null;
    try {
      f = new File(filename);
      final PropertiesConfiguration pc = new PropertiesConfiguration(f);
      pc.setReloadingStrategy(new FileChangedReloadingStrategy());
      config.addConfiguration(pc);
      log.info("Added file to configuration source: "+f.getAbsolutePath());             
    } catch (ConfigurationException e) {
      log.error("Failed to load configuration from file " + f.getAbsolutePath());
    }
  }
 
  /**
   * Add built in config file
   */
  public static void addConfigurationResource(final String resourcename) {
    // Make sure the basic initialization has been done
    instance();
    try {
      final URL url = ConfigurationHolder.class.getResource("/conf/" + resourcename);
      if (url != null) {
        final PropertiesConfiguration pc = new PropertiesConfiguration(url);
        config.addConfiguration(pc);
        log.debug("Added url to configuration source: " + url);
      }
    } catch (ConfigurationException e) {
      log.error("Failed to load configuration from resource " + "/conf/" + resourcename, e);
    }
  }
 
  /**
   * @return the configuration as a regular Properties object
   */
  public static Properties getAsProperties() {
    final Properties properties = new Properties();
    final Iterator i = instance().getKeys();
    while (i.hasNext()) {
      final String key = (String) i.next();
      properties.setProperty(key, instance().getString(key));
    }
    return properties;
  }

  /**
   * @param property the property to look for
   * @param defaultValue default value to use if property is not found
   * @return String configured for property, or default value, if defaultValue is null and property is not found null is returned.
   */
  public static String getString(final String property, final String defaultValue) {
    // Commons configuration interprets ','-separated values as an array of Strings, but we need the whole String for example SubjectDNs.
    final String ret;
    final StringBuilder str = new StringBuilder();
    final String rets[] = instance().getStringArray(property);
    for (int i=0; i<rets.length; i++) {
      if (i != 0) {
        str.append(',')
      }
      str.append(rets[i]);
    }
    if (str.length() != 0) {
      ret = str.toString();
    } else {
      ret = defaultValue;
    }
    return ret;
  }
 
  /**
   * Return a the expanded version of a property. E.g.
   *  property1=foo
   *  property2=${property1}bar
   * would return "foobar" for property2
   * @param defaultValue to use if no property of such a name is found
   */
  public static String getExpandedString(final String property, final String defaultValue) {
    String ret = getString(property, defaultValue);
    if (ret != null) {
      while (ret.indexOf("${") != -1) {
        ret = interpolate(ret);
      }
    }
    return ret;
  }
 
  private static String interpolate(final String orderString) {
    final Pattern PATTERN = Pattern.compile("\\$\\{(.+?)\\}");
    final Matcher m = PATTERN.matcher(orderString);
    final StringBuffer sb = new StringBuffer(orderString.length());
    m.reset();
    while (m.find()) {
      // when the pattern is ${identifier}, group 0 is 'identifier'
      final String key = m.group(1);
      final String value = getExpandedString(key, "");
     
      // if the pattern does exists, replace it by its value
      // otherwise keep the pattern ( it is group(0) )
      if (value != null) {
        m.appendReplacement(sb, value);
      } else {
        // I'm doing this to avoid the backreference problem as there will be a $
        // if I replace directly with the group 0 (which is also a pattern)
        m.appendReplacement(sb, "");
        final String unknown = m.group(0);
        sb.append(unknown);
      }
    }
    m.appendTail(sb);
    return sb.toString();
  }

  /**
   * Backups the original configuration in a non thread safe way.
   *
    * NOTE: This method should only be used by tests through ConfigurationSessionBean!
   */
  public static boolean backupConfiguration() {
    if (configBackup != null) {
      return false;
    }
    configBackup = (CompositeConfiguration) config.clone();
    return true;
  }
 
  /**
   * Restores the original configuration in a non thread safe way.
   *
   * NOTE: This method should only be used by tests through ConfigurationSessionBean!
   */
  public static boolean restoreConfiguration() {
    if (configBackup == null) {
      return false;
    }
    config = configBackup;
    configBackup = null;
    return true;
  }

  /**
   * Takes a backup of the active configuration if necessary and updates the active configuration.
   *
   * NOTE: This method should only be used by tests through ConfigurationSessionBean!
   */
  public static boolean updateConfiguration(final Properties properties) {
    backupConfiguration()// Only takes a backup if necessary.
    final Iterator i = properties.keySet().iterator();
    while (i.hasNext()) {
      final String key = (String) i.next();
      final String value = (String) properties.get(key);
      config.setProperty(key, value);
    }
    return true;
  }

  /**
   * Takes a backup of the active configuration if necessary and updates the active configuration.
   *
   * NOTE: This method should only be used by tests through ConfigurationSessionBean!
   */
  public static boolean updateConfiguration(final String key, final String value) {
    backupConfiguration()// Only takes a backup if necessary.
    config.setProperty(key, value);
    return true;
  }

}
TOP

Related Classes of org.ejbca.config.ConfigurationHolder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.