commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rgo...@apache.org
Subject svn commit: r823891 [1/2] - in /commons/proper/configuration/trunk: ./ conf/ src/java/org/apache/commons/configuration/ src/java/org/apache/commons/configuration/beanutils/ src/java/org/apache/commons/configuration/reloading/ src/java/org/apache/common...
Date Sat, 10 Oct 2009 17:17:45 GMT
Author: rgoers
Date: Sat Oct 10 17:17:44 2009
New Revision: 823891

URL: http://svn.apache.org/viewvc?rev=823891&view=rev
Log:
Fix CONFIGURATION-390 and CONFIGURATION-397

Added:
    commons/proper/configuration/trunk/conf/configA.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/configA.xml
    commons/proper/configuration/trunk/conf/configB.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/configB.xml
    commons/proper/configuration/trunk/conf/log4j-test.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/log4j-test.xml
    commons/proper/configuration/trunk/conf/testFileReloadConfigurationBuilder.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testFileReloadConfigurationBuilder.xml
    commons/proper/configuration/trunk/conf/testFileReloadConfigurationBuilder2.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testFileReloadConfigurationBuilder2.xml
    commons/proper/configuration/trunk/conf/testMultiConfiguration.xsd
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiConfiguration.xsd
    commons/proper/configuration/trunk/conf/testMultiConfiguration_2001.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiConfiguration_2001.xml
    commons/proper/configuration/trunk/conf/testMultiConfiguration_2002.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiConfiguration_2002.xml
    commons/proper/configuration/trunk/conf/testMultiConfiguration_3001.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiConfiguration_3001.xml
    commons/proper/configuration/trunk/conf/testMultiConfiguration_3002.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiConfiguration_3002.xml
    commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder2.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiTenentConfigurationBuilder2.xml
    commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder3.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiTenentConfigurationBuilder3.xml
    commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder4.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiTenentConfigurationBuilder4.xml
    commons/proper/configuration/trunk/conf/testVFSMultiTenentConfigurationBuilder1.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testVFSMultiTenentConfigurationBuilder1.xml
    commons/proper/configuration/trunk/conf/testVFSMultiTenentConfigurationBuilder2.xml
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testVFSMultiTenentConfigurationBuilder2.xml
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalReloadableConfiguration.java
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/java/org/apache/commons/configuration/HierarchicalReloadableConfiguration.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/Lock.java
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/java/org/apache/commons/configuration/Lock.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/Reloadable.java
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/java/org/apache/commons/configuration/reloading/Reloadable.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/VFSFileChangedReloadingStrategy.java
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/java/org/apache/commons/configuration/reloading/VFSFileChangedReloadingStrategy.java
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/Logging.java
      - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/Logging.java
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/reloading/FileRandomReloadingStrategy.java
      - copied, changed from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/FileRandomReloadingStrategy.java
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/reloading/TestVFSFileChangedReloadingStrategy.java
      - copied, changed from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/TestVFSFileChangedReloadingStrategy.java
Removed:
    commons/proper/configuration/trunk/conf/testFileMonitorConfigurationBuilder.xml
    commons/proper/configuration/trunk/conf/testFileMonitorConfigurationBuilder2.xml
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/VFSFileMonitorReloadingStrategy.java
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/reloading/TestVFSFileMonitorReloadingStrategy.java
Modified:
    commons/proper/configuration/trunk/   (props changed)
    commons/proper/configuration/trunk/conf/testConfigurationInterpolatorUpdate.xml   (props changed)
    commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml
    commons/proper/configuration/trunk/conf/testSystemProperties.xml   (props changed)
    commons/proper/configuration/trunk/pom.xml
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/   (props changed)
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/CombinedConfiguration.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/ConfigurationUtils.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultFileSystem.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DynamicCombinedConfiguration.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MultiFileHierarchicalConfiguration.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PatternSubtreeConfigurationWrapper.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/SubnodeConfiguration.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/BeanHelper.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/FileChangedReloadingStrategy.java
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/resolver/CatalogResolver.java
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/   (props changed)
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestWebdavConfigurationBuilder.java
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestXMLConfiguration.java
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/reloading/TestFileChangedReloadingStrategy.java
    commons/proper/configuration/trunk/xdocs/   (props changed)
    commons/proper/configuration/trunk/xdocs/changes.xml
    commons/proper/configuration/trunk/xdocs/userguide/howto_filesystems.xml
    commons/proper/configuration/trunk/xdocs/userguide/howto_multitenant.xml

Propchange: commons/proper/configuration/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (added)
+++ svn:mergeinfo Sat Oct 10 17:17:44 2009
@@ -0,0 +1 @@
+/commons/proper/configuration/branches/CONFIGURATION_390:819412-822131

Propchange: commons/proper/configuration/trunk/conf/testConfigurationInterpolatorUpdate.xml
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat Oct 10 17:17:44 2009
@@ -0,0 +1,2 @@
+/commons/proper/configuration/branches/CONFIGURATION_390/conf/testConfigurationInterpolatorUpdate.xml:819412-822131
+/jakarta/commons/proper/configuration/trunk/conf/testConfigurationInterpolatorUpdate.xml:141756-560656,560658-560659

Modified: commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml (original)
+++ commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml Sat Oct 10 17:17:44 2009
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="ISO-8859-1" ?>
-<configuration>
+<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:noNamespaceSchemaLocation="http://commons.apache.org/testMultiConfiguration.xsd">
   <colors>
     <background>#40404040</background>
     <text>#000000</text>

Propchange: commons/proper/configuration/trunk/conf/testSystemProperties.xml
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat Oct 10 17:17:44 2009
@@ -0,0 +1,2 @@
+/commons/proper/configuration/branches/CONFIGURATION_390/conf/testSystemProperties.xml:819412-822131
+/jakarta/commons/proper/configuration/trunk/conf/testSystemProperties.xml:141756-560656,560658-560659

Modified: commons/proper/configuration/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/pom.xml?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/pom.xml (original)
+++ commons/proper/configuration/trunk/pom.xml Sat Oct 10 17:17:44 2009
@@ -462,6 +462,7 @@
             <include>testdb.script</include>
             <include>*.properties</include>
             <include>*.dtd</include>
+            <include>*.xsd</include>
           </includes>
         </testResource>
         <testResource>
@@ -485,6 +486,8 @@
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-surefire-plugin</artifactId>
           <configuration>
+            <!-- Uncomment to enable profiling unit tests -->
+            <!-- <argLine>-agentpath:"${yourkit.home}/bin/mac/libyjpagent.jnilib"</argLine> -->
             <forkMode>once</forkMode>
             <excludes>
               <exclude>**/TestWebdavConfigurationBuilder.java</exclude>
@@ -494,6 +497,10 @@
                 <name>java.awt.headless</name>
                 <value>true</value>
               </property>
+              <property>
+                <name>org.apache.commons.logging.Log</name>
+                <value>org.apache.commons.configuration.Logging</value>
+              </property>
             </systemProperties>
           </configuration>
         </plugin>
@@ -579,6 +586,14 @@
         </plugins>
       </build>
     </profile>
+    <!-- Uncomment this and set the path accordingly to enable YourKit -->
+    <!-- http://www.yourkit.com/docs/80/help/agent.jsp -->
+    <!-- <profile>
+      <id>yourkit-profile</id>
+      <properties>
+        <yourkit.home>/Applications/YourKit_Java_Profiler_8.0.17.app/</yourkit.home>
+      </properties>
+    </profile> -->
   </profiles>
   <reporting>
     <plugins>

Propchange: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat Oct 10 17:17:44 2009
@@ -1 +1,2 @@
+/commons/proper/configuration/branches/CONFIGURATION_390/src/java/org/apache/commons/configuration:819412-822131
 /commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2:751544-751840,755692,757108

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java Sat Oct 10 17:17:44 2009
@@ -103,7 +103,7 @@
     protected ReloadingStrategy strategy;
 
     /** A lock object for protecting reload operations.*/
-    private Object reloadLock = new Object();
+    protected Object reloadLock = new Lock("AbstractFileConfiguration");
 
     /** Stores the encoding of the configuration file.*/
     private String encoding;
@@ -207,6 +207,11 @@
         return this.fileSystem;
     }
 
