blob: 4985240ed57e0c8340177e1f7d162fc99447c6b1 [file] [log] [blame]
<?xml version="1.0"?>
<!--
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.
-->
<document>
<properties>
<title>Basic Features</title>
<author email="oheger@apache.org">Oliver Heger</author>
</properties>
<body>
<section name="Basic features and AbstractConfiguration">
<p>
The <code>Configuration</code> interface defines a whole bunch of methods.
Implementing these methods all from scratch can be quite hard. Because of
that the <code><a href="../apidocs/org/apache/commons/configuration2/AbstractConfiguration.html">
AbstractConfiguration</a></code> class exists. This class serves as a
common base class for most of the <code>Configuration</code> implementations
in <em>Commons Configuration</em> and provides a great deal of the
functionality required by the interface. So for creating a custom
<code>Configuration</code> implementation this class will be a good
starting point.
</p>
<p>
In addition to base implementations for lots of the methods declared in
the <code>Configuration</code> interface the <code>AbstractConfiguration</code>
class provides some other handy and convenient features. Because this
class is at the very root of the class hierarchy in <em>Commons
Configuration</em> these features are available in most of the specific
implementations of the <code>Configuration</code> interface provided by
this library. We will cover some of these basic features in this section.
</p>
<subsection name="Handling of missing properties">
<p>
What is a configuration object supposed to do if you pass in a key to one
of its get methods that does not map to an existing property? Well, the
default behavior as implemented in <code>AbstractConfiguration</code> is
to return <b>null</b> if the return value is an object type. For primitive
types as return values returning <b>null</b> (or any other special
value) is not possible, so in this case a <code>NoSuchElementException</code>
is thrown:
</p>
<source><![CDATA[
// This will return null if no property with key "NonExistingProperty" exists
String strValue = config.getString("NonExistingProperty");
// This will throw a NoSuchElementException exception if no property with
// key "NonExistingProperty" exists
long longValue = config.getLong("NonExistingProperty");
]]></source>
<p>
For object types like <code>String</code>, <code>BigDecimal</code>, or
<code>BigInteger</code> this default behavior can be changed: If the
<code>setThrowExceptionOnMissing()</code> method is called with an
argument of <b>true</b>, these methods will behave like their primitive
counter parts and also throw an exception if the passed in property key
cannot be resolved.
</p>
<p>
<em>Note:</em> Unfortunately support for the <code>throwExceptionOnMissing</code>
property is not always consistent: The methods <code>getList()</code> and
<code>getStringArray()</code> do not evaluate this flag, but return an
empty list or array if the requested property cannot be found. Maybe this
behavior will be changed in a future major release.
</p>
</subsection>
<subsection name="List handling">
<p>
With <code>getList()</code> and <code>getStringArray()</code> the
<code>Configuration</code> interface defines methods for dealing with
properties that have multiple values. When a configuration source (e.g.
a properties file, an XML document, or a JNDI context) is processed the
corresponding <code>Configuration</code> implementation detects such
properties with multiple values and ensures that the data is correctly
stored.
</p>
<p>
When modifying properties the <code>addProperty()</code> and
<code>setProperty()</code> methods of <code>AbstractConfiguration</code>
also implement special list handling. The property value that is passed
to these methods can be a list or an array resulting in a property
with multiple values.
</p>
<p>
For some use cases it makes sense to treat string values in a special way.
For instance, some configuration formats do not support lists directly.
As an example, properties files can be used: they just consist of
key-value pairs, and there is no default syntax to assign multiple values
to a key. <code>AbstractConfiguration</code> supports a mechanism to split
strings at specific characters, so that effectively multiple values are
generated from a single string. To achieve this, an
<code>AbstractConfiguration</code> instance collaborates with an object
implementing the
<code><a href="../apidocs/org/apache/commons/configuration2/convert/ListDelimiterHandler.html">
ListDelimiterHandler</a></code> interface. This interface defines methods
for dealing with objects that may contain multiple values. Examples of
such complex objects are arrays, lists, and strings containing a specific
list delimiter. Depending on a concrete implementation of the
<code>ListDelimiterHandler</code> interface, these objects are treated in
a special way.
</p>
<p>
Per default, <code>AbstractConfiguration</code> uses an instance of the
<code><a href="../apidocs/org/apache/commons/configuration2/convert/DisabledListDelimiterHandler.html">
DisabledListDelimiterHandler</a></code> class as list handler. This
class can deal with lists and arrays, but it does not recognize any list
delimiter characters in strings. (Hence the name, as splitting of strings
at list delimiters is disabled.)
</p>
<p>
An alternative implementation of <code>ListDelimiterHandler</code> is
<code><a href="../apidocs/org/apache/commons/configuration2/convert/DefaultListDelimiterHandler.html">
DefaultListDelimiterHandler</a></code>. This class actually supports
string splitting; the list delimiter character has to be passed to the
constructor. Whenever a property is added to the configuration (or the
configuration is loaded from its source), it is checked whether the
property value is a string and - if so - if it contains the list
delimiter character. In this case, the string is split, and its single
parts are added one by one. By using the <code>setListDelimiterHandler()</code>
method you can set a specific list handler implementation. Here are some
examples:
</p>
<source>
// Enable list delimiter handling using a slash as delimiter character
config.setListDelimiterHandler(new DefaultListDelimiterHandler('/'));
// Now add some properties
config.addProperty("greeting", "Hello, how are you?");
config.addProperty("colors.pie",
new String[] { "#FF0000", "#00FF00", "#0000FF" });
config.addProperty("colors.graph", "#808080/#00FFCC/#6422FF");
// Access data
String salut = config.getString("greeting");
List&lt;Object&gt; colPie = config.getList("colors.pie");
String[] colGraph = config.getStringArray("colors.graph");
String firstPieColor = config.getString("colors.pie");
</source>
<p>
In this example splitting of strings is enabled using the slash character
as delimiter. Because this character is not contained in the
<code>greeting</code> property it won't be split, but remains a single
string. In contrast, the string passed as value for the
<code>colors.graph</code> property contains the delimiter character and
thus will result in a property with three values. Note that the
version of the <code>getList()</code> method used here returns lists of type
<code>Object</code>. This is because the concrete class of the values of a
property is not known. For instance, if you call
<code>addProperty(&quot;answer&quot;, 42)</code>, an
<code>Integer</code> object will be stored in the configuration. However,
there are overloaded versions of <code>getList()</code> supporting a
data type conversion to a specific target class (see below).
</p>
<p>
Of interest is also the last line of the example fragment. Here the
<code>getString()</code> method is called for a property that has
multiple values. This call will return the first value of the list.
</p>
<p>
One word of warning at the end: Be careful when changing the list
delimiter handler on a configuration which already contains values. List
handling is typically applied already when properties are added to the
configuration. If later another handler is set which processes lists
differently, results may be unexpected; some operations may even cause
exceptions!
</p>
</subsection>
<subsection name="Variable Interpolation">
<p>
If you are familiar with Ant or Maven, you have most certainly already encountered
the variables (like <code>${token}</code>) that are automatically expanded when the
configuration file is loaded. Commons Configuration supports this feature as well,
here is an example (we use a properties file in this example, but other
configuration sources work the same way; you can learn more about
properties files in the chapter <a href="howto_properties.html">Properties
files</a>):
</p>
<source>
application.name = Killer App
application.version = 1.6.2
application.title = ${application.name} ${application.version}
</source>
<p>
If you now retrieve the value for the <code>application.title</code>
property, the result will be <code>Killer App 1.6.2</code>. So per default
variables are interpreted as the keys of other properties. This is only a
special case, the general syntax of a variable name is
<code>${prefix:name}</code>. The prefix tells Commons Configuration that
the variable is to be evaluated in a certain context. We have already seen
that the context is the current configuration instance if the prefix is
missing. The following other prefix names are supported by default:
<table border="1">
<tr>
<th>Prefix</th>
<th>Description</th>
</tr>
<tr>
<td valign="top">sys</td>
<td>This prefix marks a variable to be a system property. Commons
Configuration will search for a system property with the given name and
replace the variable by its value. This is a very easy means for
accessing the values of system properties in every configuration
implementation.</td>
</tr>
<tr>
<td valign="top">const</td>
<td>The <code>const</code> prefix indicates that a variable is to be
interpreted as a constant member field of a class (i.e. a field with the
<b>static final</b> modifiers). The name of the variable must be of the form
<code>&lt;full qualified class name&gt;.&lt;field name&gt;</code>. The
specified class will be loaded and the value of this field will be
obtained.</td>
</tr>
<tr>
<td valign="top">env</td>
<td>Variables can also reference OS-specific environment properties.
This is indicated by the <code>env</code> prefix.</td>
</tr>
</table>
Here are some examples (again using properties syntax):
</p>
<source><![CDATA[
user.file = ${sys:user.home}/settings.xml
action.key = ${const:java.awt.event.KeyEvent.VK_CANCEL}
java.home = ${env:JAVA_HOME}
]]></source>
<p>
Below is some more information related to variable interpolation users
should be aware of:
<ul>
<li>If a variable cannot be resolved, e.g. because the name is invalid
or an unknown prefix is used, it won't be replaced, but is returned as
is including the dollar sign and the curly braces.</li>
<li>References to variables can be nested; a variable can refer to a
variable which in turn can have references to other variables and so
on.</li>
<li>Cyclic references are detected. In this case, no interpolation is
done.</li>
<li>Variable interpolation happens when properties are queried from the
configuration, not at creation time. Therefore, the mechanism is quite
dynamic: changes on one property can impact the value of another
property that references the first one.</li>
<li>Variable interpolation is done by all property access methods. One
exception is the generic <code>getProperty()</code> method which
returns the raw property value.</li>
</ul>
</p>
</subsection>
<subsection name="Customizing interpolation">
<p>
This sub section goes a bit behind the scenes of interpolation and
explains some approaches how you can add your own interpolation facilities.
Under the hood the implementation of interpolation relies on objects
implementing the
<code><a href="../apidocs/org/apache/commons/configuration2/interpol/Lookup.html">
Lookup</a></code> interface. <code>Lookup</code> defines a simple
<code>lookup()</code> method that must be implemented by custom
implementations; it expects the name of a variable as argument and
returns the corresponding value. The standard prefixes for variables we
have covered so far are indeed provided by special classes implementing
<code>Lookup</code>.
</p>
<p>
It is now possible to create your own implementation of <code>Lookup</code>
and configure a <a href="howto_builder.html">configuration builder</a>
(builders are introduced in the next chapter of this user's guide) to
make it available for all configuration objects it creates under a custom
prefix. We will show how this can be achieved. The first step is to
create a new class implementing <code>Lookup</code>, which must
define the <code>lookup()</code> method. As an example we implement a
rather dull lookup object that simply returns a kind of &quot;echo&quot;
for the variable passed in:
</p>
<source><![CDATA[
import org.apache.commons.configuration2.interpol.Lookup;
public class EchoLookup implements Lookup
{
@Override
public Object lookup(String varName)
{
return "Value of variable " + varName;
}
}
]]></source>
<p>
Now we want this class to be called for variables with the prefix
<code>echo</code>. For this purpose the <code>EchoLookup</code> class
has to be registered at the
<code><a href="../apidocs/org/apache/commons/configuration2/interpol/ConfigurationInterpolator.html">
ConfigurationInterpolator</a></code> instance of our configuration with
the desired prefix. Each <code>Configuration</code> object is associated
with a <code>ConfigurationInterpolator</code> object that handles variable
interpolation. It manages the <code>Lookup</code> objects that should be
used to resolve variables.
</p>
<p>
There are multiple ways to make a <code>Lookup</code> object known to a
<code>ConfigurationInterpolator</code>. The most direct way is to call
the interpolator's <code>registerLookup()</code> method passing in the
<code>Lookup</code> and the desired prefix:
</p>
<source><![CDATA[
// simple, but not recommended approach
ConfigurationInterpolator interpolator = config.getInterpolator();
interpolator.registerLookup("echo", new EchoLookup());
]]></source>
<p>
This approach works, but has some drawbacks, especially when used with
advanced features like reloading of configurations. The recommended way
is to set custom lookup objects via the builder which creates the
configuration object; this ensures that every <code>Configuration</code>
instance created via the builder has a correctly initialized
<code>ConfigurationInterpolator</code> object. To achieve this, create
a map using the variable prefixes as keys and the associated
<code>Lookup</code> objects as values. This map can then be passed to the
<code>setPrefixLookup()</code> method of a parameters object for the
builder. Note that the lookups for the default prefixes are added
explicitly; omitting a lookup would remove support for the corresponding
prefix:
</p>
<source><![CDATA[
// Create a map with defaults and one additional lookup
Map<String, Lookup> lookups = new HashMap<String, Lookup>(
ConfigurationInterpolator.getDefaultPrefixLookups());
lookups.put("echo", new EchoLookup());
// Configure builder with lookups
Parameters params = new Parameters();
BasicConfigurationBuilder<PropertiesConfiguration> builder =
new BasicConfigurationBuilder<PropertiesConfiguration>(
PropertiesConfiguration.class)
.configure(params.basic()
.setPrefixLookups(lookups);
PropertiesConfiguration config = builder.getConfiguration();
]]></source>
</subsection>
<subsection name="Using Expressions">
<p>
In addition to the simple lookup mechanisms previously described, Commons Configuration
provides <code>ExprLookup</code> which uses <a href="https://commons.apache.org/jexl">Apache
Commons Jexl</a> to allow expressions to be resolved wherever a StrLookup is allowed. This
example shows an alternate way of obtaining a system property if the ExprLookup is
configured.
</p>
<source><![CDATA[
user.file = ${expr:System.getProperty("user.home")}/settings.xml
]]></source>
<p>
<code>ExprLookup</code> is not enabled by default, it must be manually added or configured via
<code>DefaultConfigurationBuilder</code>. Builds that use Maven 2 and reference Commons
Configuration will not include a dependency on Jexl, so if this feature is used the
dependency on Jexl must be manually added to the project.
</p>
<p>
When using <code>DefaultConfigurationBuilder</code> adding <code>ExprLookup</code> is
straightforward.
</p>
<source><![CDATA[
<configuration>
<header>
<result/>
<lookups>
<lookup config-prefix="expr"
config-class="org.apache.commons.configuration2.interpol.ExprLookup">
<variables>
<variable name="System" value="Class:java.lang.System"/>
<variable name"net" value="Class:java.net.InetAddress"/>
<variable name="String" value="Class:org.apache.commons.lang.StringUtils"/>
</variables>
</lookup>
</lookups>
</header>
<override>
<xml fileName="${expr:System.getProperty('basePath') +
String.lowercase(net.localHost.hostName) + '/testMultiConfiguration_default.xml'}"
config-name="defaultConfig" delimiterParsingDisabled="true">
</xml>
</override>
</configuration>
]]></source>
<p>
The example above shows how to invoke static methods during expression evaluation. The
next example shows mixing expression evaluation with a subordinate lookup to
obtain the "basePath" system property. Note the difference in how the
system property was obtained in the previous example.
</p>
<source><![CDATA[
<configuration>
<header>
<result/>
<lookups>
<lookup config-prefix="expr"
config-class="org.apache.commons.configuration2.interpol.ExprLookup">
<variables>
<variable name"net" value="Class:java.net.InetAddress"/>
<variable name="String" value="Class:org.apache.commons.lang.StringUtils"/>
</variables>
</lookup>
</lookups>
</header>
<override>
<xml fileName="${expr:$[sys:basePath] +
String.lowercase(net.localHost.hostName) + '/testMultiConfiguration_default.xml'}"
config-name="defaultConfig" delimiterParsingDisabled="true">
</xml>
</override>
</configuration>
]]></source>
</subsection>
<subsection name="Data type conversions">
<p>
As was already mentioned when discussing the
<code><a href="../apidocs/org/apache/commons/configuration2/Configuration.html">
Configuration</a></code> interface, there are various <code>get()</code>
methods returning property values in different target data types. If
necessary, a data type conversion is performed. Take a look at the
following example:
</p>
<source><![CDATA[
config.addProperty("answer", "42");
int theAnswer = config.getInt("answer");
]]></source>
<p>
Here a string value is assigned to the key <em>answer</em>. Then the
<code>getInt()</code> method is called to query this key as an integer
value. <code>getInt()</code> triggers a type conversion automatically.
If such a conversion is not possible, a runtime exception of type
<code>ConversionException</code> is thrown.
</p>
<p>
The <code>Configuration</code> interface defines a bunch of methods
returning property values in different data types. All of these methods
work in the same way: they obtain the actual value of the property and
attempt a data type conversion if necessary. In addition, there are
generic methods for accessing properties in specific data types:
<dl>
<dt>&lt;T&gt; get(Class&lt;T&gt; cls, String key);</dt>
<dd>Obtains the value of the specified property and tries to convert it
to the specified target type. If the key cannot be resolved, result is
<b>null</b>, or - if the <em>throwExceptionOnMissing</em> flag is set -
an exception is thrown.</dd>
<dt>&lt;T&gt; get(Class&lt;T&gt; cls, String key, T defValue);</dt>
<dd>Obtains the value of the specified property and tries to convert it
to the specified target type. If the key cannot be resolved, the
specified default value is returned (which may be <b>null</b>).</dd>
</dl>
In fact, all specialized <code>get()</code> methods are based on these
generic methods.
</p>
<p>
Generic conversion methods are also available for obtaining arrays or
collections. For instance, it is possible to obtain the value of a
property as an array of <b>int</b> or a list of <code>java.lang.Long</code>
objects. For arrays these conversions are directly supported by the generic
<code>get()</code> methods: if the target type passed to the method is an
array class, an array conversion is done automatically. So to obtain an
array of <strong>int</strong> from a configuration, the following code
can be used:
</p>
<source><![CDATA[
int[] result = config.getInt(int[].class, "myIntArrayKey");
]]></source>
<p>
For conversions to collections specific methods are provided (this is
necessary because the element type of the collection cannot be
determined automatically as in case of arrays). These are the following
ones:
<dl>
<dt>&lt;T&gt; List&lt;T&gt; getList(Class&lt;T&gt; cls, String key);</dt>
<dd>Returns a list of the specified element class.</dd>
<dt>&lt;T&gt; Collection&lt;T&gt; getCollection(Class&lt;T&gt; cls,
String key, Collection&lt;T&gt; target);</dt>
<dd>This method is similar to <code>getList()</code>, but it allows
specifying the target collection. This is useful if the result should
be stored in a different collection type, e.g. a set to remove
duplicates.</dd>
</dl>
</p>
<p>
These methods obtain all values stored for the property with the
passed in key. For each value a conversion to the desired target type is
performed. Then the resulting values are stored in the target array or
collection. There are also variants supporting default values.
</p>
<p>
It is worth to mention that data type conversion plays well together with
<a href="#Variable_Interpolation">variable interpolation</a>: Before a
data type conversion is attempted interpolation is handled first. Then
the resulting object is converted if necessary.
</p>
</subsection>
<subsection name="Customizing data type conversions">
<p>
<em>Commons Configuration</em> supports a number of conversions to
standard types out of the box. In addition to the result types of the
<code>get()</code> methods in the <code>Configuration</code> interface,
some more types are supported. These are listed in the documentation of the
<code><a href="../apidocs/org/apache/commons/configuration2/DataConfiguration.html">
DataConfiguration</a></code> class. <code>DataConfiguration</code> is a
<em>decorator</em> providing additional data type conversion methods for
more target types; these additional methods are implemented on top of the
generic conversion methods provided by <code>AbstractConfiguration</code>.
</p>
<p>
If your application deals with special objects, there may be the
requirement to extend the conversion capabilities offered by the
library. To support this use case, there is the
<code><a href="../apidocs/org/apache/commons/configuration2/convert/ConversionHandler.html">
ConversionHandler</a></code> interface. Each instance of a configuration
class derived from <code>AbstractConfiguration</code> is associated with
such a <code>ConversionHandler</code> object. The interface defines
methods for converting an object to a target class, and for converting
values to arrays or collections of a given element type. The data type
conversion methods implemented in <code>AbstractConfiguration</code>
delegate to this handler object.
</p>
<p>
The <code>ConversionHandler</code> interface gives a developer full
control over the whole data conversion process. By implementing the
different conversion methods, it is possible to integrate existing
conversion libraries (e.g. the converters offered by
<a href="https://commons.apache.org/proper/commons-beanutils/">Commons
BeanUtils</a>) with <em>Commons Configuration</em>.
</p>
<p>
If the conversion facilities provided by <em>Commons Configuration</em>
are not to be fully replaced, but only extended by some custom types,
the class <code><a href="../apidocs/org/apache/commons/configuration2/convert/DefaultConversionHandler.html">
DefaultConversionHandler</a></code> is a good starting point. As the name
implies, an instance of this class is used per default for doing type
conversions. <code>DefaultConversionHandler</code> has some protected
methods which can be overridden by subclasses in order to extend data type
conversions:
<dl>
<dt><code>convertValue()</code></dt>
<dd>This is the main conversion method for single values. It is called
when a single value is to be converted to a target type and also for
the single elements of arrays or collections. If a conversion to another
target class is to be supported, this is the method to override. A
custom implementation typically checks whether the desired target class
is one of the classes it supports. If this is the case, the passed in
source object is converted, and the result is returned. Otherwise, the
super method is called to handle standard conversions.</dd>
<dt><code>isComplexObject()</code></dt>
<dd>This boolean method determines whether a passed in object contains
multiple values. When doing a conversion to a target class
<code>DefaultConversionHandler</code> checks whether the source object
is a complex object like an array or a collection. If this is the case,
it first extracts the value to be converted from the source object
before it calls <code>convertValue()</code>.</dd>
<dt><code>extractConversionValue()</code></dt>
<dd><code>extractConversionValue()</code> is called if a complex object
(i.e. an object containing multiple values) is to be converted to a
single object (i.e. not an array or a collection). In this case, it is
not directly obvious how the multiple values should be handled. This
situation occurs for example if a client calls <code>getInt()</code>
on a property which actually has multiple values. The default
implementation of <code>extractConversionValue()</code> simply returns
the first value available. If an application needs a different
behavior, it can provide a custom implementation of this method.</dd>
<dt><code>convert()</code></dt>
<dd>This method contains the logic for converting a single value. It
delegates to the other methods discussed here. It first checks whether
the object to be converted is a complex one. If so, it extracts the
value to be converted. Eventually, it delegates to
<code>convertValue()</code> for performing the actual conversion. So
in order to gain more control over the whole conversion process, this
method is a good candidate for overriding.</dd>
</dl>
</p>
<p>
After a custom <code>ConversionHandler</code> implementation has been
created, it can be installed at a configuration instance by using the
<code>setConversionHandler()</code> method:
</p>
<source><![CDATA[
CustomConversionHandler handler = new CustomConversionHandler(...);
config.setConversionHandler(handler);
]]></source>
<p>
Another feature of <code>DefaultConversionHandler</code> is that is
allows defining the format for the conversion of <code>Date</code> and
<code>Calendar</code> objects. This can be done by calling
<code>setDateFormat()</code> with the corresponding date pattern. The
expected string argument must be a pattern string compatible with the
<code>java.text.SimpleDateFormat</code> class. If no date format was set,
the default pattern <code>yyyy-MM-dd HH:mm:ss</code> is used.
</p>
</subsection>
<subsection name="Encoded Properties">
<p>
Sometimes property values cannot be stored in plain text in configuration
files. For instance, security-related information like database passwords
should be encrypted. <em>Commons Configuration</em> does not provide
algorithms for encrypting (or otherwise encoding) properties. However,
there is a generic mechanism for automatically reading encoded properties
and transforming them into plain text before they are handed over to the
caller. A key role in this mechanism plays the
<code><a href="../apidocs/org/apache/commons/configuration2/ConfigurationDecoder.html">
ConfigurationDecoder</a></code> interface.
</p>
<p>
<code>ConfigurationDecoder</code> defines a single method <em>decode()</em>
which expects a string as input and returns a decoded string. It should be
easy for an application to provide a custom implementation for the
encoding algorithm it uses. The
<code><a href="../apidocs/org/apache/commons/configuration2/ImmutableConfiguration.html">
ImmutableConfiguration</a></code> interface defines two overloaded methods
for querying the values of encoded properties:
</p>
<source><![CDATA[
String getEncodedString(String key, ConfigurationDecoder decoder);
String getEncodedString(String key);
]]></source>
<p>
Both methods operate on string properties. Basically, the string value for
the passed in key is retrieved by delegating to <code>getString()</code>.
This value is then passed to a <code>ConfigurationDecoder</code> to
obtain the plain text value. One of these methods expects the
<code>ConfigurationDecoder</code> to be used as argument. The other
variant makes use of a decoder associated with this configuration. For
this purpose
<code><a href="../apidocs/org/apache/commons/configuration2/AbstractConfiguration.html">
AbstractConfiguration</a></code> offers a property named
<em>configurationDecoder</em>. Making use of this property simplifies
access to encoded properties: When the central configuration object is
created the decoder is initialized. Other parts of the application do not
need any knowledge about the decoding algorithm to be applied; rather, it
is sufficient to call the simple variant of <code>getEncodedString()</code>
to obtain a property value which can be processed immediately.
</p>
</subsection>
</section>
</body>
</document>