org.jtester.module.utils.ConfigurationLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.jtester.module.utils.ConfigurationLoader.java

Source

/*
 * Copyright 2008,  Unitils.org
 *
 * 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 org.jtester.module.utils;

import java.util.Properties;

import org.apache.commons.lang.text.StrSubstitutor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jtester.exception.JTesterException;

/**
 * Utility that loads the configuration of unitils.
 * <p/>
 * Unitils settings can be defined in 3 files and in the system properties:
 * <ul>
 * <li><b>unitils-default.properties</b> - a fixed file packaged in the unitils
 * jar that contains all predefined defaults. This file should normally not be
 * modified.</li>
 * <li><b>unitils.properties</b> - a file somewhere in the classpath or
 * user.home dir that contains all custom configuration settings. Settings in
 * this file will override the default settings. This is where you should put
 * your project specific configuration</li>
 * <li><b>unitils-local.properties</b> - a file somewhere in the classpath or
 * user.home that contains machine/user local configuration. Eg the database
 * schema specific to the local user could be defined here. Settings in this
 * file will override the unitil default and custom settings.</li>
 * <li><b>system properties</b> - These settings override all other settings.</li>
 * </ul>
 * The name of the custom settings file (unitils.properties) is defined by the
 * {@link #PROPKEY_CUSTOM_CONFIGURATION} property in the default settings. The
 * name of the local settings file (unitils-local.propeties) is defined by the
 * {@link #PROPKEY_LOCAL_CONFIGURATION} in the custom or default settings. If
 * these properties are set to null or empty, the corresponding property file
 * will not be loaded.
 * <p/>
 * A runtime exception is thrown when the default properties cannot be loaded. A
 * warning is logged when the custom propreties cannot be loaded. A debug
 * message is logged when the local properties cannot be loaded.
 * <p/>
 * Ant-like property place holders, e.g. ${holder} will be expanded if needed
 * all property place holders to actual values. For example suppose you have a
 * property defined as follows: root.dir=/usr/home Expanding following
 * ${root.dir}/somesubdir will then give following result: /usr/home/somesubdir
 * 
 * @author Tim Ducheyne
 * @author Filip Neven
 * @author Fabian Krueger
 */
public class ConfigurationLoader {

    /**
     * Name of the fixed configuration file that contains all defaults
     */
    public static final String DEFAULT_PROPERTIES_FILE_NAME = "unitils-default.properties";

    /**
     * Property in the defaults configuration file that contains the name of the
     * custom configuration file
     */
    public static final String PROPKEY_CUSTOM_CONFIGURATION = "unitils.configuration.customFileName";

    /**
     * Property in the defaults and/or custom configuration file that contains
     * the name of the user local configuration file
     */
    public static final String PROPKEY_LOCAL_CONFIGURATION = "unitils.configuration.localFileName";

    /* The logger instance for this class */
    private static Log logger = LogFactory.getLog(ConfigurationLoader.class);

    /**
     * reads properties from configuration file
     */
    private PropertiesReader propertiesReader = new PropertiesReader();

    /**
     * Creates and loads all configuration settings.
     * 
     * @return the settings, not null
     */
    public Properties loadConfiguration() {
        Properties properties = new Properties();

        loadDefaultConfiguration(properties);
        loadCustomConfiguration(properties);
        loadLocalConfiguration(properties);
        loadSystemProperties(properties);
        expandPropertyValues(properties);
        return properties;
    }

    /**
     * Load the default properties file that is distributed with unitils
     * (unitils-default.properties)
     * 
     * @param properties
     *            The instance to add to loaded properties to, not null
     */
    protected void loadDefaultConfiguration(Properties properties) {
        Properties defaultProperties = propertiesReader
                .loadPropertiesFileFromClasspath(DEFAULT_PROPERTIES_FILE_NAME);
        if (defaultProperties == null) {
            throw new JTesterException(
                    "Configuration file: " + DEFAULT_PROPERTIES_FILE_NAME + " not found in classpath.");
        }
        properties.putAll(defaultProperties);
    }

    /**
     * Load the custom project level configuration file (unitils.properties)
     * 
     * @param properties
     *            The instance to add to loaded properties to, not null
     */
    protected void loadCustomConfiguration(Properties properties) {
        String customConfigurationFileName = getConfigurationFileName(PROPKEY_CUSTOM_CONFIGURATION, properties);
        Properties customProperties = propertiesReader.loadPropertiesFileFromClasspath(customConfigurationFileName);
        if (customProperties == null) {
            logger.warn("No custom configuration file " + customConfigurationFileName + " found.");
        } else {
            properties.putAll(customProperties);
        }
    }

    /**
     * Load the local configuration file from the user home, or from the
     * classpath
     * 
     * @param properties
     *            The instance to add to loaded properties to, not null
     */
    protected void loadLocalConfiguration(Properties properties) {
        String localConfigurationFileName = getConfigurationFileName(PROPKEY_LOCAL_CONFIGURATION, properties);
        Properties localProperties = propertiesReader.loadPropertiesFileFromUserHome(localConfigurationFileName);
        if (localProperties == null) {
            localProperties = propertiesReader.loadPropertiesFileFromClasspath(localConfigurationFileName);
        }
        if (localProperties == null) {
            logger.info("No local configuration file " + localConfigurationFileName + " found.");
        } else {
            properties.putAll(localProperties);
        }
    }

    /**
     * Load the environment properties.
     * 
     * @param properties
     *            The instance to add to loaded properties to, not null
     */
    protected void loadSystemProperties(Properties properties) {
        properties.putAll(System.getProperties());
    }

    /**
     * Expands all property place holders to actual values. For example suppose
     * you have a property defined as follows: root.dir=/usr/home Expanding
     * following ${root.dir}/somesubdir will then give following result:
     * /usr/home/somesubdir
     * 
     * @param properties
     *            The properties, not null
     */
    protected void expandPropertyValues(Properties properties) {
        for (Object key : properties.keySet()) {
            Object value = properties.get(key);
            try {
                String expandedValue = StrSubstitutor.replace(value, properties);
                properties.put(key, expandedValue);
            } catch (Exception e) {
                throw new JTesterException(
                        "Unable to load unitils configuration. Could not expand property value for key: " + key
                                + ", value " + value,
                        e);
            }
        }

    }

    /**
     * Gets the configuration file name from the system properties or if not
     * defined, from the given loaded properties. An exception is raised if no
     * value is defined.
     * 
     * @param propertyName
     *            The name of the property that defines the local/custom file
     *            name, not null
     * @param properties
     *            The propertis that were already loaded, not null
     * @return The property value, not null
     */
    protected String getConfigurationFileName(String propertyName, Properties properties) {
        String configurationFileName = System.getProperty(propertyName);
        if (configurationFileName != null) {
            return configurationFileName;
        }
        return PropertyUtils.getString(propertyName, properties);
    }
}