+    public Object getReloadLock()
+    {
+        return reloadLock;
+    }
+
 
     /**
      * Load the configuration from the underlying location.
@@ -747,8 +752,11 @@
      */
     public void addProperty(String key, Object value)
     {
-        super.addProperty(key, value);
-        possiblySave();
+        synchronized(reloadLock)
+        {
+            super.addProperty(key, value);
+            possiblySave();
+        }
     }
 
     /**
@@ -761,14 +769,20 @@
      */
     public void setProperty(String key, Object value)
     {
-        super.setProperty(key, value);
-        possiblySave();
+        synchronized(reloadLock)
+        {
+            super.setProperty(key, value);
+            possiblySave();
+        }
     }
 
     public void clearProperty(String key)
     {
-        super.clearProperty(key);
-        possiblySave();
+        synchronized(reloadLock)
+        {
+            super.clearProperty(key);
+            possiblySave();
+        }
     }
 
     public ReloadingStrategy getReloadingStrategy()
@@ -795,6 +809,11 @@
      */
     public void reload()
     {
+        reload(false);
+    }
+
+    public boolean reload(boolean checkReload)
+    {
         synchronized (reloadLock)
         {
             if (noReload == 0)
@@ -833,6 +852,10 @@
                 {
                     fireError(EVENT_RELOAD, null, null, e);
                     // todo rollback the changes if the file can't be reloaded
+                    if (checkReload)
+                    {
+                        return false;
+                    }
                 }
                 finally
                 {
@@ -840,6 +863,7 @@
                 }
             }
         }
+        return true;
     }
 
     /**
@@ -920,13 +944,19 @@
     public boolean isEmpty()
     {
         reload();
-        return super.isEmpty();
+        synchronized(reloadLock)
+        {
+            return super.isEmpty();
+        }
     }
 
     public boolean containsKey(String key)
     {
         reload();
-        return super.containsKey(key);
+        synchronized(reloadLock)
+        {
+            return super.containsKey(key);
+        }
     }
 
     /**

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java Sat Oct 10 17:17:44 2009
@@ -29,7 +29,10 @@
 
 import org.apache.commons.configuration.event.ConfigurationEvent;
 import org.apache.commons.configuration.event.ConfigurationListener;
+import org.apache.commons.configuration.event.ConfigurationErrorListener;
+import org.apache.commons.configuration.event.ConfigurationErrorEvent;
 import org.apache.commons.configuration.reloading.ReloadingStrategy;
+import org.apache.commons.configuration.reloading.Reloadable;
 
 /**
  * <p>Base class for implementing file based hierarchical configurations.</p>
@@ -45,7 +48,8 @@
  */
 public abstract class AbstractHierarchicalFileConfiguration
 extends HierarchicalConfiguration
