commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rgo...@apache.org
Subject svn commit: r764170 - in /commons/proper/configuration/branches/configuration2_experimental: ./ src/main/java/org/apache/commons/configuration2/ src/main/java/org/apache/commons/configuration2/beanutils/ src/main/java/org/apache/commons/configuration2/...
Date Sat, 11 Apr 2009 06:48:45 GMT
Author: rgoers
Date: Sat Apr 11 06:48:44 2009
New Revision: 764170

URL: http://svn.apache.org/viewvc?rev=764170&view=rev
Log:
CONFIGURATION-380 - Add expression evaluation during interpolation. Fix various bugs in VFS reloading and in multi file handling

Added:
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/interpol/ExprLookup.java   (with props)
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/TreeUtils.java   (with props)
    commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/interpol/TestExprLookup.java   (with props)
    commons/proper/configuration/branches/configuration2_experimental/src/test/resources/01/
    commons/proper/configuration/branches/configuration2_experimental/src/test/resources/01/testMultiConfiguration_1001.xml   (with props)
    commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testExpression.xml   (with props)
    commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testFileMonitorConfigurationBuilder.xml   (with props)
Modified:
    commons/proper/configuration/branches/configuration2_experimental/pom.xml
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/CombinedConfiguration.java
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/DefaultConfigurationBuilder.java
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/DynamicCombinedConfiguration.java
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/MultiFileHierarchicalConfiguration.java
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/VFSFileSystem.java
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/XMLConfiguration.java
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/beanutils/BeanHelper.java
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/reloading/VFSFileMonitorReloadingStrategy.java
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/MergeCombiner.java
    commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/NodeCombiner.java
    commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestDefaultConfigurationBuilder.java
    commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestVFSConfigurationBuilder.java
    commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testMultiTenentConfigurationBuilder.xml
    commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml
    commons/proper/configuration/branches/configuration2_experimental/xdocs/userguide/howto_basicfeatures.xml

Modified: commons/proper/configuration/branches/configuration2_experimental/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/pom.xml?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/pom.xml (original)
+++ commons/proper/configuration/branches/configuration2_experimental/pom.xml Sat Apr 11 06:48:44 2009
@@ -214,6 +214,13 @@
       <version>1.8.0</version>
       <optional>true</optional>
     </dependency>
+        
+    <dependency>
+      <groupId>commons-jexl</groupId>
+      <artifactId>commons-jexl</artifactId>
+      <version>1.1</version>
+      <optional>true</optional>
+    </dependency>
 
     <dependency>
       <groupId>org.apache.commons</groupId>

Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/CombinedConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/CombinedConfiguration.java?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/CombinedConfiguration.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/CombinedConfiguration.java Sat Apr 11 06:48:44 2009
@@ -23,6 +23,9 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.logging.Level;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
 
 import org.apache.commons.configuration2.event.ConfigurationEvent;
 import org.apache.commons.configuration2.event.ConfigurationListener;
@@ -33,6 +36,7 @@
 import org.apache.commons.configuration2.tree.NodeCombiner;
 import org.apache.commons.configuration2.tree.UnionCombiner;
 import org.apache.commons.configuration2.tree.ViewNode;
+import org.apache.commons.configuration2.tree.TreeUtils;
 
 /**
  * <p>
@@ -683,6 +687,13 @@
                 node = getNodeCombiner().combine(node,
                         ((ConfigData) it.next()).getTransformedRoot());
             }
+             if (getLogger().isLoggable(Level.FINEST))
+            {
+                ByteArrayOutputStream os = new ByteArrayOutputStream();
+                PrintStream stream = new PrintStream(os);
+                TreeUtils.printTree(stream, node);
+                getLogger().finest(os.toString());
+            }
             return node;
         }
     }

Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/DefaultConfigurationBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/DefaultConfigurationBuilder.java?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/DefaultConfigurationBuilder.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/DefaultConfigurationBuilder.java Sat Apr 11 06:48:44 2009
@@ -710,7 +710,9 @@
         {
             XMLBeanDeclaration<ConfigurationNode> decl = new XMLBeanDeclaration<ConfigurationNode>(config);
             String key = config.getString(KEY_LOOKUP_KEY);
-            ConfigurationInterpolator.registerGlobalLookup(key, (StrLookup) BeanHelper.createBean(decl));
+            StrLookup lookup = (StrLookup) BeanHelper.createBean(decl);
+            BeanHelper.setProperty(lookup, "configuration", this);
+            ConfigurationInterpolator.registerGlobalLookup(key, lookup);
         }
     }
 

Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/DynamicCombinedConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/DynamicCombinedConfiguration.java?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/DynamicCombinedConfiguration.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/DynamicCombinedConfiguration.java Sat Apr 11 06:48:44 2009
@@ -26,6 +26,7 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+import java.util.logging.Logger;
 
 import org.apache.commons.configuration2.event.ConfigurationErrorListener;
 import org.apache.commons.configuration2.event.ConfigurationListener;
@@ -72,6 +73,9 @@
     /** Stores the combiner. */
     private NodeCombiner nodeCombiner;
 
+    /** The name of the logger to use for each CombinedConfiguration */
+    private String loggerName;
+
     /**
      * Creates a new instance of <code>CombinedConfiguration</code> and
      * initializes the combiner to be used.
@@ -107,6 +111,15 @@
     }
 
     /**
+     * Set the name of the Logger to use on each CombinedConfiguration.
+     * @param name The Logger name.
+     */
+    public void setLoggerName(String name)
+    {
+        this.loggerName = name;
+    }
+
+    /**
      * Returns the node combiner that is used for creating the combined node
      * structure.
      *
@@ -722,7 +735,17 @@
             if (config == null)
             {
                 config = new CombinedConfiguration(getNodeCombiner());
+                if (loggerName != null)
+                {
+                    Logger log = Logger.getLogger(loggerName);
+                    if (log != null)
+                    {
+                        config.setLogger(log);
+                    }
+                }
                 config.setExpressionEngine(this.getExpressionEngine());
+                config.setDelimiterParsingDisabled(isDelimiterParsingDisabled());
+                config.setListDelimiter(getListDelimiter());
                 Iterator iter = config.getErrorListeners().iterator();
                 while (iter.hasNext())
                 {

Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/MultiFileHierarchicalConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/MultiFileHierarchicalConfiguration.java?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/MultiFileHierarchicalConfiguration.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/MultiFileHierarchicalConfiguration.java Sat Apr 11 06:48:44 2009
@@ -22,6 +22,7 @@
 import java.util.List;
 import java.util.Properties;
 import java.util.Collection;
+import java.util.logging.Logger;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.net.URL;
@@ -37,6 +38,8 @@
 import org.apache.commons.configuration2.event.ConfigurationEvent;
 import org.apache.commons.configuration2.expr.ExpressionEngine;
 import org.apache.commons.configuration2.tree.ConfigurationNode;
+import org.apache.commons.configuration2.reloading.ReloadingStrategy;
+import org.apache.commons.beanutils.BeanUtils;
 
 /**
  * This class provides access to multiple configuration files that reside in a location that
@@ -77,6 +80,18 @@
     /** Return an empty configuration if loading fails */
     private boolean ignoreException = true;
 
+    /** Capture the schema validation setting */
+    private boolean schemaValidation;
+
+    /** Stores a flag whether DTD or Schema validation should be performed.*/
+    private boolean validating;
+
+    /** A flag whether attribute splitting is disabled.*/
+    private boolean attributeSplittingDisabled;
+
+    /** The Logger name to use */
+    private String loggerName = "";
+
     /**
      * Default Constructor
      */
