All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ebay.jetstream.config.ConfigUtils Maven / Gradle / Ivy

/*******************************************************************************
 *  Copyright © 2012-2015 eBay Software Foundation
 *  This program is dual licensed under the MIT and Apache 2.0 licenses.
 *  Please see LICENSE for more information.
 *******************************************************************************/
package com.ebay.jetstream.config;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.LogManager;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;

import com.ebay.jetstream.util.CommonUtils;

public class ConfigUtils {

  public static class StreamHolder implements FactoryBean {
    private final InputStream m_stream;

    @SuppressWarnings("deprecation")
    // deprecated, but we'll use it for now anyway
    public StreamHolder(String contents) {
      m_stream = new java.io.StringBufferInputStream(contents);
    }

    public Object getObject() throws Exception {
      return m_stream;
    }

    public Class getObjectType() {
      return InputStream.class;
    }

    public boolean isSingleton() {
      return false;
    }
  }

  private static final Logger LOGGER = LoggerFactory.getLogger(ConfigUtils.class.getName());
  private static final String PKGS = "java.protocol.handler.pkgs";

  /**
   * Adds a package to the list of URL protocol supporters. Each protocol must be in a separate package with the name of
   * the protocol below the given classes package, and must contain a Handler that extends URLStreamHandler.
   * 
   * @param location
   *            the class whose package is added as a root for URLStreamHandlers.
   * 
   * @return true iff the location was added, else false.
   */
  public static boolean addURLProtocols(Class location) {
    String ln = location.getPackage().getName();
    String p = System.getProperty(PKGS);
    boolean add = p == null || !p.contains(ln);
    if (add) {
      p = (CommonUtils.isEmptyTrimmed(p) ? "" : p + "|") + ln;
      System.setProperty(PKGS, p);
    }
    return add;
  }

  public static Class getClassForName(String name) {
    Class result = null;
    try {
      result = name == null ? null : Class.forName(name);
    }
    catch (ClassNotFoundException e) { // NOPMD
      // Ignored
    }
    return result;
  }

  /**
   * Gets a ConfigDataSource for the given path. It could be from a URL, from a file, from the classpath, directory, or
   * from ldap (eventually). Note that the data source could represent multiple items (e.g. in the case of a folder).
   * 
   * @param path
   *            the path to the datasource.
   * @return the ConfigDataSource
   * @throws ConfigException
   *             in case of any problem getting the data source.
   */
  public static ConfigDataSource getConfigDataSource(String path) throws ConfigException {
    if (new File(path).isDirectory())
      return new ConfigDirectory(path, null);

    return new ConfigFile(path);
  }

  /**
   * Gets an individual ConfigStream (an InputStream and its location string) for the given path. The path reference
   * must be to a single item, not a folder.
   * 
   * @param path
   *            the path to the config stream.
   * @return the ConfigStream
   * @throws ConfigException
   *             in case of any problem, including if path is a folder.
   */
  public static ConfigDataSource.ConfigStream getConfigStream(String path) throws ConfigException {
    ConfigDataSource source = getConfigDataSource(path);
    try {
      if (source.isFolder())
        throw new ConfigException("more than one stream found");
    }
    catch (IOException e) {
      throw new ConfigException("cannot get stream: " + e, e);
    }
    Iterator ii = source.iterator();
    return ii.hasNext() ? ii.next() : null;
  }

  /**
   * Expands a string with an initial variable. The form of the string should be "${VARIABLE}remainder", where VARIABLE
   * is either a System property or an environment variable (checked in that order).
   * 
   * @param theString
   * @return the string with any initial property expanded
   */
  public static String getInitialPropertyExpanded(String theString) {
	  Pattern pattern = Pattern.compile("\\$\\{([A-Z_a-z0-9.]+)\\}");
	  Matcher matcher = pattern.matcher(theString);
	  while (matcher.find()) {
	      String strVar = matcher.group(1);
	      String strValue = System.getProperty(strVar);
	      if (strValue == null)
	    	  strValue = System.getenv(strVar);
	      if (strValue == null)
	    	  throw new RuntimeException("string value not available for '" + theString + "'");
	      theString = matcher.replaceFirst(strValue.replaceAll("\\\\", "/"));
	      matcher = pattern.matcher(theString);
	  }
	  return theString;
  }

