com.xceptance.common.util.PropertiesUtils Maven / Gradle / Ivy
/*
* Copyright (c) 2005-2022 Xceptance Software Technologies GmbH
*
* 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.xceptance.common.util;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.VFS;
/**
* The PropertiesUtils helps in dealing with properties files.
*
* @author Jörg Werner (Xceptance Software Technologies GmbH)
*/
public final class PropertiesUtils
{
/**
* Default constructor. Declared private to prevent external instantiation.
*/
private PropertiesUtils()
{
}
/**
* Start delimiter for variable name.
*/
private static final String DELIMITER_START = "${";
/**
* End delimiter for variable name.
*/
private static final String DELIMITER_STOP = "}";
/**
* Loads the properties from the given file and returns them as a Properties object.
*
* @param file
* the properties file
* @return the resulting Properties object
* @throws IOException
* if an I/O error occurs
*/
public static Properties loadProperties(final File file) throws IOException
{
ParameterCheckUtils.isReadableFile(file, "file");
return loadProperties(VFS.getManager().toFileObject(file));
}
/**
* Loads the properties from the given file and puts them into the specified Properties object.
*
* @param file
* the properties file
* @param props
* the properties object to load the properties into
* @throws IOException
* if an I/O error occurs
*/
public static void loadProperties(final File file, final Properties props) throws IOException
{
ParameterCheckUtils.isReadableFile(file, "file");
ParameterCheckUtils.isNotNull(props, "props");
loadProperties(VFS.getManager().toFileObject(file), props);
}
/**
* Loads the properties from the given file and returns them as a Properties object.
*
* @param file
* the properties file
* @return the resulting Properties object
* @throws IOException
* if an I/O error occurs
*/
public static Properties loadProperties(final FileObject file) throws IOException
{
final Properties props = new Properties();
loadProperties(file, props);
return props;
}
/**
* Loads the properties from the given file and puts them into the specified Properties object.
*
* @param file
* the properties file
* @param props
* the properties object to load the properties into
* @throws IOException
* if an I/O error occurs
*/
public static void loadProperties(final FileObject file, final Properties props) throws IOException
{
ParameterCheckUtils.isReadableFile(file, "file");
ParameterCheckUtils.isNotNull(props, "props");
try (final InputStream is = file.getContent().getInputStream())
{
props.load(is);
}
}
/**
* Perform variable substitution in string value
from the values of keys found in the system
* properties.
*
* The variable substitution delimiters are ${ and }.
*
* For example, if the System properties contains "key=value", then the call
*
*
* String s = OptionConverter.substituteVars("Value of key is ${key}.");
*
*
* will set the variable s
to "Value of key is value.".
*
* If no value could be found for the specified key, then the props
parameter is searched, if the value
* could not be found there, then substitution defaults to the empty string.
*
* For example, if system properties contains no value for the key "inexistentKey", then the call
*
*
* String s = OptionConverter.subsVars("Value of nonexistentKey is [${nonexistentKey}]");
*
*
* will set s
to "Value of nonexistentKey is []"
*
* An {@link java.lang.IllegalArgumentException} is thrown if value
contains a start delimiter "${"
* which is not balanced by a stop delimiter "}".
*
*
* @param value
* the string on which variable substitution is performed
* @param properties
* properties object to be used for variable lookup
* @return argument string where variable have been substituted
* @throws IllegalArgumentException
* if value
is malformed
*/
public static String substituteVariables(final String value, final Properties properties) throws IllegalArgumentException
{
// parameter validation
ParameterCheckUtils.isNotNull(value, "value");
ParameterCheckUtils.isNotNull(properties, "props");
if (value.length() == 0 || properties.size() == 0)
{
return value;
}
// recursively resolve the variables in the value
return resolveVariables(value, properties, new HashSet());
}
/**
* Resolves the given value as variable reference using the given properties object and set of already known
* variables.
*
* @param value
* variable reference to be resolved
* @param props
* properties object to be used to resolve the variable reference
* @param variables
* set of already known variables in current lookup path
* @return resolved variable reference
*/
private static String resolveVariables(final String value, final Properties props, final Set variables)
{
String result = value;
// list of all variable reference matches
final List matches = RegExUtils.getAllMatches(value, RegExUtils.escape(DELIMITER_START) + "(.*?)" +
RegExUtils.escape(DELIMITER_STOP),
1);
// loop through variable references
for (final String key : matches)
{
if (variables.contains(key))
{
continue;
}
// add found variable to set of known variables in order to
// prevent cyclic lookup paths
variables.add(key);
// resolve variable
// 1st: Try to get value using system properties
String substitution = System.getProperty(key, null);
if (substitution == null)
{
// 2nd: Try to get value using passed properties
substitution = props.getProperty(key);
if (substitution == null)
{
// 3rd: Try to get value using system environment
substitution = System.getenv(key);
}
}
if (substitution != null)
{
// recursively replace any variable in the substitution string
substitution = resolveVariables(substitution, props, new HashSet(variables));
// replace variable reference with its substitution value
result = RegExUtils.replaceAll(result, RegExUtils.escape(DELIMITER_START + key + DELIMITER_STOP),
Matcher.quoteReplacement(substitution));
}
}
return result;
}
/**
* Returns all properties for this domain key, strips the key from the property name, e.g.
* ClassName.Testproperty=ABC --> TestProperty=ABC Attention: Properties without a domain (e.g. foobar=test) or
* domain only properties are invalid and will be ignored. A property has to have at least this form:
* domain.propertyname=value
*
* @param domainKey
* domain for the properties
* @param properties
* the properties from which to return the matching entries
* @return map with all key value pairs of properties
*/
public static Map getPropertiesForKey(final String domainKey, final Properties properties)
{
// initialize map
final Map result = new HashMap();
// maybe we are finished yet
if (domainKey == null || domainKey.isEmpty())
{
return result;
}
// assemble prefix: append a dot to the domainKey if it does not end
// with a dot
final String prefix = domainKey.endsWith(".") ? domainKey : domainKey + ".";
// go through all property entries
for (final Entry