@@ -87,8 +102,8 @@
     }
 
     /**
-     * Constructor
-     * @param pathPattern The pattern to use to location configuration files.
+     * Construct the configuration with the specified pattern.
+     * @param pathPattern The pattern to use to locate configuration files.
      */
     public MultiFileHierarchicalConfiguration(String pathPattern)
     {
@@ -97,6 +112,11 @@
         this.init = true;
     }
 
+    public void setLoggerName(String name)
+    {
+        this.loggerName = name;
+    }
+
     /**
      * Set the File pattern
      * @param pathPattern The pattern for the path to the configuration.
@@ -106,6 +126,36 @@
         this.pattern = pathPattern;
     }
 
+    public boolean isSchemaValidation()
+    {
+        return schemaValidation;
+    }
+
+    public void setSchemaValidation(boolean schemaValidation)
+    {
+        this.schemaValidation = schemaValidation;
+    }
+
+    public boolean isValidating()
+    {
+        return validating;
+    }
+
+    public void setValidating(boolean validating)
+    {
+        this.validating = validating;
+    }
+
+    public boolean isAttributeSplittingDisabled()
+    {
+        return attributeSplittingDisabled;
+    }
+
+    public void setAttributeSplittingDisabled(boolean attributeSplittingDisabled)
+    {
+        this.attributeSplittingDisabled = attributeSplittingDisabled;
+    }
+
     /**
      * Set to true if an empty Configuration should be returned when loading fails. If
      * false an exception will be thrown.
@@ -639,11 +689,23 @@
         XMLConfiguration configuration = new XMLConfiguration();
         try
         {
+             if (loggerName != null)
+             {
+                Logger log = Logger.getLogger(loggerName);
+                if (log != null)
+                {
+                    configuration.setLogger(log);
+                }
+            }
+            configuration.setBasePath(getBasePath());
             configuration.setFileName(path);
+            configuration.setFileSystem(getFileSystem());
             configuration.setExpressionEngine(getExpressionEngine());
-            configuration.setReloadingStrategy(getReloadingStrategy());
+            configuration.setReloadingStrategy(createReloadingStrategy());
             configuration.setDelimiterParsingDisabled(isDelimiterParsingDisabled());
-            configuration.setDetailEvents(this.isDetailEvents());
+            configuration.setAttributeSplittingDisabled(isAttributeSplittingDisabled());
+            configuration.setValidating(validating);
+            configuration.setSchemaValidation(schemaValidation);
             configuration.setListDelimiter(getListDelimiter());
             configuration.addConfigurationListener(this);
             configuration.addErrorListener(this);
@@ -661,4 +723,27 @@
 
         return configuration;
     }
+
+    /**
+     * Clone the FileReloadingStrategy since each file needs its own.
+     * @return A new FileReloadingStrategy.
+     */
+    private ReloadingStrategy createReloadingStrategy()
+    {
+        if (getReloadingStrategy() == null)
+        {
+            return null;
+        }
+        try
+        {
+            ReloadingStrategy strategy = (ReloadingStrategy) BeanUtils.cloneBean(getReloadingStrategy());
+            strategy.setConfiguration(null);
+            return strategy;
+        }
+        catch (Exception ex)
+        {
+            return null;
+        }
+
+    }
 }

Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/VFSFileSystem.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/VFSFileSystem.java?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/VFSFileSystem.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/VFSFileSystem.java Sat Apr 11 06:48:44 2009
@@ -24,6 +24,8 @@
 import org.apache.commons.vfs.FileSystemException;
 import org.apache.commons.vfs.FileType;
 import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticator;
+import org.apache.commons.vfs.impl.DefaultFileSystemConfigBuilder;
 import org.apache.commons.vfs.provider.UriParser;
 import org.apache.commons.vfs.provider.http.HttpFileSystemConfigBuilder;
 import org.apache.commons.vfs.provider.webdav.WebdavFileSystemConfigBuilder;
@@ -336,10 +338,14 @@
             {
                 return setWebdavOptions(opts, map);
             }
-            if (scheme.equals("http"))
+            else if (scheme.equals("http"))
             {
                 return setHttpOptions(opts, map);
             }
+            else
+            {
+                return setDefaultOptions(opts, map);
+            }
         }
         return opts;
     }
@@ -365,6 +371,8 @@
 
     private FileSystemOptions setHttpOptions(FileSystemOptions opts, Map<String, Object> map)
     {
+        setDefaultOptions(opts, map);
+
         if (httpBuilder == null || map == null)
         {
             return opts;
@@ -390,4 +398,29 @@
         }
         return opts;
     }
+
+
+    private FileSystemOptions setDefaultOptions(FileSystemOptions opts, Map map)
+    {
+        DefaultFileSystemConfigBuilder builder = DefaultFileSystemConfigBuilder.getInstance();
+
+        if (builder == null || map == null)
+        {
+            return opts;
+        }
+
+        if (map.containsKey("userAuthenticator"))
+        {
+            UserAuthenticator auth = (UserAuthenticator) map.get("userAuthenticator");
+            try
+            {
+                builder.setUserAuthenticator(opts, auth);
+            }
+            catch (FileSystemException e)
+            {
+                return opts;
+            }
+        }
+        return opts;
+    }
 }

Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/XMLConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/XMLConfiguration.java?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/XMLConfiguration.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/XMLConfiguration.java Sat Apr 11 06:48:44 2009
@@ -31,6 +31,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Collections;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
@@ -214,6 +215,9 @@
     /** Stores a flag whether DTD or Schema validation is used */
     private boolean schemaValidation;
 
+    /** A flag whether attribute splitting is disabled.*/
+    private boolean attributeSplittingDisabled;
+
     /** The EntityResolver to use */
     private EntityResolver entityResolver = new DefaultEntityResolver();
 
@@ -479,6 +483,70 @@
     {
         return this.entityResolver;
     }