  /**
   * Gets a property from a java Properties, or a system property or process environment variable value, in that order.
   * If none is found, null is returned.
   * 
   * @param properties
   *            the Properties object
   * @param key
   *            the string name of the property or environment variable.
   * @return the property or environment value, or null if none was found.
   */
  public static String getPropOrEnv(Properties properties, String key) {
    String it = properties.getProperty(key);
    return it == null ? getPropOrEnv(key) : it;
  }

  /**
   * Gets a java system property or process environment variable value, in that order. If none is found, null is
   * returned.
   * 
   * @param key
   *            the string name of the property or environment variable.
   * @return the property or environment value, or null if none was found.
   */
  public static String getPropOrEnv(String key) {
    String it = System.getProperty(key);
    if (it == null)
      it = System.getenv(key);
    return it;
  }

  public static Object getValueForType(Class type, String value) throws ConfigException {
    if (String.class.isAssignableFrom(type))
      return value;
    if (Long.class.isAssignableFrom(type) || long.class.isAssignableFrom(type))
      return Long.decode(value);
    if (Integer.class.isAssignableFrom(type) || int.class.isAssignableFrom(type))
      return Integer.decode(value);
    if (Double.class.isAssignableFrom(type) || double.class.isAssignableFrom(type))
      return Double.valueOf(value);
    if (Boolean.class.isAssignableFrom(type) || boolean.class.isAssignableFrom(type))
      return Boolean.valueOf(value);
    throw new ConfigException("Cannot convert " + value + " to " + type.getName());
  }

  /**
   * Sets properties for java.util.logging.
   * 
   * @param theProperties
   *            the logging properties.
   */
  public static void setLoggingProperties(Properties theProperties) throws IOException {
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    ByteArrayInputStream is;
    byte[] buffer;
    theProperties.store(os, "LoggingProperties");
    buffer = os.toByteArray();
    is = new ByteArrayInputStream(buffer);
    LogManager.getLogManager().readConfiguration(is);
  }

  public static void setProperties(Object theTarget, Properties theProperties) throws ConfigException {
    Class clazz = theTarget.getClass();
    Method[] methods = clazz.getMethods();
    for (Object key : theProperties.keySet()) {
      if (!(key instanceof String))
        continue;
      String property = (String) key;
      String setter = "set" + (property.startsWith("is") ? property.substring(2) : property);
      for (int i = 0; i < methods.length; i++) {
        Class[] formals = methods[i].getParameterTypes();
        if (formals.length == 1 && setter.equalsIgnoreCase(methods[i].getName())) {
          Object value = getValueForType(formals[0], theProperties.getProperty(property));
          try {
            // Pretty dumb now - doesn't handle overloads or many type conversions
            methods[i].invoke(theTarget, new Object[] { value });
            i = methods.length;
            setter = null;
          }
          catch (Throwable t) {
            throw new ConfigException("Cannot set property " + property + " to value " + value, t);
          }
        } // if a matching setter
      } // for methods
      if (setter != null)
        LOGGER.warn( "No such property found: " + key + " in " + theTarget);
    } // for property keys
  }

  /**
   * Sets the System properties for those given to the new values, and adds properties that do not exist.
   * 
   * @param theProperties
   *            the set of properties to add and update.
   */
  public static void setSystemProperties(Properties theProperties) {
    for (Map.Entry entry : theProperties.entrySet())
      System.setProperty(entry.getKey().toString(), entry.getValue().toString());
  }

  /**
   * Sets the System properties for those given to the new values, and adds properties that do not exist. Expands any
   * initial dollar-bracket-name-bracket sequence with its environment variable or pre-existing system property value.
   * 
   * @param theProperties
   *            the set of properties to add and update.
   */
  public static void setSystemPropertiesExpanded(Properties theProperties) {
    for (Map.Entry entry : theProperties.entrySet())
      System.setProperty(entry.getKey().toString(), getInitialPropertyExpanded(entry.getValue().toString()));
  }

  /**
   * Writes a text file from a list of lines to a file by the given name and path. The path can optionally be prefixed
   * with a ${system.property}.
   * 
   * @param theName
   *            the file name, with optional System property prefix.
   * @param theContents
   *            List of content lines.
   * @throws IOException
   */
  public static void writeTextFile(String theName, List theContents) throws IOException {
    theName = getInitialPropertyExpanded(theName);
    File file = new File(theName);
    if (file.isFile() && !file.delete()) {
        throw new IOException("Failed to delete " + file.getCanonicalFile());
    }
    PrintWriter writer = new PrintWriter(file);
    try {
      for (Iterator ii = theContents.iterator(); ii.hasNext();)
        writer.println(ii.next());
    }
    finally {
      writer.close();
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy