Package com.google.api.ads.common.lib.conf

Source Code of com.google.api.ads.common.lib.conf.ConfigurationHelper

// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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.google.api.ads.common.lib.conf;

import com.google.api.ads.common.lib.utils.logging.AdsServiceLoggers;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;

import org.apache.commons.configuration.AbstractConfiguration;
import org.apache.commons.configuration.CombinedConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.MapConfiguration;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.tree.OverrideCombiner;

import java.io.File;
import java.net.URL;
import java.security.AccessControlException;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import javax.annotation.Nullable;

/**
* Helper class that loads {@link Configuration} from various sources.
*
* @author Kevin Winter
* @author Jeff Sham
* @author Adam Rogal
*/
public class ConfigurationHelper {

  /**
   * Loads configuration from a specified path. If not absolute, will look in
   * the user home directory, the current classpath and the system classpath.
   * Absolute classpath references will not work.
   *
   * @param path the path to try first as a resource, then as a file
   * @throws ConfigurationLoadException if the configuration could not be
   *         loaded.
   * @returns properties loaded from the specified path or null.
   */
  public Configuration fromFile(String path) throws ConfigurationLoadException {
    PropertiesConfiguration propertiesConfiguration = new PropertiesConfiguration();
    try {
      propertiesConfiguration.load(path);
    } catch (ConfigurationException e) {
      if (Throwables.getRootCause(e) instanceof AccessControlException){
        AdsServiceLoggers.ADS_API_LIB_LOG.debug("Properties could not be loaded.", e);
      } else {
        throw new ConfigurationLoadException(
            "Encountered a problem reading the provided configuration file \"" + path + "\"!", e);
      }
    }
    return propertiesConfiguration;
  }

  /**
   * Loads configuration from a specified path.
   *
   * @param path the path to try first as a resource, then as a file
   * @throws ConfigurationLoadException if the configuration could not be
   *         loaded.
   * @returns properties loaded from the specified path or null.
   */
  public Configuration fromFile(File path) throws ConfigurationLoadException {
    try {
      return new PropertiesConfiguration(path);
    } catch (ConfigurationException e) {
      throw new ConfigurationLoadException(
          "Encountered a problem reading the provided configuration file \"" + path + "\"!", e);
    }
  }

  /**
   * Loads configuration from a specified path.
   *
   * @param path the path to try first as a resource, then as a file
   * @throws ConfigurationLoadException if the configuration could not be
   *         loaded.
   * @returns properties loaded from the specified path or null.
   */
  public Configuration fromFile(URL path) throws ConfigurationLoadException {
    try {
      return new PropertiesConfiguration(path);
    } catch (ConfigurationException e) {
      throw new ConfigurationLoadException(
          "Encountered a problem reading the provided configuration file \"" + path + "\"!", e);
    }
  }

  /**
   * Loads configuration from system defined arguments, i.e. -Dapi.x.y.z=abc.
   */
  public Configuration fromSystem() {
    return new MapConfiguration((Properties) System.getProperties().clone());
  }

  /**
   * Creates the combined configuration. System properties will overwrite path
   * properties, which overwrite URL properties. The configuration is created
   * by:
   * <ol><li>Loading properties {@link #fromSystem() from the system}.</li>
   * <li>Loading properties from each path with lower indexed paths overwritting
   * higher indexed paths using {@link #fromFile(String)}.</li>
   * <li>Loading properties from each URL with lower indexed urls overwritting
   * higher indexed URLs using {@link #fromFile(URL)}.</li></ol>
   * @throws ConfigurationLoadException if any required configuration could not
   *         be loaded
   */
  public CombinedConfiguration createCombinedConfiguration(
      @Nullable List<ConfigurationInfo<String>> paths,
      @Nullable List<ConfigurationInfo<URL>> urls) throws ConfigurationLoadException {
    CombinedConfiguration combinedConfiguration = new CombinedConfiguration(new OverrideCombiner());

    // System configuration will override all other configurations.
    addConfiguration(combinedConfiguration, fromSystem());

    // Classpath and file path configurations will override URL configurations.
    if (paths != null) {
      for (ConfigurationInfo<String> path : paths) {
        if (path != null && path.getLocation() != null) {
          try {
            addConfiguration(combinedConfiguration, fromFile(path.getLocation()));
          } catch (ConfigurationLoadException e) {
            if (!path.isOptional) {
              throw e;
            } else {
              AdsServiceLoggers.ADS_API_LIB_LOG.debug("Did not load optional configuration "
                  + path.getLocation() + ":", e);
            }
          }
        }
      }
    }

    if (urls != null) {
      for (ConfigurationInfo<URL> url : urls) {
        if (url != null && url.getLocation() != null) {
          try {
            addConfiguration(combinedConfiguration, fromFile(url.getLocation()));
          } catch (ConfigurationLoadException e) {
            if (!url.isOptional) {
              throw e;
            } else {
              AdsServiceLoggers.ADS_API_LIB_LOG.debug(
                  "Did not load optional configuration" + url.getLocation() + ":", e);
            }
          }
        }
      }
    }
    return combinedConfiguration;
  }

  /**
   * Adds a configuration to the combined configuration, overwriting any
   * existing properties.
   */
  @VisibleForTesting
  void addConfiguration(CombinedConfiguration combinedConfiguration,
      final Configuration configuration) {
    if (configuration instanceof AbstractConfiguration) {
      combinedConfiguration.addConfiguration((AbstractConfiguration) configuration);
    } else {
      combinedConfiguration.addConfiguration(new AbstractConfiguration() {

        public boolean isEmpty() {
          return configuration.isEmpty();
        }

        public Object getProperty(String key) {
          return configuration.getProperty(key);
        }

        @SuppressWarnings("rawtypes") // No rawtype in class.
        public Iterator getKeys() {
          return configuration.getKeys();
        }

        public boolean containsKey(String key) {
          return configuration.containsKey(key);
        }

        @Override
        protected void addPropertyDirect(String key, Object value) {
          configuration.addProperty(key, value);
        }
      });
    }
  }

  /**
   * Creates a list of configuration infos from the locations and if they are
   * optional. A {@code null} locations will return {@code null}
   *
   * @param <T> the type of location. Only {@code String} and {@code URL} are
   *            supported.
   */
  public static <T> List<ConfigurationInfo<T>> newList(@Nullable List<T> locations,
      final boolean isOptional) {
    if (locations == null) {
      return null;
    }

    return Lists.transform(locations, new Function<T, ConfigurationInfo<T>>() {
      public ConfigurationInfo<T> apply(T input) {
        return new ConfigurationInfo<T>(input, isOptional);
      }
    });
  }

  /**
   * Creates a list of configuration infos from the locations and if they are
   * optional.
   *
   * @param <T> the type of location. Only {@code String} and {@code URL} are
   *            supported.
   */
  public static <T> List<ConfigurationInfo<T>> newList(boolean isOptional, T... locations) {
    if (locations == null) {
      throw new IllegalArgumentException("locations cannot be null");
    }
    return newList(Lists.<T>newArrayList(locations), isOptional);
  }

  /**
   * Information about the configuration.

   * @param <T> the location type
   */
  public static class ConfigurationInfo<T> {

    private final T location;
    private final boolean isOptional;

    /**
     * Constructor.
     *
     * @param location the location (String for file path or {@code URL}) of the
     *        properties file
     * @param isOptional {@code true} if no exception should be thrown if it
     *        can't be loaded.
     * @throws IllegalArgumentException if location is anything but {@code String}
     *         or {@code URL}.
     */
    public ConfigurationInfo(T location, boolean isOptional) {
      if (!(location instanceof String || location instanceof URL)) {
        throw new IllegalArgumentException("Type " + location.getClass()
            + " not supported as a configuration location.");
      }
      this.location = location;
      this.isOptional = isOptional;
    }

    public T getLocation() {
      return location;
    }

    public boolean isOptional() {
      return isOptional;
    }
  }
}
TOP

Related Classes of com.google.api.ads.common.lib.conf.ConfigurationHelper

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.