+    /**
+      * Returns the flag whether attribute splitting is disabled.
+      *
+      * @return the flag whether attribute splitting is disabled
+      * @see #setAttributeSplittingDisabled(boolean)
+      * @since 1.6
+      */
+     public boolean isAttributeSplittingDisabled()
+     {
+         return attributeSplittingDisabled;
+     }
+
+     /**
+      * <p>
+      * Sets a flag whether attribute splitting is disabled.
+      * </p>
+      * <p>
+      * The Configuration API allows adding multiple values to an attribute. This
+      * is problematic when storing the configuration because in XML an attribute
+      * can appear only once with a single value. To solve this problem, per
+      * default multiple attribute values are concatenated using a special
+      * separator character and split again when the configuration is loaded. The
+      * separator character is either the list delimiter character (see
+      * {@link #setListDelimiter(char)}) or the pipe symbol (&quot;|&quot;) if
+      * list delimiter parsing is disabled.
+      * </p>
+      * <p>
+      * In some constellations the splitting of attribute values can have
+      * undesired effects, especially if list delimiter parsing is disabled and
+      * attributes may contain the &quot;|&quot; character. In these cases it is
+      * possible to disable the attribute splitting mechanism by calling this
+      * method with a boolean value set to <b>false</b>. If attribute splitting
+      * is disabled, the values of attributes will not be processed, but stored
+      * as configuration properties exactly as they are returned by the XML
+      * parser.
+      * </p>
+      * <p>
+      * Note that in this mode multiple attribute values cannot be handled
+      * correctly. It is possible to create a <code>XMLConfiguration</code>
+      * object, add multiple values to an attribute and save it. When the
+      * configuration is loaded again and attribute splitting is disabled, the
+      * attribute will only have a single value, which is the concatenation of
+      * all values set before. So it lies in the responsibility of the
+      * application to carefully set the values of attributes.
+      * </p>
+      * <p>
+      * As is true for the {@link #setDelimiterParsingDisabled(boolean)} method,
+      * this method must be called before the configuration is loaded. So it
+      * can't be used together with one of the constructors expecting the
+      * specification of the file to load. Instead the default constructor has to
+      * be used, then <code>setAttributeSplittingDisabled(false)</code> has to be
+      * called, and finally the configuration can be loaded using one of its
+      * <code>load()</code> methods.
+      * </p>
+      *
+      * @param attributeSplittingDisabled <b>true</b> for disabling attribute
+      *        splitting, <b>false</b> for enabling it
+      * @see #setDelimiterParsingDisabled(boolean)
+      * @since 1.6
+      */
+     public void setAttributeSplittingDisabled(boolean attributeSplittingDisabled)
+     {
+         this.attributeSplittingDisabled = attributeSplittingDisabled;
+     }
 
     /**
      * Returns the XML document this configuration was loaded from. The return
@@ -597,8 +665,16 @@
             if (w3cNode instanceof Attr)
             {
                 Attr attr = (Attr) w3cNode;
-                char delimiter = isDelimiterParsingDisabled() ? ATTR_VALUE_DELIMITER : getListDelimiter();
-                List<String> values = PropertyConverter.split(attr.getValue(), delimiter);
+                List<String> values;
+                if (isAttributeSplittingDisabled())
+                {
+                    values = Collections.singletonList(attr.getValue());
+                }
+                else
+                {
+                    char delimiter = isDelimiterParsingDisabled() ? ATTR_VALUE_DELIMITER : getListDelimiter();
+                    values = PropertyConverter.split(attr.getValue(), delimiter);
+                }
 
                 for (String value : values)
                 {

Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/beanutils/BeanHelper.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/beanutils/BeanHelper.java?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/beanutils/BeanHelper.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/beanutils/BeanHelper.java Sat Apr 11 06:48:44 2009
@@ -17,19 +17,17 @@
 
 package org.apache.commons.configuration2.beanutils;
 
-import java.beans.BeanInfo;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
+import java.lang.reflect.InvocationTargetException;
+import java.beans.PropertyDescriptor;
 
 import org.apache.commons.configuration2.ConfigurationRuntimeException;
-import org.apache.commons.configuration2.converter.Converter;
-import org.apache.commons.configuration2.converter.DefaultPropertyConverter;
 import org.apache.commons.lang.ClassUtils;
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.beanutils.BeanUtils;
 
 /**
  * <p>
@@ -61,9 +59,6 @@
     /** Stores a map with the registered bean factories. */
     private static Map<String, BeanFactory> beanFactories = Collections.synchronizedMap(new HashMap<String, BeanFactory>());
 
-    /** Converter to set the bean properties */
-    private static Converter converter = new DefaultPropertyConverter();
-
     /**
      * Stores the default bean factory, which will be used if no other factory
      * is provided.
@@ -110,7 +105,7 @@
      */
     public static BeanFactory deregisterBeanFactory(String name)
     {
-        return (BeanFactory) beanFactories.remove(name);
+        return beanFactories.remove(name);
     }
 
     /**
@@ -178,6 +173,29 @@
      */
     public static void initBean(Object bean, BeanDeclaration data, boolean lenient) throws ConfigurationRuntimeException
     {
+        initBeanProperties(bean, data, lenient);
+
+        Map<String, BeanDeclaration> nestedBeans = data.getNestedBeanDeclarations();
+        if (nestedBeans != null)
+        {
+            for (Map.Entry<String, BeanDeclaration> e : nestedBeans.entrySet())
+            {
+                String propName = e.getKey();
+                Class defaultClass = getDefaultClass(bean, propName);
+                initProperty(bean, propName, createBean(e.getValue(), defaultClass), lenient);
+            }
+        }
+    }
+
+    public static void initBeanProperties(Object bean, BeanDeclaration data)
+        throws ConfigurationRuntimeException
+    {
+        initBeanProperties(bean, data, false);
+    }
+
+    public static void initBeanProperties(Object bean, BeanDeclaration data, boolean lenient)
+        throws ConfigurationRuntimeException
+    {
         Map<String, Object> properties = data.getBeanProperties();
         if (properties != null)
         {
@@ -186,19 +204,33 @@
                 initProperty(bean, e.getKey(), e.getValue(), lenient);
             }
         }
+    }
 
-        Map<String, BeanDeclaration> nestedBeans = data.getNestedBeanDeclarations();
-        if (nestedBeans != null)
+    /**
+     * Return the Class of the property if it can be determined.
+     * @param bean The bean containing the property.
+     * @param propName The name of the property.
+     * @return The class associated with the property or null.
+     */
+    private static Class getDefaultClass(Object bean, String propName)
+    {
+        try
         {
-            for (Map.Entry<String, BeanDeclaration> e : nestedBeans.entrySet())
+            PropertyDescriptor desc = PropertyUtils.getPropertyDescriptor(bean, propName);
+            if (desc == null)
             {
-                initProperty(bean, e.getKey(), createBean(e.getValue(), null), lenient);
+                return null;
             }
+            return desc.getPropertyType();
+        }
+        catch (Exception ex)
+        {
+            return null;
         }
     }
 
     /**
-     * Sets a property on the given bean.
+     * Sets a Property on the given bean using Common Beanutils.
      *
      * @param bean     the bean
      * @param propName the name of the property
@@ -208,63 +240,55 @@
      */
     private static void initProperty(Object bean, String propName, Object value, boolean lenient) throws ConfigurationRuntimeException
     {
-        try
+        if (!PropertyUtils.isWriteable(bean, propName))
         {
-            // find the descriptor for the property requested
-            PropertyDescriptor descriptor = getPropertyDescriptor(bean.getClass(), propName);
-
-            // check if the property is writeable
-            if (descriptor == null || descriptor.getWriteMethod() == null)
+            if (lenient)
             {
-                if (lenient)
-                {
-                    return;
-                }
-                else
-                {
-                    throw new ConfigurationRuntimeException("Property " + propName + " cannot be set!");
-                }
+                return;
             }
+            throw new ConfigurationRuntimeException("Property " + propName
+                    + " cannot be set!");
+        }
 
-            // set the property
-            Class type = descriptor.getPropertyType();
-            Object convertedValue = type.isAssignableFrom(value.getClass()) ? value : converter.convert(type, value);
-            descriptor.getWriteMethod().invoke(bean, convertedValue);
+        try
+        {
+            BeanUtils.setProperty(bean, propName, value);
         }
-        catch (ConfigurationRuntimeException e)
+        catch (IllegalAccessException iaex)
         {
-            throw e;
+            throw new ConfigurationRuntimeException(iaex);
         }
-        catch (Exception e)
+        catch (InvocationTargetException itex)
         {
-            throw new ConfigurationRuntimeException("Unable to set the property " + propName + " to '" + value + "'", e);
+            throw new ConfigurationRuntimeException(itex);
         }
     }
 
     /**
-     * Returns the PropertyDescriptor of the class for the specified property name.
-     *
-     * @param cls          the class to be introspected
-     * @param propertyName the name of the property
-     * @return the descriptor, or null if no property matches the name specified
-     * @throws IntrospectionException
+     * Set a property on the bean only if the property exists
+     * @param bean the bean
+     * @param propName the name of the property
+     * @param value the property's value
+     * @throws ConfigurationRuntimeException if the property is not writeable or
+     * an error occurred
      */
