Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.commons.configuration2.interpol;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;
import org.apache.commons.text.StringSubstitutor;
/**
*
* A class that handles interpolation (variable substitution) for configuration objects.
*
*
* Each instance of {@code AbstractConfiguration} is associated with an object of this class. All interpolation tasks
* are delegated to this object.
*
*
* {@code ConfigurationInterpolator} internally uses the {@code StringSubstitutor} class from
* Commons Text. Thus it supports the same syntax of variable expressions.
*
*
* The basic idea of this class is that it can maintain a set of primitive {@link Lookup} objects, each of which is
* identified by a special prefix. The variables to be processed have the form {@code ${prefix:name}}.
* {@code ConfigurationInterpolator} will extract the prefix and determine, which primitive lookup object is registered
* for it. Then the name of the variable is passed to this object to obtain the actual value. It is also possible to
* define an arbitrary number of default lookup objects, which are used for variables that do not have a prefix or that
* cannot be resolved by their associated lookup object. When adding default lookup objects their order matters; they
* are queried in this order, and the first non-null variable value is used.
*
*
* After an instance has been created it does not contain any {@code Lookup} objects. The current set of lookup objects
* can be modified using the {@code registerLookup()} and {@code deregisterLookup()} methods. Default lookup objects
* (that are invoked for variables without a prefix) can be added or removed with the {@code addDefaultLookup()} and
* {@code removeDefaultLookup()} methods respectively. (When a {@code ConfigurationInterpolator} instance is created by
* a configuration object, a default lookup object is added pointing to the configuration itself, so that variables are
* resolved using the configuration's properties.)
*
*
* The default usage scenario is that on a fully initialized instance the {@code interpolate()} method is called. It is
* passed an object value which may contain variables. All these variables are substituted if they can be resolved. The
* result is the passed in value with variables replaced. Alternatively, the {@code resolve()} method can be called to
* obtain the values of specific variables without performing interpolation.
*
*
String Conversion
*
* When variables are part of larger interpolated strings, the variable values, which can be of any type, must be
* converted to strings to produce the full result. Each interpolator instance has a configurable
* {@link #setStringConverter(Function) string converter} to perform this conversion. The default implementation of this
* function simply uses the value's {@code toString} method in the majority of cases. However, for maximum
* consistency with
* {@link org.apache.commons.configuration2.convert.DefaultConversionHandler DefaultConversionHandler}, when a variable
* value is a container type (such as a collection or array), then only the first element of the container is converted
* to a string instead of the container itself. For example, if the variable {@code x} resolves to the integer array
* {@code [1, 2, 3]}, then the string "my value = ${x}" will by default be interpolated to
* {@code "my value = 1"}.
*
*
* Implementation note: This class is thread-safe. Lookup objects can be added or removed at any time
* concurrent to interpolation operations.
*
*
* @since 1.4
*/
public class ConfigurationInterpolator {
/**
* Internal class used to construct the default {@link Lookup} map used by
* {@link ConfigurationInterpolator#getDefaultPrefixLookups()}.
*/
static final class DefaultPrefixLookupsHolder {
/** Singleton instance, initialized with the system properties. */
static final DefaultPrefixLookupsHolder INSTANCE = new DefaultPrefixLookupsHolder(System.getProperties());
/**
* Add the prefix and lookup from {@code lookup} to {@code map}.
* @param lookup lookup to add
* @param map map to add to
*/
private static void addLookup(final DefaultLookups lookup, final Map map) {
map.put(lookup.getPrefix(), lookup.getLookup());
}
/**
* Create the lookup map used when the user has requested no customization.
* @return default lookup map
*/
private static Map createDefaultLookups() {
final Map lookupMap = new HashMap<>();
addLookup(DefaultLookups.BASE64_DECODER, lookupMap);
addLookup(DefaultLookups.BASE64_ENCODER, lookupMap);
addLookup(DefaultLookups.CONST, lookupMap);
addLookup(DefaultLookups.DATE, lookupMap);
addLookup(DefaultLookups.ENVIRONMENT, lookupMap);
addLookup(DefaultLookups.FILE, lookupMap);
addLookup(DefaultLookups.JAVA, lookupMap);
addLookup(DefaultLookups.LOCAL_HOST, lookupMap);
addLookup(DefaultLookups.PROPERTIES, lookupMap);
addLookup(DefaultLookups.RESOURCE_BUNDLE, lookupMap);
addLookup(DefaultLookups.SYSTEM_PROPERTIES, lookupMap);
addLookup(DefaultLookups.URL_DECODER, lookupMap);
addLookup(DefaultLookups.URL_ENCODER, lookupMap);
addLookup(DefaultLookups.XML, lookupMap);
return lookupMap;
}
/**
* Constructs a lookup map by parsing the given string. The string is expected to contain
* comma or space-separated names of values from the {@link DefaultLookups} enum.
* @param str string to parse; not null
* @return lookup map parsed from the given string
* @throws IllegalArgumentException if the string does not contain a valid default lookup
* definition
*/
private static Map parseLookups(final String str) {
final Map lookupMap = new HashMap<>();
try {
for (final String lookupName : str.split("[\\s,]+")) {
if (!lookupName.isEmpty()) {
addLookup(DefaultLookups.valueOf(lookupName.toUpperCase()), lookupMap);
}
}
} catch (final IllegalArgumentException exc) {
throw new IllegalArgumentException("Invalid default lookups definition: " + str, exc);
}
return lookupMap;
}
/** Default lookup map. */
private final Map defaultLookups;
/**
* Constructs a new instance initialized with the given properties.
* @param props initialization properties
*/
DefaultPrefixLookupsHolder(final Properties props) {
final Map lookups = props.containsKey(DEFAULT_PREFIX_LOOKUPS_PROPERTY)
? parseLookups(props.getProperty(DEFAULT_PREFIX_LOOKUPS_PROPERTY))
: createDefaultLookups();
defaultLookups = Collections.unmodifiableMap(lookups);
}
/**
* Gets the default prefix lookups map.
* @return default prefix lookups map
*/
Map getDefaultPrefixLookups() {
return defaultLookups;
}
}
/** Class encapsulating the default logic to convert resolved variable values into strings.
* This class is thread-safe.
*/
private static final class DefaultStringConverter implements Function