-implements FileConfiguration, ConfigurationListener, FileSystemBased
+implements FileConfiguration, ConfigurationListener, ConfigurationErrorListener, FileSystemBased,
+        Reloadable
 {
     /** Stores the delegate used for implementing functionality related to the
      * <code>FileConfiguration</code> interface.
@@ -137,26 +141,38 @@
 
     protected void addPropertyDirect(String key, Object obj)
     {
-        super.addPropertyDirect(key, obj);
-        delegate.possiblySave();
+        synchronized(delegate.getReloadLock())
+        {
+            super.addPropertyDirect(key, obj);
+            delegate.possiblySave();
+        }
     }
 
     public void clearProperty(String key)
     {
-        super.clearProperty(key);
-        delegate.possiblySave();
+        synchronized(delegate.getReloadLock())
+        {
+            super.clearProperty(key);
+            delegate.possiblySave();
+        }
     }
 
     public void clearTree(String key)
     {
-        super.clearTree(key);
-        delegate.possiblySave();
+        synchronized(delegate.getReloadLock())
+        {
+            super.clearTree(key);
+            delegate.possiblySave();
+        }
     }
 
     public void setProperty(String key, Object value)
     {
-        super.setProperty(key, value);
-        delegate.possiblySave();
+        synchronized(delegate.getReloadLock())
+        {
+            super.setProperty(key, value);
+            delegate.possiblySave();
+        }
     }
 
     public void load() throws ConfigurationException
@@ -281,10 +297,15 @@
 
     public void reload()
     {
+        reload(false);
+    }
+
+    private boolean reload(boolean checkReload)
+    {
         setDetailEvents(false);
         try
         {
-            delegate.reload();
+            return delegate.reload(checkReload);
         }
         finally
         {
@@ -302,34 +323,58 @@
         delegate.setEncoding(encoding);
     }
 
+    public Object getReloadLock()
+    {
+        return delegate.getReloadLock();
+    }
+
     public boolean containsKey(String key)
     {
         reload();
-        return super.containsKey(key);
+        synchronized(delegate.getReloadLock())
+        {
+            return super.containsKey(key);
+        }
     }
 
     public Iterator getKeys()
     {
         reload();
-        return super.getKeys();
+        synchronized(delegate.getReloadLock())
+        {
+            return super.getKeys();
+        }
     }
 
     public Iterator getKeys(String prefix)
     {
         reload();
-        return super.getKeys(prefix);
+        synchronized(delegate.getReloadLock())
+        {
+            return super.getKeys(prefix);
+        }
     }
 
     public Object getProperty(String key)
     {
-        reload();
-        return super.getProperty(key);
+        if (reload(true))
+        {
+            // Avoid reloading again and getting the same error.
+            synchronized(delegate.getReloadLock())
+            {
+                return super.getProperty(key);
+            }
+        }
+        return null;
     }
 
     public boolean isEmpty()
     {
         reload();
-        return super.isEmpty();
+        synchronized(delegate.getReloadLock())
+        {
+            return super.isEmpty();
+        }
     }
 
     /**
@@ -342,8 +387,11 @@
      */
     public void addNodes(String key, Collection nodes)
     {
-        super.addNodes(key, nodes);
-        delegate.possiblySave();
+        synchronized(delegate.getReloadLock())
+        {
+            super.addNodes(key, nodes);
+            delegate.possiblySave();
+        }
     }
 
     /**
@@ -356,7 +404,10 @@
     protected List fetchNodeList(String key)
     {
         reload();
-        return super.fetchNodeList(key);
+        synchronized(delegate.getReloadLock())
+        {
+            return super.fetchNodeList(key);
+        }
     }
 
     /**
@@ -394,6 +445,8 @@
     private void initDelegate(FileConfigurationDelegate del)
     {
         del.addConfigurationListener(this);
+        del.addErrorListener(this);
+        del.setLogger(getLogger());
     }
 
     /**
@@ -418,6 +471,12 @@
         }
     }
 
+    public void configurationError(ConfigurationErrorEvent event)
+    {
+        fireError(event.getType(), event.getPropertyName(), event.getPropertyValue(),
+                event.getCause());
+    }
+
     /**
      * Returns the file configuration delegate.
      *

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/CombinedConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/CombinedConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/CombinedConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/CombinedConfiguration.java Sat Oct 10 17:17:44 2009
@@ -169,7 +169,7 @@
  * @since 1.3
  * @version $Id$
  */
-public class CombinedConfiguration extends HierarchicalConfiguration implements
+public class CombinedConfiguration extends HierarchicalReloadableConfiguration implements
         ConfigurationListener, Cloneable
 {
     /**
@@ -204,6 +204,12 @@
     /** Stores a map with the named configurations. */
     private Map namedConfigurations;
 
+    /** The default behavior is to ignore exceptions that occur during reload */
+    private boolean ignoreReloadExceptions = true;
+
+    /** Set to true when the backing file has changed */
+    private boolean reloadRequired = false;
+
     /**
      * An expression engine used for converting child configurations to
      * hierarchical ones.
@@ -226,6 +232,18 @@
         clear();
     }
 
+    public CombinedConfiguration(NodeCombiner comb, Lock lock)
+    {
+        super(lock);
+        setNodeCombiner((comb != null) ? comb : DEFAULT_COMBINER);
+        clear();
+    }
+
+    public CombinedConfiguration(Lock lock)
+    {
+        this(null, lock);
+    }
+
     /**
      * Creates a new instance of <code>CombinedConfiguration</code> that uses
      * a union combiner.
@@ -234,7 +252,7 @@
      */
     public CombinedConfiguration()
     {
-        this(null);
+        this(null, null);
     }
 
     /**
@@ -330,6 +348,26 @@
     }
 
     /**
+     * Retrieves the value of the ignoreReloadExceptions flag.
+     * @return true if exceptions are ignored, false otherwise.
+     */
+    public boolean isIgnoreReloadExceptions()
+    {
+        return ignoreReloadExceptions;
+    }
+
+    /**
+     * If set to true then exceptions that occur during reloading will be
+     * ignored. If false then the exceptions will be allowed to be thrown
+     * back to the caller.
+     * @param ignoreReloadExceptions true if exceptions should be ignored.
+     */
+    public void setIgnoreReloadExceptions(boolean ignoreReloadExceptions)
+    {
+        this.ignoreReloadExceptions = ignoreReloadExceptions;
+    }
+
+    /**
      * Adds a new configuration to this combined configuration. It is possible
      * (but not mandatory) to give the new configuration a name. This name must
      * be unique, otherwise a <code>ConfigurationRuntimeException</code> will
@@ -362,6 +400,10 @@
         }
 
         ConfigData cd = new ConfigData(config, name, at);
+        if (getLogger().isDebugEnabled())
+        {
+            getLogger().debug("Adding configuration " + config + " with name " + name);
+        }
         configurations.add(cd);
         if (name != null)
         {
@@ -546,7 +588,7 @@
      */
     public void invalidate()
     {
-        combinedRoot = null;
+        reloadRequired = true;
         fireEvent(EVENT_COMBINED_INVALIDATE, null, null, false);
     }
 
@@ -578,11 +620,15 @@
      */
     public ConfigurationNode getRootNode()
     {
-        if (combinedRoot == null)
+        synchronized(getReloadLock())
         {
-            combinedRoot = constructCombinedNode();
+            if (reloadRequired || combinedRoot == null)
+            {
+                combinedRoot = constructCombinedNode();
+                reloadRequired = false;
+            }
+            return combinedRoot;
         }
-        return combinedRoot;
     }
 
     /**
@@ -716,8 +762,10 @@
             }
             catch (Exception ex)
             {
-                // ignore all exceptions, e.g. missing property exceptions
-                ;
+                if (!ignoreReloadExceptions)
+                {
+                    throw new ConfigurationRuntimeException(ex);
+                }
             }
         }
     }
@@ -731,6 +779,10 @@
     {
         if (getNumberOfConfigurations() < 1)
         {
+            if (getLogger().isDebugEnabled())
+            {
+                getLogger().debug("No configurations defined for " + this);
+            }
             return new ViewNode();
         }
 
@@ -763,23 +815,26 @@
      */
     private Configuration findSourceConfiguration(ConfigurationNode node)
     {
-        ConfigurationNode root = null;
-        ConfigurationNode current = node;
-
-        // find the root node in this hierarchy
-        while (current != null)
+        synchronized(getReloadLock())
         {
-            root = current;
-            current = current.getParentNode();
-        }
+            ConfigurationNode root = null;
+            ConfigurationNode current = node;
 
-        // Check with the root nodes of the child configurations
-        for (Iterator it = configurations.iterator(); it.hasNext();)
-        {
-            ConfigData cd = (ConfigData) it.next();
-            if (root == cd.getRootNode())
+            // find the root node in this hierarchy
+            while (current != null)
             {
-                return cd.getConfiguration();
+                root = current;
+                current = current.getParentNode();
+            }
+
+            // Check with the root nodes of the child configurations
+            for (Iterator it = configurations.iterator(); it.hasNext();)
+            {
+                ConfigData cd = (ConfigData) it.next();
+                if (root == cd.getRootNode())
+                {
+                    return cd.getConfiguration();
+                }
             }
         }
 
@@ -889,11 +944,12 @@
             }
 
             // Copy data of the root node to the new path
-            rootNode = ConfigurationUtils
+            ConfigurationNode root = ConfigurationUtils
                     .convertToHierarchical(getConfiguration(),
                             getConversionExpressionEngine()).getRootNode();
-            atParent.appendChildren(rootNode);
-            atParent.appendAttributes(rootNode);
+            atParent.appendChildren(root);
+            atParent.appendAttributes(root);
+            rootNode = root;
 
             return result;
         }

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/ConfigurationUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/ConfigurationUtils.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/ConfigurationUtils.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/ConfigurationUtils.java Sat Oct 10 17:17:44 2009
@@ -32,6 +32,7 @@
 import org.apache.commons.configuration.event.ConfigurationErrorListener;
 import org.apache.commons.configuration.event.EventSource;
 import org.apache.commons.configuration.tree.ExpressionEngine;
+import org.apache.commons.configuration.reloading.Reloadable;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.SystemUtils;
 import org.apache.commons.logging.Log;
@@ -223,7 +224,19 @@
 
         if (conf instanceof HierarchicalConfiguration)
         {
-            HierarchicalConfiguration hc = (HierarchicalConfiguration) conf;
+            HierarchicalConfiguration hc;
+            if (conf instanceof Reloadable)
+            {
+                Object lock = ((Reloadable) conf).getReloadLock();
+                synchronized(lock)
+                {
+                    hc = new HierarchicalConfiguration((HierarchicalConfiguration) conf);
+                }
+            }
+            else
+            {
+                hc = (HierarchicalConfiguration) conf;
+            }
             if (engine != null)
             {
                 hc.setExpressionEngine(engine);

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java Sat Oct 10 17:17:44 2009
@@ -40,6 +40,7 @@
 import org.apache.commons.configuration.resolver.EntityResolverSupport;
 import org.apache.commons.lang.text.StrLookup;
 import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.Log;
 import org.xml.sax.EntityResolver;
 
 /**
@@ -651,6 +652,11 @@
                     .next();
             ConfigurationDeclaration decl = new ConfigurationDeclaration(this,
                     conf);
+            if (getLogger().isDebugEnabled())
+            {
+                getLogger().debug("Creating configuration " + decl.getBeanClassName() + " with name " +
+                    decl.getConfiguration().getString(ATTR_NAME));
+            }
             AbstractConfiguration newConf = createConfigurationAt(decl);
             if (newConf != null)
             {
@@ -1225,6 +1231,8 @@
      */
     static class ConfigurationBeanFactory implements BeanFactory
     {
+        private Log logger = LogFactory.getLog(DefaultConfigurationBuilder.class);
+
         /**
          * Creates an instance of a bean class. This implementation expects that
          * the passed in bean declaration is a declaration for a configuration.
@@ -1268,6 +1276,11 @@
                 }
                 else
                 {
+                    if (logger.isDebugEnabled())
+                    {
+                        logger.debug("Load failed for optional configuration " + tagName + ": "
+                            + ex.getMessage());
+                    }
                     // Notify registered error listeners
                     decl.getConfigurationBuilder().fireError(
                             EVENT_ERR_LOAD_OPTIONAL,

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultFileSystem.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultFileSystem.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultFileSystem.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultFileSystem.java Sat Oct 10 17:17:44 2009
@@ -16,6 +16,9 @@
  */
 package org.apache.commons.configuration;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
 import java.io.InputStream;
 import java.io.File;
 import java.io.IOException;
@@ -35,6 +38,11 @@
  */
 public class DefaultFileSystem extends FileSystem
 {
+    /**
+     * The Log for diagnostic messages.
+     */
+    private Log log = LogFactory.getLog(DefaultFileSystem.class);
+
     public InputStream getInputStream(String basePath, String fileName)
         throws ConfigurationException
     {
@@ -254,6 +262,10 @@
         }
         catch (IOException e)
         {
+            if (log.isDebugEnabled())
+            {
+                log.debug("Could not locate file " + fileName + " at " + basePath + ": " + e.getMessage());
+            }
             return null;
         }
     }

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DynamicCombinedConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DynamicCombinedConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DynamicCombinedConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DynamicCombinedConfiguration.java Sat Oct 10 17:17:44 2009
@@ -32,8 +32,10 @@
 import org.apache.commons.configuration.tree.ConfigurationNode;
 import org.apache.commons.configuration.tree.ExpressionEngine;
 import org.apache.commons.configuration.tree.NodeCombiner;
+import org.apache.commons.configuration.interpol.ConfigurationInterpolator;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.commons.lang.text.StrSubstitutor;
 
 /**
  * DynamicCombinedConfiguration allows a set of CombinedConfigurations to be used. Each CombinedConfiguration
@@ -74,7 +76,9 @@
     private NodeCombiner nodeCombiner;
 
     /** The name of the logger to use for each CombinedConfiguration */
-    private String loggerName;
+    private String loggerName = DynamicCombinedConfiguration.class.getName();
+
+    private StrSubstitutor localSubst = new StrSubstitutor(new ConfigurationInterpolator());
 
     /**
      * Creates a new instance of <code>CombinedConfiguration</code> and
@@ -87,6 +91,8 @@
     {
         super();
         setNodeCombiner(comb);
+        setIgnoreReloadExceptions(false);
+        setLogger(LogFactory.getLog(DynamicCombinedConfiguration.class));
     }
 
     /**
@@ -98,6 +104,8 @@
     public DynamicCombinedConfiguration()
     {
         super();
+        setIgnoreReloadExceptions(false);
+        setLogger(LogFactory.getLog(DynamicCombinedConfiguration.class));
     }
 
     public void setKeyPattern(String pattern)
@@ -752,7 +760,7 @@
 
     private CombinedConfiguration getCurrentConfig()
     {
-        String key = getSubstitutor().replace(keyPattern);
+        String key = localSubst.replace(keyPattern);
         CombinedConfiguration config;
         synchronized (getNodeCombiner())
         {
@@ -768,6 +776,7 @@
                         config.setLogger(log);
                     }
                 }
+                config.setIgnoreReloadExceptions(isIgnoreReloadExceptions());
                 config.setExpressionEngine(this.getExpressionEngine());
                 config.setDelimiterParsingDisabled(isDelimiterParsingDisabled());
                 config.setConversionExpressionEngine(getConversionExpressionEngine());
@@ -795,6 +804,10 @@
                 configs.put(key, config);
             }
         }
+        if (getLogger().isDebugEnabled())
+        {
+            getLogger().debug("Returning config for " + key + ": " + config);
+        }
         return config;
     }
 

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java Sat Oct 10 17:17:44 2009
@@ -194,6 +194,16 @@
     }
 
     /**
+     * Object to synchronize on a reload. This class is not reloadable so this
+     * object isn't important
+     * @return
+     */
+    public Object getReloadLock()
+    {
+        return this;
+    }
+
+    /**
      * Returns the root node of this hierarchical configuration. This method
      * exists for backwards compatibility only. New code should use the
      * <code>{@link #getRootNode()}</code> method instead, which operates on

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MultiFileHierarchicalConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MultiFileHierarchicalConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MultiFileHierarchicalConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MultiFileHierarchicalConfiguration.java Sat Oct 10 17:17:44 2009
@@ -39,10 +39,13 @@
 import org.apache.commons.configuration.tree.ExpressionEngine;
 import org.apache.commons.configuration.reloading.ReloadingStrategy;
 import org.apache.commons.configuration.resolver.EntityResolverSupport;
+import org.apache.commons.configuration.interpol.ConfigurationInterpolator;
 import org.apache.commons.beanutils.BeanUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.commons.lang.text.StrSubstitutor;
 import org.xml.sax.EntityResolver;
+import org.xml.sax.SAXParseException;
 
 /**
  * This class provides access to multiple configuration files that reside in a location that
@@ -92,7 +95,7 @@
     private boolean attributeSplittingDisabled;
 
     /** The Logger name to use */
-    private String loggerName = "";
+    private String loggerName = MultiFileHierarchicalConfiguration.class.getName();
 
     /** The Reloading strategy to use on created configurations */
     private ReloadingStrategy fileStrategy;
@@ -100,6 +103,8 @@
     /** The EntityResolver */
     private EntityResolver entityResolver;
 
+    private StrSubstitutor localSubst = new StrSubstitutor(new ConfigurationInterpolator());
+
     /**
      * Default Constructor.
      */
@@ -107,6 +112,7 @@
     {
         super();
         this.init = true;
+        setLogger(LogFactory.getLog(loggerName));
     }
 
     /**
@@ -118,6 +124,7 @@
         super();
         this.pattern = pathPattern;
         this.init = true;
+        setLogger(LogFactory.getLog(loggerName));
     }
 
     public void setLoggerName(String name)
@@ -402,6 +409,11 @@
         return this.getConfiguration().subset(prefix);
     }
 
+    public Object getReloadLock()
+    {
+        return this.getConfiguration().getReloadLock();
+    }
+
     public Node getRoot()
     {
         return this.getConfiguration().getRoot();
@@ -621,6 +633,14 @@
                 listener.configurationError(event);
             }
         }
+
+        if (event.getType() == AbstractFileConfiguration.EVENT_RELOAD)
+        {
+            if (isThrowable(event.getCause()))
+            {
+                throw new ConfigurationRuntimeException(event.getCause());
+            }
+        }
     }
 
     /*
@@ -669,7 +689,7 @@
         {
             throw new ConfigurationRuntimeException("File pattern must be defined");
         }
-        String path = getSubstitutor().replace(pattern);
+        String path = localSubst.replace(pattern);
         synchronized (configurationsMap)
         {
             if (configurationsMap.containsKey(path))
@@ -730,7 +750,7 @@
         }
         catch (ConfigurationException ce)
         {
-            if (!ignoreException)
+            if (isThrowable(ce))
             {
                 throw new ConfigurationRuntimeException(ce);
             }
@@ -746,6 +766,20 @@
         return configuration;
     }
 
+    private boolean isThrowable(Throwable throwable)
+    {
+        if (!ignoreException)
+        {
+            return true;
+        }
+        Throwable cause = throwable.getCause();
+        while (cause != null && !(cause instanceof SAXParseException))
+        {
+            cause = cause.getCause();
+        }
+        return cause != null;
+    }
+
     /**
      * Clone the FileReloadingStrategy since each file needs its own.
      * @return A new FileReloadingStrategy.

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PatternSubtreeConfigurationWrapper.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PatternSubtreeConfigurationWrapper.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PatternSubtreeConfigurationWrapper.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PatternSubtreeConfigurationWrapper.java Sat Oct 10 17:17:44 2009
@@ -78,6 +78,11 @@
         this.init = true;
     }
 
+    public Object getReloadLock()
+    {
+        return config.getReloadLock();
+    }
+
     public void addProperty(String key, Object value)
     {
         config.addProperty(makePath(key), value);

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/SubnodeConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/SubnodeConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/SubnodeConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/SubnodeConfiguration.java Sat Oct 10 17:17:44 2009
@@ -23,6 +23,7 @@
 
 import org.apache.commons.configuration.interpol.ConfigurationInterpolator;
 import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.configuration.reloading.Reloadable;
 
 /**
  * <p>
@@ -114,7 +115,7 @@
  * @author Oliver Heger
  * @version $Id$
  */
-public class SubnodeConfiguration extends HierarchicalConfiguration
+public class SubnodeConfiguration extends HierarchicalReloadableConfiguration
 {
     /**
      * The serial version UID.
@@ -136,6 +137,7 @@
      */
     public SubnodeConfiguration(HierarchicalConfiguration parent, ConfigurationNode root)
     {
+        super(parent instanceof Reloadable ? ((Reloadable) parent).getReloadLock() : null);
         if (parent == null)
         {
             throw new IllegalArgumentException(

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java Sat Oct 10 17:17:44 2009
@@ -49,6 +49,7 @@
 import org.apache.commons.configuration.tree.ConfigurationNode;
 import org.apache.commons.configuration.resolver.EntityRegistry;
 import org.apache.commons.configuration.resolver.DefaultEntityResolver;
+import org.apache.commons.logging.LogFactory;
 import org.w3c.dom.Attr;
 import org.w3c.dom.CDATASection;
 import org.w3c.dom.DOMException;
@@ -226,6 +227,7 @@
     public XMLConfiguration()
     {
         super();
+        setLogger(LogFactory.getLog(XMLConfiguration.class));
     }
 
     /**
@@ -243,6 +245,7 @@
         super(c);
         clearReferences(getRootNode());
         setRootElementName(getRootNode().getName());
+        setLogger(LogFactory.getLog(XMLConfiguration.class));
     }
 
     /**
@@ -255,6 +258,7 @@
     public XMLConfiguration(String fileName) throws ConfigurationException
     {
         super(fileName);
+        setLogger(LogFactory.getLog(XMLConfiguration.class));
     }
 
     /**
@@ -267,6 +271,7 @@
     public XMLConfiguration(File file) throws ConfigurationException
     {
         super(file);
+        setLogger(LogFactory.getLog(XMLConfiguration.class));
     }
 
     /**
@@ -279,6 +284,7 @@
     public XMLConfiguration(URL url) throws ConfigurationException
     {
         super(url);
+        setLogger(LogFactory.getLog(XMLConfiguration.class));
     }
 
     /**
@@ -567,6 +573,7 @@
     public void clear()
     {
         super.clear();
+        setRoot(new Node());
         document = null;
     }
 
@@ -939,11 +946,11 @@
         }
         catch (SAXParseException spe)
         {
-            this.getLogger().debug("Error parsing " + source.getSystemId(), spe);
             throw new ConfigurationException("Error parsing " + source.getSystemId(), spe);
         }
         catch (Exception e)
         {
+            this.getLogger().debug("Unable to load the configuraton", e);
             throw new ConfigurationException("Unable to load the configuration", e);
         }
     }

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/BeanHelper.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/BeanHelper.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/BeanHelper.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/BeanHelper.java Sat Oct 10 17:17:44 2009
@@ -263,7 +263,7 @@
         if (!PropertyUtils.isWriteable(bean, propName))
         {
             throw new ConfigurationRuntimeException("Property " + propName
-                    + " cannot be set!");
+                    + " cannot be set on " + bean.getClass().getName());
         }
 
         try

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/FileChangedReloadingStrategy.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/FileChangedReloadingStrategy.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/FileChangedReloadingStrategy.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/FileChangedReloadingStrategy.java Sat Oct 10 17:17:44 2009
@@ -23,6 +23,8 @@
 
 import org.apache.commons.configuration.ConfigurationUtils;
 import org.apache.commons.configuration.FileConfiguration;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 /**
  * <p>A reloading strategy that will reload the configuration every time its
@@ -64,6 +66,9 @@
     /** A flag whether a reload is required.*/
     private boolean reloading;
 
+    /** The Log to use for diagnostic messages */
+    private Log logger = LogFactory.getLog(FileChangedReloadingStrategy.class);
+
     public void setConfiguration(FileConfiguration configuration)
     {
         this.configuration = configuration;
@@ -85,6 +90,10 @@
                 lastChecked = now;
                 if (hasChanged())
                 {
+                    if (logger.isDebugEnabled())
+                    {
+                        logger.debug("File change detected: " + getName());
+                    }
                     reloading = true;
                 }
             }
@@ -141,6 +150,11 @@
         File file = getFile();
         if (file == null || !file.exists())
         {
+            if (logger.isWarnEnabled() && lastModified != 0)
+            {
+                logger.warn("File was deleted: " + getName(file));
+                lastModified = 0;
+            }
             return false;
         }
 
@@ -186,4 +200,27 @@
             return ConfigurationUtils.fileFromURL(url);
         }
     }
+
+    private String getName()
+    {
+        return getName(getFile());
+    }
+
+    private String getName(File file)
+    {
+        String name = configuration.getURL().toString();
+        if (name == null)
+        {
+            if (file != null)
+            {
+                name = file.getAbsolutePath();
+            }
+            else
+            {
+                name = "base: " + configuration.getBasePath()
+                       + "file: " + configuration.getFileName();
+            }
+        }
+        return name;
+    }
 }

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/resolver/CatalogResolver.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/resolver/CatalogResolver.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/resolver/CatalogResolver.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/resolver/CatalogResolver.java Sat Oct 10 17:17:44 2009
@@ -23,6 +23,7 @@
 import org.apache.xml.resolver.Catalog;
 import org.apache.xml.resolver.readers.CatalogReader;
 import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.commons.logging.impl.NoOpLog;
 import org.apache.commons.configuration.FileSystem;
 import org.apache.commons.configuration.ConfigurationException;
@@ -199,7 +200,7 @@
             }
             catch (Exception e)
             {
-                log.debug("Failed to create InputSource for " + resolved + " ("
+                log.warn("Failed to create InputSource for " + resolved + " ("
                                 + e.toString() + ")");
                 return null;
             }
@@ -229,7 +230,7 @@
      */
     public void setLogger(Log log)
     {
-        this.log = (log != null) ? log : new NoOpLog();
+        this.log = (log != null) ? log : LogFactory.getLog(CatalogResolver.class);
     }
 
     private synchronized org.apache.xml.resolver.tools.CatalogResolver getResolver()

Propchange: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat Oct 10 17:17:44 2009
@@ -1 +1,2 @@
+/commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration:819412-822131
 /commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2:751544-751840,755692,757108

Modified: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java Sat Oct 10 17:17:44 2009
@@ -34,10 +34,13 @@
 import org.apache.commons.configuration.event.ConfigurationEvent;
 import org.apache.commons.configuration.event.ConfigurationListener;
 import org.apache.commons.configuration.reloading.FileAlwaysReloadingStrategy;
+import org.apache.commons.configuration.reloading.FileRandomReloadingStrategy;
 import org.apache.commons.configuration.tree.DefaultExpressionEngine;
 import org.apache.commons.configuration.tree.NodeCombiner;
 import org.apache.commons.configuration.tree.OverrideCombiner;
 import org.apache.commons.configuration.tree.UnionCombiner;
+import org.apache.commons.configuration.tree.MergeCombiner;
+import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
 
 /**
  * Test class for CombinedConfiguration.
@@ -764,6 +767,75 @@
                 .getInt("xmlReload1"));
     }
 
+    public void testConcurrentGetAndReload() throws Exception
+    {
+        final int threadCount = 5;
+        final int loopCount = 1000;
+        config.setForceReloadCheck(true);
+        config.setNodeCombiner(new MergeCombiner());
+        final XMLConfiguration xml = new XMLConfiguration("configA.xml");
+        xml.setReloadingStrategy(new FileRandomReloadingStrategy());
+        config.addConfiguration(xml);
+        final XMLConfiguration xml2 = new XMLConfiguration("configB.xml");
+        xml2.setReloadingStrategy(new FileRandomReloadingStrategy());
+        config.addConfiguration(xml2);
+        config.setExpressionEngine(new XPathExpressionEngine());
+
+        assertEquals(config.getString("/property[@name='config']/@value"), "100");
+
+        Thread testThreads[] = new Thread[threadCount];
+        int failures[] = new int[threadCount];
+
+        for (int i = 0; i < testThreads.length; ++i)
+        {
+            testThreads[i] = new ReloadThread(config, failures, i, loopCount);
+            testThreads[i].start();
+        }
+
+        int totalFailures = 0;
+        for (int i = 0; i < testThreads.length; ++i)
+        {
+            testThreads[i].join();
+            totalFailures += failures[i];
+        }
+        assertTrue(totalFailures + " failures Occurred", totalFailures == 0);
+    }
+
+    private class ReloadThread extends Thread
+    {
+        CombinedConfiguration combined;
+        int[] failures;
+        int index;
+        int count;
+
+        ReloadThread(CombinedConfiguration config, int[] failures, int index, int count)
+        {
+            combined = config;
+            this.failures = failures;
+            this.index = index;
+            this.count = count;
+        }
+        public void run()
+        {
+            failures[index] = 0;
+            for (int i = 0; i < count; i++)
+            {
+                try
+                {
+                    String value = combined.getString("/property[@name='config']/@value");
+                    if (value == null || !value.equals("100"))
+                    {
+                        ++failures[index];
+                    }
+                }
+                catch (Exception ex)
+                {
+                    ++failures[index];
+                }
+            }
+        }
+    }
+
     /**
      * Helper method for writing a file. The file is also added to a list and
      * will be deleted in teadDown() automatically.

Modified: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java Sat Oct 10 17:17:44 2009
@@ -21,12 +21,15 @@
 
 import junit.framework.TestCase;
 import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
+import org.apache.commons.lang.text.StrLookup;
 
 public class TestDynamicCombinedConfiguration extends TestCase
 {
     private static String PATTERN ="${sys:Id}";
     private static String PATTERN1 = "target/test-classes/testMultiConfiguration_${sys:Id}.xml";
     private static String DEFAULT_FILE = "target/test-classes/testMultiConfiguration_default.xml";
+    private static final File MULTI_TENENT_FILE = new File(
+            "conf/testMultiTenentConfigurationBuilder4.xml");
 
     public void testConfiguration() throws Exception
     {
@@ -57,9 +60,186 @@
         assertEquals("a\\,b\\,c", config.getString("split/list2"));
     }
 
+    public void testConcurrentGetAndReload() throws Exception
+    {
+        final int threadCount = 5;
+        final int loopCount = 500;
+        System.getProperties().remove("Id");
+        DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
+        factory.setFile(MULTI_TENENT_FILE);
+        CombinedConfiguration config = factory.getConfiguration(true);
+
+        assertEquals(config.getString("rowsPerPage"), "50");
+        Thread testThreads[] = new Thread[threadCount];
+        int failures[] = new int[threadCount];
+
+        for (int i = 0; i < testThreads.length; ++i)
+        {
+            testThreads[i] = new ReloadThread(config, failures, i, loopCount, false, null, "50");
+            testThreads[i].start();
+        }
+
+        int totalFailures = 0;
+        for (int i = 0; i < testThreads.length; ++i)
+        {
+            testThreads[i].join();
+            totalFailures += failures[i];
+        }
+        assertTrue(totalFailures + " failures Occurred", totalFailures == 0);
+    }
+
+    public void testConcurrentGetAndReload2() throws Exception
+    {
+        final int threadCount = 5;
+        final int loopCount = 500;
+        System.getProperties().remove("Id");
+        DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
+        factory.setFile(MULTI_TENENT_FILE);
+        CombinedConfiguration config = factory.getConfiguration(true);
+
+        assertEquals(config.getString("rowsPerPage"), "50");
+
+        Thread testThreads[] = new Thread[threadCount];
+        int failures[] = new int[threadCount];
+        System.setProperty("Id", "2002");
+        assertEquals(config.getString("rowsPerPage"), "25");
+        for (int i = 0; i < testThreads.length; ++i)
+        {
+            testThreads[i] = new ReloadThread(config, failures, i, loopCount, false, null, "25");
+            testThreads[i].start();
+        }
+
+        int totalFailures = 0;
+        for (int i = 0; i < testThreads.length; ++i)
+        {
+            testThreads[i].join();
+            totalFailures += failures[i];
+        }
+        System.getProperties().remove("Id");
+        assertTrue(totalFailures + " failures Occurred", totalFailures == 0);
+    }
+
+    public void testConcurrentGetAndReloadMultipleClients() throws Exception
+    {
+        final int threadCount = 5;
+        final int loopCount = 500;
+        System.getProperties().remove("Id");
+        DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
+        factory.setFile(MULTI_TENENT_FILE);
+        CombinedConfiguration config = factory.getConfiguration(true);
+
+        assertEquals(config.getString("rowsPerPage"), "50");
+
+        Thread testThreads[] = new Thread[threadCount];
+        int failures[] = new int[threadCount];
+        String[] ids = new String[] {null, "2002", "3001", "3002", "3003"};
+        String[] expected = new String[] {"50", "25", "15", "25", "50"};
+        for (int i = 0; i < testThreads.length; ++i)
+        {
+            testThreads[i] = new ReloadThread(config, failures, i, loopCount, true, ids[i], expected[i]);
+            testThreads[i].start();
+        }
+
+        int totalFailures = 0;
+        for (int i = 0; i < testThreads.length; ++i)
+        {
+            testThreads[i].join();
+            totalFailures += failures[i];
+        }
+        System.getProperties().remove("Id");
+        if (totalFailures != 0)
+        {
+            System.out.println("Failures:");
+            for (int i = 0; i < testThreads.length; ++i)
+            {
+                System.out.println("Thread " + i + " " + failures[i]);
+            }
+        }
+        assertTrue(totalFailures + " failures Occurred", totalFailures == 0);
+    }
+
+    private class ReloadThread extends Thread
+    {
+        CombinedConfiguration combined;
+        int[] failures;
+        int index;
+        int count;
+        String expected;
+        String id;
+        boolean useId;
+
+        ReloadThread(CombinedConfiguration config, int[] failures, int index, int count,
+                     boolean useId, String id, String expected)
+        {
+            combined = config;
+            this.failures = failures;
+            this.index = index;
+            this.count = count;
+            this.expected = expected;
+            this.id = id;
+            this.useId = useId;
+        }
+        public void run()
+        {
+            failures[index] = 0;
+
+            if (useId)
+            {
+                ThreadLookup.setId(id);
+            }
+            for (int i = 0; i < count; i++)
+            {
+                try
+                {
+                    String value = combined.getString("rowsPerPage", null);
+                    if (value == null || !value.equals(expected))
+                    {
+                        ++failures[index];
+                    }
+                }
+                catch (Exception ex)
+                {
+                    ++failures[index];
+                }
+            }
+        }
+    }
+
     private void verify(String key, DynamicCombinedConfiguration config, int rows)
     {
         System.setProperty("Id", key);
         assertTrue(config.getInt("rowsPerPage") == rows);
     }
+
+    public static class ThreadLookup extends StrLookup
+    {
+        private static ThreadLocal id = new ThreadLocal();
+
+
+
+        public ThreadLookup()
+        {
+
+        }
+
+        public static void setId(String value)
+        {
+            id.set(value);
+        }
+
+        public String lookup(String key)
+        {
+            if (key == null || !key.equals("Id"))
+            {
+                return null;
+            }
+            String value = System.getProperty("Id");
+            if (value != null)
+            {
+                return value;
+            }
+            return (String)id.get();
+
+        }
+    }
 }

Modified: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java Sat Oct 10 17:17:44 2009
@@ -19,6 +19,9 @@
 
 import junit.framework.TestCase;
 import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
+import org.xml.sax.SAXParseException;
+
+import java.io.*;
 
 /**
  * Unit test for simple MultiConfigurationTest.
@@ -27,6 +30,15 @@
 {
     private static String PATTERN1 = "target/test-classes/testMultiConfiguration_${sys:Id}.xml";
 
+    private static final File MULTI_TENENT_FILE = new File(
+            "conf/testMultiTenentConfigurationBuilder2.xml");
+
+    private static final File MULTI_TENENT_FILE2 = new File(
+            "target/test-classes/testMultiTenentConfigurationBuilder2.xml");
+
+    private static final File MULTI_RELOAD_FILE = new File(
+            "conf/testMultiTenentConfigurationBuilder3.xml");
+
     /**
      * Rigourous Test :-)
      */
@@ -48,4 +60,238 @@
         System.setProperty("Id", "1003");
         assertTrue(config.getInt("rowsPerPage") == 35);
     }
+
+    public void testSchemaValidationError() throws Exception
+    {
+        System.clearProperty("Id");
+        DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
+        factory.setFile(MULTI_TENENT_FILE);
+        CombinedConfiguration config = factory.getConfiguration(true);
+        try
+        {
+            System.setProperty("Id", "2001");
+            config.getInt("rowsPerPage");
+            fail("No exception thrown");
+        }
+        catch (Exception ex)
+        {
+            Throwable cause = ex.getCause();
+            while (cause != null && !(cause instanceof SAXParseException))
+            {
+                cause = cause.getCause();
+            }
+            assertTrue("SAXParseException was not thrown", cause instanceof SAXParseException);
+        }
+    }
+
+    public void testSchemaValidation() throws Exception
+    {
+        System.clearProperty("Id");
+        DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
+        factory.setFile(MULTI_TENENT_FILE);
+        CombinedConfiguration config = factory.getConfiguration(true);
+        System.setProperty("Id", "2002");
+        int rows = config.getInt("rowsPerPage");
+        assertTrue("expected: " + rows + " actual: " + "25", 25 == rows);
+    }
+
+    public void testMissingFile() throws Exception
+    {
+        System.clearProperty("Id");
+        DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
+        factory.setFile(MULTI_TENENT_FILE);
+        CombinedConfiguration config = factory.getConfiguration(true);
+        System.setProperty("Id", "3099");
+        int rows = config.getInt("rowsPerPage");
+        assertTrue("expected: " + rows + " actual: " + "50", 50 == rows);
+
+    }
+
+    public void testFileReload1() throws Exception
+    {
+        System.getProperties().remove("Id");
+        DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
+        factory.setFile(MULTI_RELOAD_FILE);
+        CombinedConfiguration config = factory.getConfiguration(true);
+
+        // create a new configuration
+        File input = new File("target/test-classes/testMultiConfiguration_3001.xml");
+        File output = new File("target/test-classes/testwrite/testMultiConfiguration_3001.xml");
+        output.delete();
+        output.getParentFile().mkdir();
+        copyFile(input, output);
+
+        assertNotNull(config);
+        verify("3001", config, 15);
+        Thread.sleep(1100);
+        XMLConfiguration x = new XMLConfiguration();
+        x.setFile(output);
+        x.setAttributeSplittingDisabled(true);
+        x.setDelimiterParsingDisabled(true);
+        x.load();
+        x.setProperty("rowsPerPage", "35");
+        //Insure orginal timestamp and new timestamp aren't the same second.
+        Thread.sleep(1100);
+        x.save();
+        verify("3001", config, 35);
+        output.delete();
+    }
+
+    public void testFileReload2() throws Exception
+    {
+        // create a new configuration
+        File input = new File("target/test-classes/testMultiConfiguration_3002.xml");
+        File output = new File("target/test-classes/testwrite/testMultiConfiguration_3002.xml");
+        output.delete();
+
+        System.getProperties().remove("Id");
+        DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
+        factory.setFile(MULTI_RELOAD_FILE);
+        CombinedConfiguration config = factory.getConfiguration(true);
+        assertNotNull(config);
+        // The file should not exist yet.
+        verify("3002", config, 50);
+
+        output.getParentFile().mkdir();
+        copyFile(input, output);
+        Thread.sleep(600);
+        verify("3002", config, 25);
+        output.delete();
+    }
+
+    public void testFileReload3() throws Exception
+    {
+        // create a new configuration
+        File input = new File("target/test-classes/testMultiConfiguration_3001.xml");
+        File output = new File("target/test-classes/testwrite/testMultiConfiguration_3001.xml");
+        output.delete();
+        output.getParentFile().mkdir();
+
+        System.getProperties().remove("Id");
+        DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
+        factory.setFile(MULTI_RELOAD_FILE);
+        CombinedConfiguration config = factory.getConfiguration(true);
+        assertNotNull(config);
+        //The file does not exist yet.
+        verify("3001", config, 50);
+        copyFile(input, output);
+        //Sleep so refreshDelay elapses
+        Thread.sleep(600);
+        verify("3001", config, 15);
+        Thread.sleep(500);
+        XMLConfiguration x = new XMLConfiguration();
+        x.setFile(output);
+        x.setAttributeSplittingDisabled(true);
+        x.setDelimiterParsingDisabled(true);
+        x.load();
+        x.setProperty("rowsPerPage", "35");
+        // Insure original timestamp and new timestamp are not the same second.
+        Thread.sleep(1100);
+        x.save();
+        verify("3001", config, 35);
+        output.delete();
+    }
+
+
+    public void testReloadDefault() throws Exception
+    {
+        // create a new configuration
+        String defaultName = "target/test-classes/testMultiConfiguration_default.xml";
+        File input = new File(defaultName);
+
+        System.getProperties().remove("Id");
+        DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
+        factory.setFile(MULTI_TENENT_FILE2);
+        CombinedConfiguration config = factory.getConfiguration(true);
+        assertNotNull(config);
+        verify("3001", config, 15);
+        verify("3002", config, 25);
+        System.setProperty("Id", "3002");
+        config.addProperty("/ TestProp", "Test");
+        assertTrue("Property not added", "Test".equals(config.getString("TestProp")));
+        System.getProperties().remove("Id");
+        //Sleep so refreshDelay elapses
+        Thread.sleep(600);
+        long time = System.currentTimeMillis();
+        long original = input.lastModified();
+        input.setLastModified(time);
+        File defaultFile = new File(defaultName);
+        long newTime = defaultFile.lastModified();
+        assertTrue("time mismatch", original != newTime);
+        Thread.sleep(600);
+        verify("3001", config, 15);
+        verify("3002", config, 25);
+        System.setProperty("Id", "3002");
+        String test = config.getString("TestProp");
+        assertNull("Property was not cleared by reload", test);
+    }
+
+
+    public void testFileReloadSchemaValidationError() throws Exception
+    {
+        System.getProperties().remove("Id");
+        DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
+        factory.setFile(MULTI_RELOAD_FILE);
+        CombinedConfiguration config = factory.getConfiguration(true);
+
+        // create a new configuration
+        File input = new File("target/test-classes/testMultiConfiguration_3001.xml");
+        File output = new File("target/test-classes/testwrite/testMultiConfiguration_3001.xml");
+        output.delete();
+        output.getParentFile().mkdir();
+        copyFile(input, output);
+
+        assertNotNull(config);
+        verify("3001", config, 15);
+        Thread.sleep(1100);
+        XMLConfiguration x = new XMLConfiguration();
+        x.setFile(output);
+        x.setAttributeSplittingDisabled(true);
+        x.setDelimiterParsingDisabled(true);
+        x.load();
+        x.setProperty("rowsPerPage", "test");
+        //Insure orginal timestamp and new timestamp aren't the same second.
+        Thread.sleep(1100);
+        x.save();
+        System.setProperty("Id", "3001");
+        try
+        {
+            config.getInt("rowsPerPage");
+            fail("No exception was thrown");
+        }
+        catch (Exception ex)
+        {
+
+        }
+
+        output.delete();
+    }    
+
+    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)
+    {
+        if (key == null)
+        {
+            System.getProperties().remove("Id");
+        }
+        else
+        {
+            System.setProperty("Id", key);
+        }
+        int actual = config.getInt("rowsPerPage");
+        assertTrue("expected: " + rows + " actual: " + actual, actual == rows);
+    }
 }

Modified: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java?rev=823891&r1=823890&r2=823891&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java (original)
+++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java Sat Oct 10 17:17:44 2009
@@ -31,11 +31,8 @@
 
 import org.apache.commons.configuration.beanutils.BeanHelper;
 import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
-import org.apache.commons.configuration.reloading.VFSFileMonitorReloadingStrategy;
 import org.apache.commons.configuration.tree.DefaultConfigurationNode;
 import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
-import org.apache.commons.configuration.event.ConfigurationListener;
-import org.apache.commons.configuration.event.ConfigurationEvent;
 
 /**
  * Test class for DefaultConfigurationBuilder.
@@ -43,7 +40,7 @@
  * @author Oliver Heger
  * @version $Id$
  */
-public class TestVFSConfigurationBuilder extends TestCase implements ConfigurationListener
+public class TestVFSConfigurationBuilder extends TestCase
 {
     /** Test configuration definition file. */
     private static final File TEST_FILE = new File(
@@ -91,30 +88,21 @@
     private static final File FILESYSTEM_FILE = new File(
             "conf/testFileSystem.xml");
 
-    private static final File FILEMONITOR_FILE = new File(
-            "target/test-classes/testFileMonitorConfigurationBuilder.xml");
+    private static final File FILERELOAD_FILE = new File(
+            "target/test-classes/testFileReloadConfigurationBuilder.xml");
 
-    private static final File FILEMONITOR2_FILE = new File(
-            "target/test-classes/testFileMonitorConfigurationBuilder2.xml");
+      private static final File MULTI_RELOAD_FILE1 = new File(
+            "target/test-classes/testVFSMultiTenentConfigurationBuilder1.xml");
 
-    private static final String FILEMONITOR_URI = "file://" + System.getProperty("user.dir")
-            + "/target/test-classes/testFileMonitorConfigurationBuilder2.xml";
+    private static final File MULTI_RELOAD_FILE2 = new File(
+            "target/test-classes/testVFSMultiTenentConfigurationBuilder2.xml");
 
     /** Constant for the name of an optional configuration.*/
     private static final String OPTIONAL_NAME = "optionalConfig";
 
-    /** true when a file is changed */
-    private boolean configChanged = false;
-
     /** Stores the object to be tested. */
     DefaultConfigurationBuilder factory;
 
-    public TestVFSConfigurationBuilder()
-    {
-        super();
-        VFSFileMonitorReloadingStrategy.stopMonitor();
-    }
-
     protected void setUp() throws Exception
     {
         super.setUp();
@@ -1005,7 +993,7 @@
         }
     }
 
-    public void testFileMonitor1() throws Exception
+    public void testFileReload1() throws Exception
     {
         // create a new configuration
         File input = new File("target/test-classes/testMultiConfiguration_1001.xml");
@@ -1013,116 +1001,147 @@
         output.delete();
         output.getParentFile().mkdir();
         copyFile(input, output);
+        // Sleep to make sure the file timestamp is not in the same second as "now".
+        Thread.sleep(1100);
 
-        factory.setFile(FILEMONITOR_FILE);
+        factory.setFile(FILERELOAD_FILE);
         FileSystem.resetDefaultFileSystem();
         System.getProperties().remove("Id");
 
         CombinedConfiguration config = factory.getConfiguration(true);
         assertNotNull(config);
-        config.addConfigurationListener(this);
         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();
-
-        waitForChange();
         verify("1001", config, 50);
         output.delete();
-        VFSFileMonitorReloadingStrategy.stopMonitor();
     }
 
-    public void testFileMonitor2() throws Exception
+    public void testFileReload2() throws Exception
     {
         // create a new configuration
         File input = new File("target/test-classes/testMultiConfiguration_1002.xml");
         File output = new File("target/test-classes/testwrite/testMultiConfiguration_1002.xml");
         output.delete();
 
-        factory.setFile(FILEMONITOR_FILE);
+        factory.setFile(FILERELOAD_FILE);
         FileSystem.resetDefaultFileSystem();
         System.getProperties().remove("Id");
 
         CombinedConfiguration config = factory.getConfiguration(true);
-        config.addConfigurationListener(this);
         assertNotNull(config);
 
         verify("1002", config, 50);
-        Thread.sleep(1000);
-
+        // Sleep to make sure the file timestamp is not in the same second as "now".
+        Thread.sleep(1100);
         output.getParentFile().mkdir();
         copyFile(input, output);
-
-        // Allow time for the monitor to notice the change.
-        //Thread.sleep(2000);
-        waitForChange();
         verify("1002", config, 25);
         output.delete();
-        VFSFileMonitorReloadingStrategy.stopMonitor();
     }
 
-
-    public void testFileMonitor3() throws Exception
+    public void testFileReload3() 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.delete();
         output.getParentFile().mkdir();
-        copyFile(input, output);
 
-        factory.setFile(FILEMONITOR2_FILE);
+        factory.setFile(FILERELOAD_FILE);
+        FileSystem.resetDefaultFileSystem();
         System.getProperties().remove("Id");
 
         CombinedConfiguration config = factory.getConfiguration(true);
         assertNotNull(config);
-        config.addConfigurationListener(this);
+        verify("1001", config, 50);
+        copyFile(input, output);
+        // Sleep to make sure the file timestamp is not in the same second as "now".
+        Thread.sleep(1100);
         verify("1001", config, 15);
-
-        // Allow time for FileMonitor to set up.
-        Thread.sleep(1000);
         XMLConfiguration x = new XMLConfiguration(output);
-        x.setProperty("rowsPerPage", "50");
+        x.setProperty("rowsPerPage", "25");
         x.save();
-        // Let FileMonitor detect the change.
-        //Thread.sleep(2000);
-        waitForChange();
-        verify("1001", config, 50);
+         // Sleep to make sure the file timestamp is not in the same second as "now".
+        Thread.sleep(1100);
+        verify("1001", config, 25);
         output.delete();
-        VFSFileMonitorReloadingStrategy.stopMonitor();
     }
 
-    public void testFileMonitor4() throws Exception
+    public void testReloadDefault() throws Exception
     {
         // create a new configuration
-        File input = new File("target/test-classes/testMultiConfiguration_1002.xml");
-        File output = new File("target/test-classes/testwrite/testMultiConfiguration_1002.xml");
-        output.delete();
+        String defaultName = "target/test-classes/testMultiConfiguration_default.xml";
+        File input = new File(defaultName);
 
-        factory.setFileName(FILEMONITOR_URI);
         System.getProperties().remove("Id");
-
+        factory.setFile(MULTI_RELOAD_FILE1);
         CombinedConfiguration config = factory.getConfiguration(true);
         assertNotNull(config);
-        config.addConfigurationListener(this);
+        verify("3001", config, 15);
+        verify("3002", config, 25);
+        System.setProperty("Id", "3002");
+        config.addProperty("/ TestProp", "Test");
+        assertTrue("Property not added", "Test".equals(config.getString("TestProp")));
+        System.getProperties().remove("Id");
+        //Sleep so refreshDelay elapses
+        Thread.sleep(600);
+        long time = System.currentTimeMillis();
+        long original = input.lastModified();
+        input.setLastModified(time);
+        File defaultFile = new File(defaultName);
+        long newTime = defaultFile.lastModified();
+        assertTrue("time mismatch", original != newTime);
+        Thread.sleep(600);
+        verify("3001", config, 15);
+        verify("3002", config, 25);
+        System.setProperty("Id", "3002");
+        String test = config.getString("TestProp");
+        assertNull("Property was not cleared by reload", test);
+    }
 
-        verify("1002", config, 50);
-        Thread.sleep(1000);
 
+    public void testFileReloadSchemaValidationError() throws Exception
+    {
+        System.getProperties().remove("Id");
+        factory.setFile(MULTI_RELOAD_FILE2);
+        CombinedConfiguration config = factory.getConfiguration(true);
+
+        // create a new configuration
+        File input = new File("target/test-classes/testMultiConfiguration_3001.xml");
+        File output = new File("target/test-classes/testwrite/testMultiConfiguration_3001.xml");
+        output.delete();
         output.getParentFile().mkdir();
         copyFile(input, output);
 
-        // Allow time for the monitor to notice the change.
-        //Thread.sleep(2000);
-        waitForChange();
-        verify("1002", config, 25);
+        assertNotNull(config);
+        verify("3001", config, 15);
+        Thread.sleep(1100);
+        XMLConfiguration x = new XMLConfiguration();
+        x.setFile(output);
+        x.setAttributeSplittingDisabled(true);
+        x.setDelimiterParsingDisabled(true);
+        x.load();
+        x.setProperty("rowsPerPage", "test");
+        //Insure orginal timestamp and new timestamp aren't the same second.
+        Thread.sleep(1100);
+        x.save();
+        System.setProperty("Id", "3001");
+        try
+        {
+            config.getInt("rowsPerPage");
+            fail("No exception was thrown");
+        }
+        catch (Exception ex)
+        {
+
+        }
+
         output.delete();
-        VFSFileMonitorReloadingStrategy.stopMonitor();
     }
 
+
     private void copyFile(File input, File output) throws IOException
     {
         Reader reader = new FileReader(input);
@@ -1151,39 +1170,4 @@
         int actual = config.getInt("rowsPerPage");
         assertTrue("expected: " + rows + " actual: " + actual, actual == rows);
     }
-
-    private void waitForChange()
-    {
-        synchronized(this)
-        {
-            try
-            {
-                int count = 0;
-                while (!configChanged && count++ <= 3)
-                {
-                    this.wait(5000);
-                }
-            }
-            catch (InterruptedException ie)
-            {
-                throw new IllegalStateException("wait timed out");
-            }
-            finally
-            {
-                configChanged = false;
-            }
-        }
-    }
-
-    public void configurationChanged(ConfigurationEvent event)
-    {
-        if (event.getType() == AbstractFileConfiguration.EVENT_CONFIG_CHANGED)
-        {
-            synchronized(this)
-            {
-                configChanged = true;
-                this.notify();
-            }
-        }
-    }
 }
\ No newline at end of file



Mime
View raw message