-    private static PropertyDescriptor getPropertyDescriptor(Class cls, String propertyName) throws IntrospectionException
+    public static void setProperty(Object bean, String propName, Object value)
     {
-        // find the descriptor for the property requested
-        BeanInfo info = Introspector.getBeanInfo(cls);
-        PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
-        PropertyDescriptor descriptor = null;
-        for (PropertyDescriptor d : descriptors)
+        if (PropertyUtils.isWriteable(bean, propName))
         {
-            if (d.getName().equals(propertyName))
+            try
             {
-                descriptor = d;
-                break;
+                BeanUtils.setProperty(bean, propName, value);
+            }
+            catch (IllegalAccessException iaex)
+            {
+                throw new ConfigurationRuntimeException(iaex);
+            }
+            catch (InvocationTargetException itex)
+            {
+                throw new ConfigurationRuntimeException(itex);
             }
         }
-
-        return descriptor;
     }
 
     /**

Added: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/interpol/ExprLookup.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/interpol/ExprLookup.java?rev=764170&view=auto
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/interpol/ExprLookup.java (added)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/interpol/ExprLookup.java Sat Apr 11 06:48:44 2009
@@ -0,0 +1,288 @@
+/*
+ * 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 org.apache.commons.lang.text.StrLookup;
+import org.apache.commons.lang.text.StrSubstitutor;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.ClassUtils;
+import org.apache.commons.configuration2.AbstractConfiguration;
+import org.apache.commons.configuration2.ConfigurationRuntimeException;
+import org.apache.commons.jexl.JexlHelper;
+import org.apache.commons.jexl.JexlContext;
+import org.apache.commons.jexl.Expression;
+import org.apache.commons.jexl.ExpressionFactory;
+
+import java.util.ArrayList;
+import java.util.logging.Level;
+
+/**
+ * Lookup that allows expressions to be evaluated.
+ *
+ * <pre>
+ *     ExprLookup.Variables vars = new ExprLookup.Variables();
+ *     vars.add(new ExprLookup.Variable("String", org.apache.commons.lang.StringUtils.class));
+ *     vars.add(new ExprLookup.Variable("Util", new Utility("Hello")));
+ *     vars.add(new ExprLookup.Variable("System", "Class:java.lang.System"));
+ *     XMLConfiguration config = new XMLConfiguration(TEST_FILE);
+ *     config.setLogger(log);
+ *     ExprLookup lookup = new ExprLookup(vars);
+ *     lookup.setConfiguration(config);
+ *     String str = lookup.lookup("'$[element] ' + String.trimToEmpty('$[space.description]')");
+ * </pre>
+ *
+ * In the example above TEST_FILE contains xml that looks like:
+ * <pre>
+ * &lt;configuration&gt;
+ *   &lt;element&gt;value&lt;/element&gt;
+ *   &lt;space xml:space="preserve"&gt;
+ *     &lt;description xml:space="default"&gt;     Some text      &lt;/description&gt;
+ *   &lt;/space&gt;
+ * &lt;/configuration&gt;
+ * </pre>
+ *
+ * The result will be "value Some text".
+ *
+ * This lookup uses Apache Commons Jexl and requires that the dependency be added to any
+ * projects which use this.
+ *
+ * @since 1.7
+ * @author <a
+ * href="http://commons.apache.org/configuration/team-list.html">Commons Configuration team</a>
+ * @version $Id$
+ */
+public class ExprLookup extends StrLookup
+{
+    /** Prefix to identify a Java Class object */
+    private static final String CLASS = "Class:";
+
+    /** The default prefix for subordinate lookup expressions */
+    private static final String DEFAULT_PREFIX = "$[";
+
+    /** The default suffix for subordinate lookup expressions */
+    private static final String DEFAULT_SUFFIX = "]";
+
+    /** Configuration being operated on */
+    private AbstractConfiguration configuration;
+
+    /** The JexlContext */
+    private JexlContext context = JexlHelper.createContext();
+
+    /** The String to use to start subordinate lookup expressions */
+    private String prefixMatcher = DEFAULT_PREFIX;
+
+    /** The String to use to terminate subordinate lookup expressions */
+    private String suffixMatcher = DEFAULT_SUFFIX;
+
+    /**
+     * The default constructor. Will get used when the Lookup is constructed via
+     * configuration.
+     */
+    public ExprLookup()
+    {
+    }
+
+    /**
+     * Constructor for use by applications.
+     * @param list The list of objects to be accessible in expressions.
+     */
+    public ExprLookup(Variables list)
+    {
+        setVariables(list);
+    }
+
+    /**
+     * Constructor for use by applications.
+     * @param list The list of objects to be accessible in expressions.
+     * @param prefix The prefix to use for subordinate lookups.
+     * @param suffix The suffix to use for subordinate lookups.
+     */
+    public ExprLookup(Variables list, String prefix, String suffix)
+    {
+        this(list);
+        setVariablePrefixMatcher(prefix);
+        setVariableSuffixMatcher(suffix);
+    }
+
+    /**
+     * Set the prefix to use to identify subordinate expressions. This cannot be the
+     * same as the prefix used for the primary expression.
+     * @param prefix The String identifying the beginning of the expression.
+     */
+    public void setVariablePrefixMatcher(String prefix)
+    {
+        prefixMatcher = prefix;
+    }
+
+
+    /**
+     * Set the suffix to use to identify subordinate expressions. This cannot be the
+     * same as the suffix used for the primary expression.
+     * @param suffix The String identifying the end of the expression.
+     */
+    public void setVariableSuffixMatcher(String suffix)
+    {
+        suffixMatcher = suffix;
+    }
+
+    /**
+     * Add the Variables that will be accessible within expressions.
+     * @param list The list of Variables.
+     */
+    public void setVariables(Variables list)
+    {
+        for (Variable var : list)
+        {
+            context.getVars().put(var.getName(), var.getValue());
+        }
+    }
+
+    /**
+     * Returns the list of Variables that are accessible within expressions.
+     * @return the List of Variables that are accessible within expressions.
+     */
+    public Variables getVariables()
+    {
+        return null;
+    }
+
+    /**
+     * Set the configuration to be used to interpolate subordinate expressiosn.
+     * @param config The Configuration.
+     */
+    public void setConfiguration(AbstractConfiguration config)
+    {
+        this.configuration = config;
+    }
+
+    /**
+     * Evaluates the expression.
+     * @param var The expression.
+     * @return The String result of the expression.
+     */
+    public String lookup(String var)
+    {
+        ConfigurationInterpolator interp = configuration.getInterpolator();
+        StrSubstitutor subst = new StrSubstitutor(interp, prefixMatcher, suffixMatcher,
+                StrSubstitutor.DEFAULT_ESCAPE);
+
+        String result = subst.replace(var);
+
+        try
+        {
+            Expression exp = ExpressionFactory.createExpression(result);
+            result = (String) exp.evaluate(context);
+        }
+        catch (Exception e)
+        {
+            configuration.getLogger().log(Level.FINE, "Error encountered evaluation " + result, e);
+        }
+
+        return result;
+    }
+
+    /**
+     * List wrapper used to allow the Variables list to be created as beans in
+     * DefaultConfigurationBuilder.
+     */
+    public static class Variables extends ArrayList<Variable>
+    {
+        public void setVariable(Variable var)
+        {
+            add(var);
+        }
+
+        public Variable getVariable()
+        {
+            if (size() > 0)
+            {
+                return get(size() - 1);
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+    }
+
+    /**
+     * The key and corresponding object that will be made available to the
+     * JexlContext for use in expressions.
+     */
+    public static class Variable
+    {
+        /** The name to be used in expressions */
+        private String key;
+
+        /** The object to be accessed in expressions */
+        private Object value;
+
+        public Variable()
+        {
+        }
+
+        public Variable(String name, Object value)
+        {
+            setName(name);
+            setValue(value);
+        }
+
+        public String getName()
+        {
+            return key;
+        }
+
+        public void setName(String name)
+        {
+            this.key = name;
+        }
+
+        public Object getValue()
+        {
+            return value;
+        }
+
+        public void setValue(Object value) throws ConfigurationRuntimeException
+        {
+            try
+            {
+                if (!(value instanceof String))
+                {
+                    this.value = value;
+                    return;
+                }
+                String val = (String) value;
+                String name = StringUtils.removeStartIgnoreCase(val, CLASS);
+                Class clazz = ClassUtils.getClass(name);
+                if (name.length() == val.length())
+                {
+                    this.value = clazz.newInstance();
+                }
+                else
+                {
+                    this.value = clazz;
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ConfigurationRuntimeException("Unable to create " + value, e);
+            }
+
+        }
+    }
+}

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/interpol/ExprLookup.java
------------------------------------------------------------------------------
    svn:eol-keywords = Date Author Id Revision HeadURL

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/interpol/ExprLookup.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/interpol/ExprLookup.java
------------------------------------------------------------------------------
    svn:keywords = "Date Author Id Revision HeadURL"

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/interpol/ExprLookup.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/reloading/VFSFileMonitorReloadingStrategy.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/reloading/VFSFileMonitorReloadingStrategy.java?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/reloading/VFSFileMonitorReloadingStrategy.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/reloading/VFSFileMonitorReloadingStrategy.java Sat Apr 11 06:48:44 2009
@@ -90,7 +90,7 @@
      */
     public void setConfiguration(FileConfiguration configuration)
     {
-        if (configuration instanceof FileSystemBased)
+        if (configuration == null || configuration instanceof FileSystemBased)
         {
             this.configuration = configuration;
         }
@@ -105,6 +105,10 @@
      */
     public void init()
     {
+        if (configuration.getURL() == null && configuration.getFileName() == null)
+        {
+            return;
+        }
         if (this.configuration == null)
         {
             throw new IllegalStateException("No configuration has been set for this strategy");
@@ -134,6 +138,10 @@
             FileSystem fs = ((FileSystemBased) configuration).getFileSystem();
             String uri = fs.getPath(null, configuration.getURL(), configuration.getBasePath(),
                 configuration.getFileName());
+            if (uri == null)
+            {
+                throw new ConfigurationRuntimeException("Unable to determine file to monitor");
+            }
             FileObject file = fsManager.resolveFile(uri);
             file.getFileSystem().addListener(file, this);
             fm.addFile(file);

Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/MergeCombiner.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/MergeCombiner.java?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/MergeCombiner.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/MergeCombiner.java Sat Apr 11 06:48:44 2009
@@ -16,7 +16,6 @@
  */
 package org.apache.commons.configuration2.tree;
 
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.ArrayList;
@@ -54,27 +53,19 @@
 
     public ConfigurationNode combine(ConfigurationNode node1, ConfigurationNode node2)
     {
-        ConfigurationNode result = doCombine(node1, node2);
-        printTree(result);
-        return result;
-    }
-    
-    public ConfigurationNode doCombine(ConfigurationNode node1, ConfigurationNode node2)
-    {
         ViewNode result = createViewNode();
         result.setName(node1.getName());
         result.setValue(node1.getValue());
         addAttributes(result, node1, node2);
 
         // Check if nodes can be combined
-        List children2 = new LinkedList(node2.getChildren());
-        for (Iterator it = node1.getChildren().iterator(); it.hasNext();)
+        List<ConfigurationNode> children2 = new LinkedList<ConfigurationNode>(node2.getChildren());
+        for (ConfigurationNode child1 : node1.getChildren())
         {
-            ConfigurationNode child1 = (ConfigurationNode) it.next();
             ConfigurationNode child2 = canCombine(node1, node2, child1, children2);
             if (child2 != null)
             {
-                result.addChild(doCombine(child1, child2));
+                result.addChild(combine(child1, child2));
                 children2.remove(child2);
             }
             else
@@ -84,9 +75,9 @@
         }
 
         // Add remaining children of node 2
-        for (Iterator it = children2.iterator(); it.hasNext();)
+        for (ConfigurationNode node : children2)
         {
-            result.addChild((ConfigurationNode) it.next());
+            result.addChild(node);
         }
         return result;
     }
@@ -105,9 +96,8 @@
             ConfigurationNode node2)
     {
         result.appendAttributes(node1);
-        for (Iterator it = node2.getAttributes().iterator(); it.hasNext();)
+        for (ConfigurationNode attr : node2.getAttributes())
         {
-            ConfigurationNode attr = (ConfigurationNode) it.next();
             if (node1.getAttributeCount(attr.getName()) == 0)
             {
                 result.addAttribute(attr);
@@ -128,21 +118,16 @@
     protected ConfigurationNode canCombine(ConfigurationNode node1,
             ConfigurationNode node2, ConfigurationNode child, List children2)
     {
-        List attrs1 = child.getAttributes();
-        List nodes = new ArrayList();
+        List<ConfigurationNode> attrs1 = child.getAttributes();
+        List<ConfigurationNode> nodes = new ArrayList();
 
-        List children = node2.getChildren(child.getName());
-        Iterator it = children.iterator();
-        while (it.hasNext())
-        {
-            ConfigurationNode node = (ConfigurationNode) it.next();
-            Iterator iter = attrs1.iterator();
-            while (iter.hasNext())
-            {
-                ConfigurationNode attr1 = (ConfigurationNode) iter.next();
-                List list2 = node.getAttributes(attr1.getName());
-                if (list2.size() == 1
-                    && !attr1.getValue().equals(((ConfigurationNode)list2.get(0)).getValue()))
+        List<ConfigurationNode> children = node2.getChildren(child.getName());
+        for (ConfigurationNode node : children)
+        {
+            for (ConfigurationNode attr1 : attrs1)
+            {
+                List<ConfigurationNode> list2 = node.getAttributes(attr1.getName());
+                if (list2.size() == 1 && !attr1.getValue().equals((list2.get(0)).getValue()))
                 {
                     node = null;
                     break;
@@ -156,16 +141,15 @@
 
         if (nodes.size() == 1)
         {
-            return (ConfigurationNode) nodes.get(0);
+            return nodes.get(0);
         }
         if (nodes.size() > 1 && !isListNode(child))
         {
-            Iterator iter = nodes.iterator();
-            while (iter.hasNext())
+            for (ConfigurationNode node : nodes)
             {
-                children2.remove(iter.next());
+                children2.remove(node);
             }
-        }        
+        }
 
         return null;
     }

Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/NodeCombiner.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/NodeCombiner.java?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/NodeCombiner.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/NodeCombiner.java Sat Apr 11 06:48:44 2009
@@ -53,9 +53,6 @@
  */
 public abstract class NodeCombiner
 {
-    /** Stream to write debug output to */
-    private PrintStream debugStream = null;
-
     /** Stores a list with node names that are known to be list nodes. */
     protected Set<String> listNodes;
 
@@ -124,51 +121,4 @@
     {
         return new ViewNode();
     }
-
-    /**
-     * Set the output stream to write the tree to.
-     * @param stream The OutputStream.
-     */
-    public void setDebugStream(PrintStream stream)
-    {
-        this.debugStream = stream;
-    }
-
-    protected void printTree(ConfigurationNode result)
-    {
-        if (debugStream != null)
-        {
-            printTree("", result);
-        }
-    }
-
-    private void printTree(String indent, ConfigurationNode result)
-    {
-        StringBuffer buffer = new StringBuffer(indent).append("<").append(result.getName());
-        for (ConfigurationNode node : result.getAttributes())
-        {
-            buffer.append(" ").append(node.getName()).append("='").append(node.getValue()).append("'");
-        }
-        buffer.append(">");
-        debugStream.print(buffer.toString());
-        if (result.getValue() != null)
-        {
-            debugStream.print(result.getValue());
-        }
-        boolean newline = false;
-        if (result.getChildrenCount() > 0)
-        {
-            debugStream.print("\n");
-            for (ConfigurationNode node : result.getChildren())
-            {
-                printTree(indent + "  ", node);
-            }
-            newline = true;
-        }
-        if (newline)
-        {
-            debugStream.print(indent);
-        }
-        debugStream.println("</" + result.getName() + ">");
-    }
 }

Added: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/TreeUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/TreeUtils.java?rev=764170&view=auto
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/TreeUtils.java (added)
+++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/TreeUtils.java Sat Apr 11 06:48:44 2009
@@ -0,0 +1,61 @@
+package org.apache.commons.configuration2.tree;
+
+import java.io.PrintStream;
+import java.util.Iterator;
+
+/**
+ * Utility methods.
+ * @author <a
+ * href="http://commons.apache.org/configuration/team-list.html">Commons
+ * Configuration team</a>
+ * @version $Id$
+ * @since 1.7
+ */
+public class TreeUtils
+{
+    /**
+     * Print out the data in the configuration.
+     * @param stream The OutputStream.
+     * @param result The root node of the tree.
+     */
+    public static void printTree(PrintStream stream, ConfigurationNode result)
+    {
+        if (stream != null)
+        {
+            printTree(stream, "", result);
+        }
+    }
+
+    private static void printTree(PrintStream stream, String indent, ConfigurationNode result)
+    {
+        StringBuffer buffer = new StringBuffer(indent).append("<").append(result.getName());
+        Iterator iter = result.getAttributes().iterator();
+        while (iter.hasNext())
+        {
+            ConfigurationNode node = (ConfigurationNode) iter.next();
+            buffer.append(" ").append(node.getName()).append("='").append(node.getValue()).append("'");
+        }
+        buffer.append(">");
+        stream.print(buffer.toString());
+        if (result.getValue() != null)
+        {
+            stream.print(result.getValue());
+        }
+        boolean newline = false;
+        if (result.getChildrenCount() > 0)
+        {
+            stream.print("\n");
+            iter = result.getChildren().iterator();
+            while (iter.hasNext())
+            {
+                printTree(stream, indent + "  ", (ConfigurationNode) iter.next());
+            }
+            newline = true;
+        }
+        if (newline)
+        {
+            stream.print(indent);
+        }
+        stream.println("</" + result.getName() + ">");
+    }
+}

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/TreeUtils.java
------------------------------------------------------------------------------
    svn:eol-keywords = Date Author Id Revision HeadURL

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/TreeUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/TreeUtils.java
------------------------------------------------------------------------------
    svn:keywords = "Date Author Id Revision HeadURL"

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/tree/TreeUtils.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestDefaultConfigurationBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestDefaultConfigurationBuilder.java?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestDefaultConfigurationBuilder.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestDefaultConfigurationBuilder.java Sat Apr 11 06:48:44 2009
@@ -18,13 +18,19 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.io.ByteArrayOutputStream;
 import java.net.URL;
 import java.util.Collection;
 import java.util.Set;
 import java.util.Map;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Iterator;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import java.util.logging.StreamHandler;
+import java.util.logging.SimpleFormatter;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Handler;
 
 import junit.framework.TestCase;
 
@@ -80,6 +86,9 @@
     private static final File MULTI_TENENT_FILE = ConfigurationAssert
             .getTestFile("testMultiTenentConfigurationBuilder.xml");
 
+    private static final File EXPRESSION_FILE = ConfigurationAssert
+            .getTestFile("conf/testExpression.xml");
+
     /** Constant for the name of an optional configuration.*/
     private static final String OPTIONAL_NAME = "optionalConfig";
 
@@ -868,12 +877,26 @@
     public void testMultiTenentConfiguration3() throws Exception
     {
         factory.setFile(MULTI_TENENT_FILE);
+        ByteArrayOutputStream stream = new ByteArrayOutputStream();
+        StreamHandler handler = new StreamHandler(stream, new SimpleFormatter());
+        handler.setLevel(Level.ALL);
+        Logger logger = Logger.getLogger("TestLogger");
+        logger.addHandler(handler);
+        logger.setLevel(Level.ALL);
+        logger.setUseParentHandlers(false);
+
         System.setProperty("Id", "1005");
 
         CombinedConfiguration config = factory.getConfiguration(true);
         assertTrue("Incorrect configuration", config instanceof DynamicCombinedConfiguration);
 
         verify("1001", config, 15);
+        handler.flush();
+        String xml = stream.toString();
+        assertNotNull("No XML returned", xml);
+        assertTrue("Incorect configuration data: " + xml, xml.contains("<rowsPerPage>15</rowsPerPage>"));
+        logger.removeHandler(handler);
+        logger.setLevel(Level.OFF);   
         verify("1002", config, 25);
         verify("1003", config, 35);
         verify("1004", config, 50);
@@ -891,25 +914,30 @@
         HierarchicalConfiguration sub2 = config.configurationAt("Channels/Channel[@id='2']");
         assertEquals("Channel 2", sub2.getString("Name"));
         assertEquals("more test 2 data", sub2.getString("MoreChannelData"));
-    } 
+    }
 
     public void testMerge() throws Exception
     {
         factory.setFile(MULTI_TENENT_FILE);
         System.setProperty("Id", "1004");
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("default", "${colors.header4}");
+        map.put("background", "#40404040");
+        map.put("text", "#000000");
+        map.put("header", "#444444");
 
         CombinedConfiguration config = factory.getConfiguration(true);
         assertTrue("Incorrect configuration", config instanceof DynamicCombinedConfiguration);
 
-        List list = config.configurationsAt("colors/*");
-        Iterator iter = list.iterator();
-        System.out.println("Color nodes");
-        while (iter.hasNext())
+        List<HierarchicalConfiguration> list = config.configurationsAt("colors/*");
+        for (HierarchicalConfiguration sub : list)
         {
-            SubnodeConfiguration sub = (SubnodeConfiguration)iter.next();
             ConfigurationNode node = sub.getRootNode();
             String value = (node.getValue() == null) ? "null" : node.getValue().toString();
-            System.out.println(node.getName() + "=" + value);
+            if (map.containsKey(node.getName()))
+            {
+                assertEquals(map.get(node.getName()), value);
+            }
         }
 
     }
@@ -930,6 +958,18 @@
         assertEquals("a\\,b\\,c", config.getString("split/list2"));
     }
 
+    public void testExpression() throws Exception
+    {
+        factory.setFile(EXPRESSION_FILE);
+        factory.setAttributeSplittingDisabled(true);
+        System.getProperties().remove("Id");
+
+        CombinedConfiguration config = factory.getConfiguration(true);
+        assertTrue("Incorrect configuration", config instanceof DynamicCombinedConfiguration);
+
+        verify("1001", config, 15);
+    }
+
     private void verify(String key, CombinedConfiguration config, int rows)
     {
         System.setProperty("Id", key);

Modified: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestVFSConfigurationBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestVFSConfigurationBuilder.java?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestVFSConfigurationBuilder.java (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestVFSConfigurationBuilder.java Sat Apr 11 06:48:44 2009
@@ -18,6 +18,10 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.io.FileReader;
+import java.io.Reader;
+import java.io.FileWriter;
+import java.io.Writer;
 import java.net.URL;
 import java.util.Collection;
 import java.util.Set;
@@ -78,6 +82,9 @@
     private static final File FILESYSTEM_FILE = ConfigurationAssert
             .getTestFile("testFileSystem.xml");
 
+    private static final File FILEMONITOR_FILE = ConfigurationAssert
+            .getTestFile("testFileMonitorConfigurationBuilder.xml");
+
     /** Constant for the name of an optional configuration.*/
     private static final String OPTIONAL_NAME = "optionalConfig";
 
@@ -951,6 +958,48 @@
         }
     }
 
+    public void testFileMonitor() throws Exception
+    {
+
+        // create a new configuration
+        File input = new File("target/test-classes/testMultiConfiguration_1001.xml");
+        File output = new File("target/test-classes/testwrite/testMultiConfiguration_1001.xml");
+        output.getParentFile().mkdir();
+        copyFile(input, output);
+
+        factory.setFile(FILEMONITOR_FILE);
+        FileSystem.resetDefaultFileSystem();
+        System.getProperties().remove("Id");
+
+        CombinedConfiguration config = factory.getConfiguration(true);
+        assertNotNull(config);
+        verify("1001", config, 15);
+
+        // Allow time for FileMonitor to set up.
+        Thread.sleep(1000);
+        XMLConfiguration x = new XMLConfiguration(output);
+        x.setProperty("rowsPerPage", "50");
+        x.save();
+        // Let FileMonitor detect the change.
+        Thread.sleep(2000);
+        verify("1001", config, 50);
+    }
+
+    private void copyFile(File input, File output) throws IOException
+    {
+        Reader reader = new FileReader(input);
+        Writer writer = new FileWriter(output);
+        char[] buffer = new char[4096];
+        int n = 0;
+        while (-1 != (n = reader.read(buffer)))
+        {
+            writer.write(buffer, 0, n);
+        }
+        reader.close();
+        writer.close();
+    }
+
+
     private void verify(String key, CombinedConfiguration config, int rows)
     {
         System.setProperty("Id", key);

Added: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/interpol/TestExprLookup.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/interpol/TestExprLookup.java?rev=764170&view=auto
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/interpol/TestExprLookup.java (added)
+++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/interpol/TestExprLookup.java Sat Apr 11 06:48:44 2009
@@ -0,0 +1,100 @@
+/*
+ * 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 junit.framework.TestCase;
+
+import java.io.File;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+import org.apache.commons.configuration2.XMLConfiguration;
+import org.apache.commons.configuration2.ConfigurationAssert;
+
+/**
+ * Test class for ExprLookup.
+ *
+ * @version $Id$
+ */
+public class TestExprLookup extends TestCase
+{
+    private static File TEST_FILE = ConfigurationAssert.getTestFile("test.xml");
+
+    private static String PATTERN1 =
+        "String.replace(Util.message, 'Hello', 'Goodbye') + System.getProperty('user.name')";
+    private static String PATTERN2 =
+        "'$[element] ' + String.trimToEmpty('$[space.description]')";
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+    }
+
+    /**
+     * Clears the test environment. Here the static cache of the constant lookup
+     * class is wiped out.
+     */
+    protected void tearDown() throws Exception
+    {
+        super.tearDown();
+    }
+
+    public void testLookup() throws Exception
+    {
+        ConsoleHandler handler = new ConsoleHandler();
+        Logger logger = Logger.getLogger("TestLogger");
+        logger.addHandler(handler);
+        logger.setLevel(Level.FINE);
+        ExprLookup.Variables vars = new ExprLookup.Variables();
+        vars.add(new ExprLookup.Variable("String", org.apache.commons.lang.StringUtils.class));
+        vars.add(new ExprLookup.Variable("Util", new Utility("Hello")));
+        vars.add(new ExprLookup.Variable("System", "Class:java.lang.System"));
+        XMLConfiguration config = new XMLConfiguration(TEST_FILE);
+        config.setLogger(logger);
+        ExprLookup lookup = new ExprLookup(vars);
+        lookup.setConfiguration(config);
+        String str = lookup.lookup(PATTERN1);
+        assertTrue(str.startsWith("Goodbye"));
+        str = lookup.lookup(PATTERN2);
+        assertTrue("Incorrect value: " + str, str.equals("value Some text"));
+        logger.removeHandler(handler);
+
+    }
+
+
+
+    public static class Utility
+    {
+        String message;
+
+        public Utility(String msg)
+        {
+            this.message = msg;
+        }
+
+        public String getMessage()
+        {
+            return message;
+        }
+
+        public String str(String str)
+        {
+            return str;
+        }
+    }
+}

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/interpol/TestExprLookup.java
------------------------------------------------------------------------------
    svn:eol-keywords = Date Author Id Revision HeadURL

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/interpol/TestExprLookup.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/interpol/TestExprLookup.java
------------------------------------------------------------------------------
    svn:keywords = "Date Author Id Revision HeadURL"

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/interpol/TestExprLookup.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/01/testMultiConfiguration_1001.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/resources/01/testMultiConfiguration_1001.xml?rev=764170&view=auto
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/test/resources/01/testMultiConfiguration_1001.xml (added)
+++ commons/proper/configuration/branches/configuration2_experimental/src/test/resources/01/testMultiConfiguration_1001.xml Sat Apr 11 06:48:44 2009
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<configuration>
+  <colors>
+    <background>#808080</background>
+    <text>#000000</text>
+    <header>#008000</header>
+    <link normal="#000080" visited="#800080"/>
+    <default>${colors.header}</default>
+  </colors>
+  <rowsPerPage>15</rowsPerPage>
+  <buttons>
+    <name>OK,Cancel,Help</name>
+  </buttons>
+  <numberFormat pattern="###\,###.##"/>
+  <Channels>
+    <Channel id="1">
+      <Name>My Channel</Name>
+    </Channel>
+    <Channel id="2">
+      <MoreChannelData>more test 2 data</MoreChannelData>
+    </Channel>
+  </Channels>
+</configuration>

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/01/testMultiConfiguration_1001.xml
------------------------------------------------------------------------------
    svn:eol-keywords = Date Author Id Revision HeadURL

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/01/testMultiConfiguration_1001.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/01/testMultiConfiguration_1001.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testExpression.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testExpression.xml?rev=764170&view=auto
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testExpression.xml (added)
+++ commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testExpression.xml Sat Apr 11 06:48:44 2009
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!-- Test configuration definition file that demonstrates complex initialization -->
+<configuration>
+  <header>
+    <result delimiterParsingDisabled="true" forceReloadCheck="true" loggerName="TestLogger"
+            config-class="org.apache.commons.configuration2.DynamicCombinedConfiguration"
+            keyPattern="$${sys:Id}">
+      <nodeCombiner config-class="org.apache.commons.configuration2.tree.MergeCombiner"/>
+      <expressionEngine
+          config-class="org.apache.commons.configuration2.tree.xpath.XPathExpressionEngine"/>
+    </result>
+    <lookups>
+      <lookup config-prefix="expr" 
+              config-class="org.apache.commons.configuration2.interpol.ExprLookup">
+        <variables>
+          <variable name="String" value="Class:org.apache.commons.lang.StringUtils"/>
+        </variables>
+      </lookup>
+    </lookups>
+    <providers>
+      <provider config-tag="multifile"
+         config-class="org.apache.commons.configuration2.DefaultConfigurationBuilder$FileConfigurationProvider"
+         configurationClass="org.apache.commons.configuration2.MultiFileHierarchicalConfiguration"/>
+    </providers>
+  </header>
+  <override>
+    <multifile filePattern='$$${expr:String.right("$[sys:Id]", 2)}/testMultiConfiguration_$$${sys:Id}.xml'
+               config-name="clientConfig" delimiterParsingDisabled="true">
+       <expressionEngine
+          config-class="org.apache.commons.configuration2.expr.xpath.XPathExpressionEngine"/>
+    </multifile>
+    <xml fileName="testMultiConfiguration_default.xml"
+         config-name="defaultConfig" delimiterParsingDisabled="true">
+      <expressionEngine
+          config-class="org.apache.commons.configuration2.expr.xpath.XPathExpressionEngine"/>
+    </xml>
+  </override>
+</configuration>
\ No newline at end of file

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testExpression.xml
------------------------------------------------------------------------------
    svn:eol-keywords = Date Author Id Revision HeadURL

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testExpression.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testExpression.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testFileMonitorConfigurationBuilder.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testFileMonitorConfigurationBuilder.xml?rev=764170&view=auto
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testFileMonitorConfigurationBuilder.xml (added)
+++ commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testFileMonitorConfigurationBuilder.xml Sat Apr 11 06:48:44 2009
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!-- Test configuration definition file that demonstrates complex initialization -->
+<configuration>
+  <header>
+    <result delimiterParsingDisabled="true" forceReloadCheck="true"
+            config-class="org.apache.commons.configuration2.DynamicCombinedConfiguration"
+            keyPattern="$${sys:Id}">
+      <nodeCombiner config-class="org.apache.commons.configuration2.tree.MergeCombiner"/>
+      <expressionEngine
+          config-class="org.apache.commons.configuration2.tree.xpath.XPathExpressionEngine"/>
+    </result>
+    <fileSystem config-class="org.apache.commons.configuration2.VFSFileSystem"/>
+    <providers>
+      <provider config-tag="multifile"
+         config-class="org.apache.commons.configuration2.DefaultConfigurationBuilder$FileConfigurationProvider"
+         configurationClass="org.apache.commons.configuration2.MultiFileHierarchicalConfiguration"/>
+    </providers>
+  </header>
+  <override>
+    <multifile filePattern="testwrite/testMultiConfiguration_$$${sys:Id}.xml"
+               config-name="clientConfig" delimiterParsingDisabled="true" schemaValidation="false">
+       <expressionEngine
+          config-class="org.apache.commons.configuration2.expr.xpath.XPathExpressionEngine"/>
+       <reloadingStrategy delay="500"
+          config-class="org.apache.commons.configuration2.reloading.VFSFileMonitorReloadingStrategy"/>
+    </multifile>
+    <xml fileName="testMultiConfiguration_default.xml"
+         config-name="defaultConfig" delimiterParsingDisabled="true">
+      <expressionEngine
+          config-class="org.apache.commons.configuration2.expr.xpath.XPathExpressionEngine"/>
+      <reloadingStrategy
+          config-class="org.apache.commons.configuration2.reloading.VFSFileMonitorReloadingStrategy"/>
+    </xml>
+  </override>
+</configuration>
\ No newline at end of file

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testFileMonitorConfigurationBuilder.xml
------------------------------------------------------------------------------
    svn:eol-keywords = Date Author Id Revision HeadURL

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testFileMonitorConfigurationBuilder.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testFileMonitorConfigurationBuilder.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Modified: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testMultiTenentConfigurationBuilder.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testMultiTenentConfigurationBuilder.xml?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testMultiTenentConfigurationBuilder.xml (original)
+++ commons/proper/configuration/branches/configuration2_experimental/src/test/resources/testMultiTenentConfigurationBuilder.xml Sat Apr 11 06:48:44 2009
@@ -2,7 +2,7 @@
 <!-- Test configuration definition file that demonstrates complex initialization -->
 <configuration>
   <header>
-    <result delimiterParsingDisabled="true" forceReloadCheck="true"
+    <result delimiterParsingDisabled="true" forceReloadCheck="true" loggerName="TestLogger"
             config-class="org.apache.commons.configuration2.DynamicCombinedConfiguration"
             keyPattern="$${sys:Id}">
       <nodeCombiner config-class="org.apache.commons.configuration2.tree.MergeCombiner"/>
@@ -17,7 +17,7 @@
   </header>
   <override>
     <multifile filePattern="testMultiConfiguration_$$${sys:Id}.xml"
-               config-name="clientConfig" delimiterParsingDisabled="true">
+               config-name="clientConfig" delimiterParsingDisabled="true" schemaValidation="false">
       <expressionEngine
           config-class="org.apache.commons.configuration2.expr.xpath.XPathExpressionEngine"/>
     </multifile>

Modified: commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml (original)
+++ commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml Sat Apr 11 06:48:44 2009
@@ -85,6 +85,11 @@
     </release>
 
     <release version="1.7" date="in SVN" description="">
+      <action dev="rgoers" type="add" issue="CONFIGURATION-380">
+        Add ExprLookup to allow expressions to be evaluated in configurations. When
+        used, this requires that Apache Commons Jexl be added as a dependency to
+        projects using Commons Configuration.
+      </action>      
       <action dev="oheger" type="add" issue="CONFIGURATION-374">
         MapConfiguration now provides a way of controlling the trimming
         behavior.
@@ -196,6 +201,14 @@
         DefaultConfigurationBuilder now supports defining new configuration
         providers in the configuration definition file.
       </action>
+      <action dev="oheger" type="add" issue="CONFIGURATION-335">
+        XMLConfiguration now allows disabling the attribute splitting mechanism
+        introduced in the 1.5 release (as part of the fix for CONFIGURATION-268).
+        This may be necessary for correctly processing attributes containing
+        both the list delimiter and the attribute delimiter character. The new
+        property &quot;disableAttributeSplitting&quot; was added for this
+        purpose.
+      </action>
       <action dev="oheger" type="fix" issue="CONFIGURATION-334">
         Made handling of parent nodes more consistent when setRoot() or
         setRootNode() of HierarchicalConfiguration are involved.

Modified: commons/proper/configuration/branches/configuration2_experimental/xdocs/userguide/howto_basicfeatures.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/xdocs/userguide/howto_basicfeatures.xml?rev=764170&r1=764169&r2=764170&view=diff
==============================================================================
--- commons/proper/configuration/branches/configuration2_experimental/xdocs/userguide/howto_basicfeatures.xml (original)
+++ commons/proper/configuration/branches/configuration2_experimental/xdocs/userguide/howto_basicfeatures.xml Sat Apr 11 06:48:44 2009
@@ -271,6 +271,79 @@
       which are then only used by this configuration instance.
     </p>
     </subsection>
+    <subsection name="Using Expressions">
+      <p>
+        In addition to the simple lookup mechanisms previously described, Commond Configuration
+        provides <code>ExprLookup</code> which uses <a href="http://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>
     </section>
 </body>
 



Mime
View raw message