PropertiesHelper.java Source code

Java tutorial

Introduction

Here is the source code for PropertiesHelper.java

Source

/**
 *  Copyright 2007 University Of Southern California
 *
 *  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.
 */

import java.io.IOException;
import java.util.Enumeration;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PropertiesHelper extends Properties {

    /**
     * Adds new properties to an existing set of properties while
     * substituting variables. This function will allow value
     * substitutions based on other property values. Value substitutions
     * may not be nested. A value substitution will be ${property.key},
     * where the dollar-brace and close-brace are being stripped before
     * looking up the value to replace it with. Note that the ${..}
     * combination must be escaped from the shell.
     *
     * @param b is the set of properties to add to existing properties.
     * @return the combined set of properties.
     */
    protected Properties addProperties(Properties b) {
        // initial
        // Properties result = new Properties(this);
        Properties sys = System.getProperties();
        Pattern pattern = Pattern.compile("\\$\\{[-a-zA-Z0-9._]+\\}");

        for (Enumeration e = b.propertyNames(); e.hasMoreElements();) {
            String key = (String) e.nextElement();
            String value = b.getProperty(key);

            // unparse value ${prop.key} inside braces
            Matcher matcher = pattern.matcher(value);
            StringBuffer sb = new StringBuffer();
            while (matcher.find()) {
                // extract name of properties from braces
                String newKey = value.substring(matcher.start() + 2, matcher.end() - 1);

                // try to find a matching value in result properties
                String newVal = getProperty(newKey);

                // if still not found, try system properties
                if (newVal == null) {
                    newVal = sys.getProperty(newKey);
                }

                // replace braced string with the actual value or empty string
                matcher.appendReplacement(sb, newVal == null ? "" : newVal);
            }
            matcher.appendTail(sb);
            setProperty(key, sb.toString());
        }
        return this;
    }

    /**
     * Adds new properties to an existing set of properties while
     * substituting variables. This function will allow value
     * substitutions based on other property values. Value substitutions
     * may not be nested. A value substitution will be ${property.key},
     * where the dollar-brace and close-brace are being stripped before
     * looking up the value to replace it with. Note that the ${..}
     * combination must be escaped from the shell.
     *
     * @param a is the initial set of known properties (besides System ones)
     * @param b is the set of properties to add to a
     * @return the combined set of properties from a and b.
     */
    protected static Properties addProperties(Properties a, Properties b) {
        // initial
        Properties result = new Properties(a);
        Properties sys = System.getProperties();
        Pattern pattern = Pattern.compile("\\$\\{[-a-zA-Z0-9._]+\\}");

        for (Enumeration e = b.propertyNames(); e.hasMoreElements();) {
            String key = (String) e.nextElement();
            String value = b.getProperty(key);

            // unparse value ${prop.key} inside braces
            Matcher matcher = pattern.matcher(value);
            StringBuffer sb = new StringBuffer();
            while (matcher.find()) {
                // extract name of properties from braces
                String newKey = value.substring(matcher.start() + 2, matcher.end() - 1);

                // try to find a matching value in result properties
                String newVal = result.getProperty(newKey);

                // if still not found, try system properties
                if (newVal == null) {
                    newVal = sys.getProperty(newKey);
                }

                // replace braced string with the actual value or empty string
                matcher.appendReplacement(sb, newVal == null ? "" : newVal);
            }
            matcher.appendTail(sb);
            result.setProperty(key, sb.toString());
        }
        // final
        return result;
    }

    public PropertiesHelper() {
        super();
    }

    public PropertiesHelper(Properties defaults) {
        super(defaults);
    }

    protected PropertiesHelper(String propFilename, Properties defaults)
            throws IOException, MissingResourceException {
        // create empty new instance
        super(defaults);
    }

    /**
     * Accessor: Overwrite any properties from within the program.
     *
     * @param key is the key to look up
     * @param value is the new property value to place in the system.
     * @return the old value, or null if it didn't exist before.
     */
    /**  public Object setProperty(String key, String value) {
        return System.setProperty(key, value);
      }
     **/
    /**
     * Accessor: access to the internal properties as read from file.
     * An existing system property of the same key will have precedence
     * over any project property. This method will remove leading and
     * trailing ASCII control characters and whitespaces.
     *
     * @param key is the key to look up
     * @return the value for the key, or null, if not found.
     */
    /** public String getProperty(String key) {
       String result =
     System.getProperty(key, this.m_props.getProperty(key));
       return (result == null ? result : result.trim());
     }
     **/
    /**
     * Accessor: access to the internal properties as read from file
     * An existing system property of the same key will have precedence
     * over any project property. This method will remove leading and
     * trailing ASCII control characters and whitespaces.
     *
     * @param key is the key to look up
     * @param defValue is a default to use, if no value can be found for the key.
     * @return the value for the key, or the default value, if not found.
     */
    /** public String getProperty(String key, String defValue) {
       String result =
     System.getProperty(key, this.m_props.getProperty(key, defValue));
       return (result == null ? result : result.trim());
     }
     **/
    /**
     * Extracts a specific property key subset from the known properties.
     * The prefix may be removed from the keys in the resulting dictionary,
     * or it may be kept. In the latter case, exact matches on the prefix
     * will also be copied into the resulting dictionary.
     *
     * @param prefix is the key prefix to filter the properties by.
     * @param keepPrefix if true, the key prefix is kept in the resulting
     * dictionary. As side-effect, a key that matches the prefix exactly
     * will also be copied. If false, the resulting dictionary's keys are
     * shortened by the prefix. An exact prefix match will not be copied,
     * as it would result in an empty string key.
     * @return a property dictionary matching the filter key. May be
     * an empty dictionary, if no prefix matches were found.
     *
     * @see #getProperty( String ) is used to assemble matches
     */
    public Properties matchingSubset(String prefix, boolean keepPrefix) {
        Properties result = new Properties();

        // sanity check
        if (prefix == null || prefix.length() == 0) {
            return result;
        }

        String prefixMatch; // match prefix strings with this
        String prefixSelf; // match self with this
        if (prefix.charAt(prefix.length() - 1) != '.') {
            // prefix does not end in a dot
            prefixSelf = prefix;
            prefixMatch = prefix + '.';
        } else {
            // prefix does end in one dot, remove for exact matches
            prefixSelf = prefix.substring(0, prefix.length() - 1);
            prefixMatch = prefix;
        }
        // POSTCONDITION: prefixMatch and prefixSelf are initialized!

        // now add all matches into the resulting properties.
        // Remark 1: #propertyNames() will contain the System properties!
        // Remark 2: We need to give priority to System properties. This is done
        // automatically by calling this class's getProperty method.
        String key;
        for (Enumeration e = propertyNames(); e.hasMoreElements();) {
            key = (String) e.nextElement();

            if (keepPrefix) {
                // keep full prefix in result, also copy direct matches
                if (key.startsWith(prefixMatch) || key.equals(prefixSelf)) {
                    result.setProperty(key, getProperty(key));
                }
            } else {
                // remove full prefix in result, dont copy direct matches
                if (key.startsWith(prefixMatch)) {
                    result.setProperty(key.substring(prefixMatch.length()), getProperty(key));
                }
            }
        }

        // done
        return result;
    }

    /**
     * Extracts a specific property key subset from the properties passed.
     * The prefix may be removed from the keys in the resulting dictionary,
     * or it may be kept. In the latter case, exact matches on the prefix
     * will also be copied into the resulting dictionary.
     *
     *
     * @param prefix is the key prefix to filter the properties by.
     * @param keepPrefix if true, the key prefix is kept in the resulting
     * dictionary. As side-effect, a key that matches the prefix exactly
     * will also be copied. If false, the resulting dictionary's keys are
     * shortened by the prefix. An exact prefix match will not be copied,
     * as it would result in an empty string key.
     * @return a property dictionary matching the filter key. May be
     * an empty dictionary, if no prefix matches were found.
     *
     * @see #getProperty( String ) is used to assemble matches
     */
    public static Properties matchingSubset(Properties properties, String prefix, boolean keepPrefix) {
        Properties result = new Properties();

        // sanity check
        if (prefix == null || prefix.length() == 0) {
            return result;
        }

        String prefixMatch; // match prefix strings with this
        String prefixSelf; // match self with this
        if (prefix.charAt(prefix.length() - 1) != '.') {
            // prefix does not end in a dot
            prefixSelf = prefix;
            prefixMatch = prefix + '.';
        } else {
            // prefix does end in one dot, remove for exact matches
            prefixSelf = prefix.substring(0, prefix.length() - 1);
            prefixMatch = prefix;
        }
        // POSTCONDITION: prefixMatch and prefixSelf are initialized!

        // now add all matches into the resulting properties.
        // Remark 1: #propertyNames() will contain the System properties!
        // Remark 2: We need to give priority to System properties. This is done
        // automatically by calling this class's getProperty method.
        String key;
        for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) {
            key = (String) e.nextElement();

            if (keepPrefix) {
                // keep full prefix in result, also copy direct matches
                if (key.startsWith(prefixMatch) || key.equals(prefixSelf)) {
                    result.setProperty(key, properties.getProperty(key));
                }
            } else {
                // remove full prefix in result, dont copy direct matches
                if (key.startsWith(prefixMatch)) {
                    result.setProperty(key.substring(prefixMatch.length()), properties.getProperty(key));
                }
            }
        }

        // done
        return result;
    }

}