You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by rg...@apache.org on 2009/09/28 00:28:18 UTC

svn commit: r819418 [2/2] - in /commons/proper/configuration/branches/CONFIGURATION_390: ./ conf/ src/java/org/apache/commons/configuration/ src/java/org/apache/commons/configuration/reloading/ src/test/org/apache/commons/configuration/ src/test/org/ap...

Modified: commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java?rev=819418&r1=819417&r2=819418&view=diff
==============================================================================
--- commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java (original)
+++ commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java Sun Sep 27 22:28:16 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/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java?rev=819418&r1=819417&r2=819418&view=diff
==============================================================================
--- commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java (original)
+++ commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java Sun Sep 27 22:28:16 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/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java?rev=819418&r1=819417&r2=819418&view=diff
==============================================================================
--- commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java (original)
+++ commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java Sun Sep 27 22:28:16 2009
@@ -31,7 +31,6 @@
 
 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;
@@ -91,14 +90,17 @@
     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 FILERELOAD2_FILE = new File(
+            "target/test-classes/testFileReloadConfigurationBuilder2.xml");
 
-    private static final String FILEMONITOR_URI = "file://" + System.getProperty("user.dir")
-            + "/target/test-classes/testFileMonitorConfigurationBuilder2.xml";
+      private static final File MULTI_RELOAD_FILE1 = new File(
+            "target/test-classes/testVFSMultiTenentConfigurationBuilder1.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";
@@ -109,12 +111,6 @@
     /** Stores the object to be tested. */
     DefaultConfigurationBuilder factory;
 
-    public TestVFSConfigurationBuilder()
-    {
-        super();
-        VFSFileMonitorReloadingStrategy.stopMonitor();
-    }
-
     protected void setUp() throws Exception
     {
         super.setUp();
@@ -1005,7 +1001,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 +1009,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);
@@ -1161,7 +1188,11 @@
                 int count = 0;
                 while (!configChanged && count++ <= 3)
                 {
-                    this.wait(5000);
+                    this.wait(2000);
+                }
+                if (!configChanged)
+                {
+                  throw new IllegalStateException("No change detected");
                 }
             }
             catch (InterruptedException ie)

Modified: commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestWebdavConfigurationBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestWebdavConfigurationBuilder.java?rev=819418&r1=819417&r2=819418&view=diff
==============================================================================
--- commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestWebdavConfigurationBuilder.java (original)
+++ commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestWebdavConfigurationBuilder.java Sun Sep 27 22:28:16 2009
@@ -21,7 +21,6 @@
 import java.io.Reader;
 import java.io.FileReader;
 import java.io.Writer;
-import java.io.FileWriter;
 import java.io.OutputStreamWriter;
 import java.util.Collection;
 import java.util.HashMap;
@@ -32,7 +31,6 @@
 
 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.ConfigurationEvent;
@@ -42,7 +40,6 @@
 import org.apache.commons.vfs.VFS;
 import org.apache.commons.vfs.FileName;
 import org.apache.commons.vfs.FileSystemOptions;
-import org.apache.commons.vfs.FileContent;
 
 /**
  * Test class for DefaultConfigurationBuilder.
@@ -93,13 +90,13 @@
     private static final String MULTI_TENENT_FILE =
             "testMultiTenentConfigurationBuilder.xml";
 
-    private static final String FILEMONITOR2_FILE =
-            "testFileMonitorConfigurationBuilder2.xml";
+    private static final String FILERELOAD2_FILE =
+            "testFileReloadConfigurationBuilder2.xml";
 
-    private static final String FILEMONITOR_1001_FILE =
+    private static final String FILERELOAD_1001_FILE =
             "testwrite/testMultiConfiguration_1001.xml";
 
-    private static final String FILEMONITOR_1002_FILE =
+    private static final String FILERELOAD_1002_FILE =
             "testwrite/testMultiConfiguration_1002.xml";
 
     private static final String TEST_PROPERTIES = "test.properties.xml";
@@ -900,16 +897,16 @@
         verify("1005", config, 50);
     }
 
-    public void testFileMonitor1() throws Exception
+    public void testFileChanged() throws Exception
     {
         // create a new configuration
         File input = new File("target/test-classes/testMultiConfiguration_1001.xml");
-        FileObject output = getFile(getBasePath() + FILEMONITOR_1001_FILE);
+        FileObject output = getFile(getBasePath() + FILERELOAD_1001_FILE);
         output.delete();
         output.getParent().createFolder();
         copyFile(input, output);
 
-        factory.setFileName(getBasePath() + FILEMONITOR2_FILE);
+        factory.setFileName(getBasePath() + FILERELOAD2_FILE);
         System.getProperties().remove("Id");
 
         CombinedConfiguration config = factory.getConfiguration(true);
@@ -919,7 +916,7 @@
 
         // Allow time for FileMonitor to set up.
         Thread.sleep(1000);
-        XMLConfiguration x = new XMLConfiguration(getBasePath() + FILEMONITOR_1001_FILE);
+        XMLConfiguration x = new XMLConfiguration(getBasePath() + FILERELOAD_1001_FILE);
         x.setProperty("rowsPerPage", "50");
         x.save();
         // Let FileMonitor detect the change.
@@ -927,17 +924,16 @@
         waitForChange();
         verify("1001", config, 50);
         output.delete();
-        VFSFileMonitorReloadingStrategy.stopMonitor();
     }
 
-    public void testFileMonitor2() throws Exception
+    public void testFileChanged2() throws Exception
     {
         // create a new configuration
         File input = new File("target/test-classes/testMultiConfiguration_1002.xml");
-        FileObject output = getFile(getBasePath() + FILEMONITOR_1002_FILE);
+        FileObject output = getFile(getBasePath() + FILERELOAD_1002_FILE);
         output.delete();
 
-        factory.setFileName(getBasePath() + FILEMONITOR2_FILE);
+        factory.setFileName(getBasePath() + FILERELOAD2_FILE);
         System.getProperties().remove("Id");
 
         CombinedConfiguration config = factory.getConfiguration(true);
@@ -955,7 +951,6 @@
         waitForChange();
         verify("1002", config, 25);
         output.delete();
-        VFSFileMonitorReloadingStrategy.stopMonitor();
     }
 
 

Modified: commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestXMLConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestXMLConfiguration.java?rev=819418&r1=819417&r2=819418&view=diff
==============================================================================
--- commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestXMLConfiguration.java (original)
+++ commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/TestXMLConfiguration.java Sun Sep 27 22:28:16 2009
@@ -1597,6 +1597,50 @@
         }
     }
 
+    public void testConcurrentGetAndReload() throws Exception
+    {
+        //final FileConfiguration config = new PropertiesConfiguration("test.properties");
+        final FileConfiguration config = new XMLConfiguration("test.xml");
+        config.setReloadingStrategy(new FileAlwaysReloadingStrategy());
+
+        assertTrue("Property not found", config.getProperty("test.short") != null);
+
+        Thread testThreads[] = new Thread[5];
+
+        for (int i = 0; i < testThreads.length; ++i)
+        {
+            testThreads[i] = new ReloadThread(config);
+            testThreads[i].start();
+        }
+
+        for (int i = 0; i < 2000; i++)
+        {
+            assertTrue("Property not found", config.getProperty("test.short") != null); 
+        }
+
+        for (int i = 0; i < testThreads.length; ++i)
+        {
+            testThreads[i].join();
+        }
+    }
+
+    private class ReloadThread extends Thread
+    {
+        FileConfiguration config;
+
+        ReloadThread(FileConfiguration config)
+        {
+            this.config = config;
+        }
+        public void run()
+        {
+            for (int i = 0; i < 1000; i++)
+            {
+                config.reload();
+            }
+        }
+    }
+
     /**
      * Prepares a configuration object for testing a reload operation.
      *

Added: commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/FileRandomReloadingStrategy.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/FileRandomReloadingStrategy.java?rev=819418&view=auto
==============================================================================
--- commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/FileRandomReloadingStrategy.java (added)
+++ commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/FileRandomReloadingStrategy.java Sun Sep 27 22:28:16 2009
@@ -0,0 +1,31 @@
+package org.apache.commons.configuration.reloading;
+
+import java.io.File;
+import java.util.Random;
+
+/**
+ * A ReloadingStrategy that randomly returns true or false;
+ */
+public class FileRandomReloadingStrategy extends FileChangedReloadingStrategy
+{
+    Random random = new Random();
+    /**
+     * Checks whether a reload is necessary.
+     *
+     * @return a flag whether a reload is required
+     */
+    public boolean reloadingRequired()
+    {
+        return random.nextBoolean();
+    }
+
+    /**
+     * Returns the file that is watched by this strategy.
+     *
+     * @return the monitored file
+     */
+    public File getMonitoredFile()
+    {
+        return getFile();
+    }
+}

Modified: commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/TestFileChangedReloadingStrategy.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/TestFileChangedReloadingStrategy.java?rev=819418&r1=819417&r2=819418&view=diff
==============================================================================
--- commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/TestFileChangedReloadingStrategy.java (original)
+++ commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/TestFileChangedReloadingStrategy.java Sun Sep 27 22:28:16 2009
@@ -19,6 +19,7 @@
 
 import java.io.File;
 import java.io.FileWriter;
+import java.io.ByteArrayOutputStream;
 import java.net.URL;
 
 import junit.framework.TestCase;
@@ -26,6 +27,12 @@
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.PropertiesConfiguration;
 import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.log4j.Logger;
+import org.apache.log4j.Layout;
+import org.apache.log4j.PatternLayout;
+import org.apache.log4j.Appender;
+import org.apache.log4j.WriterAppender;
+import org.apache.log4j.Level;
 
 /**
  * Test case for the ReloadableConfiguration class.
@@ -163,4 +170,46 @@
         strategy.reloadingPerformed();
         assertFalse("Reloading still required", strategy.reloadingRequired());
     }
+
+    public void testFileDeletion() throws Exception
+    {
+        Logger logger = Logger.getLogger(FileChangedReloadingStrategy.class.getName());
+        Layout layout = new PatternLayout("%p - %m%n");
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        Appender appender = new WriterAppender(layout, os);
+        logger.addAppender(appender);
+        logger.setLevel(Level.WARN);
+        logger.setAdditivity(false);
+        // create a new configuration
+        File file = new File("target/testReload.properties");
+
+        if (file.exists())
+        {
+            file.delete();
+        }
+
+        // create the configuration file
+        FileWriter out = new FileWriter(file);
+        out.write("string=value1");
+        out.flush();
+        out.close();
+
+        // load the configuration
+        PropertiesConfiguration config = new PropertiesConfiguration("target/testReload.properties");
+        FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();
+        strategy.setRefreshDelay(500);
+        config.setReloadingStrategy(strategy);
+        assertEquals("Initial value", "value1", config.getString("string"));
+
+        Thread.sleep(2000);
+
+        // Delete the file.
+        file.delete();
+        //Old value should still be returned.
+        assertEquals("Initial value", "value1", config.getString("string"));
+        logger.removeAppender(appender);
+        String str = os.toString();
+        //System.out.println(str);
+        assertTrue("No error was logged", str != null && str.length() > 0);
+    }
 }

Copied: commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/TestVFSFileChangedReloadingStrategy.java (from r805888, commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/reloading/TestVFSFileMonitorReloadingStrategy.java)
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/TestVFSFileChangedReloadingStrategy.java?p2=commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/TestVFSFileChangedReloadingStrategy.java&p1=commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/reloading/TestVFSFileMonitorReloadingStrategy.java&r1=805888&r2=819418&rev=819418&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/reloading/TestVFSFileMonitorReloadingStrategy.java (original)
+++ commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/TestVFSFileChangedReloadingStrategy.java Sun Sep 27 22:28:16 2009
@@ -38,11 +38,10 @@
  * @author Ralph Goers
  * @version $Revision$
  */
-public class TestVFSFileMonitorReloadingStrategy extends TestCase
-        implements ConfigurationListener
+public class TestVFSFileChangedReloadingStrategy extends TestCase
 {
-    /** true when a file is changed */
-    private boolean configChanged = false;
+    /** Constant for the name of a test properties file.*/
+    private static final String TEST_FILE = "test.properties";
 
     protected void setUp() throws Exception
     {
@@ -74,12 +73,12 @@
 
         // load the configuration
         PropertiesConfiguration config = new PropertiesConfiguration("target/testReload.properties");
-        VFSFileMonitorReloadingStrategy strategy = new VFSFileMonitorReloadingStrategy();
-        strategy.setDelay(500);
+        VFSFileChangedReloadingStrategy strategy = new VFSFileChangedReloadingStrategy();
+        strategy.setRefreshDelay(500);
         config.setReloadingStrategy(strategy);
         assertEquals("Initial value", "value1", config.getString("string"));
 
-        Thread.sleep(1000);
+        Thread.sleep(2000);
 
         // change the file
         out = new FileWriter(file);
@@ -87,15 +86,8 @@
         out.flush();
         out.close();
 
-        Thread.sleep(2000);
-
         // test the automatic reloading
         assertEquals("Modified value with enabled reloading", "value2", config.getString("string"));
-        strategy.stopMonitor();
-        if (file.exists())
-        {
-            file.delete();
-        }
     }
 
     public void testNewFileReloading() throws Exception
@@ -110,9 +102,8 @@
 
         PropertiesConfiguration config = new PropertiesConfiguration();
         config.setFile(file);
-        config.addConfigurationListener(this);
-        VFSFileMonitorReloadingStrategy strategy = new VFSFileMonitorReloadingStrategy();
-        strategy.setDelay(500);
+        VFSFileChangedReloadingStrategy strategy = new VFSFileChangedReloadingStrategy();
+        strategy.setRefreshDelay(500);
         config.setReloadingStrategy(strategy);
 
         assertNull("Initial value", config.getString("string"));
@@ -123,106 +114,40 @@
         out.flush();
         out.close();
 
-        waitForChange();
+        Thread.sleep(2000);
 
         // test the automatic reloading
-        try
-        {
-            assertEquals("Modified value with enabled reloading", "value1", config.getString("string"));
-        }
-        finally
-        {
-            strategy.stopMonitor();
-            if (file.exists())
-            {
-                file.delete();
-            }
-        }
+        assertEquals("Modified value with enabled reloading", "value1", config.getString("string"));
     }
 
     public void testGetRefreshDelay() throws Exception
     {
-        // create a new configuration
-        File file = new File("target/testReload.properties");
-
-        if (file.exists())
-        {
-            file.delete();
-        }
-
-        // create the configuration file
-        FileWriter out = new FileWriter(file);
-        out.write("string=value1");
-        out.flush();
-        out.close();
-
-        PropertiesConfiguration config = new PropertiesConfiguration("target/testReload.properties");
-        VFSFileMonitorReloadingStrategy strategy = new VFSFileMonitorReloadingStrategy();
-        strategy.setDelay(500);
-        config.setReloadingStrategy(strategy);
-        // Minimum is 1 second.
-        assertEquals("refresh delay", 1000, strategy.getDelay());
-
-        config = new PropertiesConfiguration("target/testReload.properties");
-        strategy = new VFSFileMonitorReloadingStrategy();
-        strategy.setDelay(1500);
-        config.setReloadingStrategy(strategy);
-        // Can be made longer
-        assertEquals("refresh delay", 1500, strategy.getDelay());
-
-        config = new PropertiesConfiguration("target/testReload.properties");
-        strategy = new VFSFileMonitorReloadingStrategy();
-        strategy.setDelay(500);
-        config.setReloadingStrategy(strategy);
-        // Can't be made shorter
-        assertEquals("refresh delay", 1500, strategy.getDelay());
-
-        strategy.stopMonitor();
-        // Reset and verify everything clears
-        config = new PropertiesConfiguration("target/testReload.properties");
-        strategy = new VFSFileMonitorReloadingStrategy();
-        strategy.setDelay(1100);
-        config.setReloadingStrategy(strategy);
-        assertEquals("refresh delay", 1100, strategy.getDelay());
-        strategy.stopMonitor();
-        if (file.exists())
-        {
-            file.delete();
-        }
-    }
-
-    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;
-            }
-        }
+        VFSFileChangedReloadingStrategy strategy = new VFSFileChangedReloadingStrategy();
+        strategy.setRefreshDelay(500);
+        assertEquals("refresh delay", 500, strategy.getRefreshDelay());
     }
 
-    public void configurationChanged(ConfigurationEvent event)
+    /**
+     * Tests calling reloadingRequired() multiple times before a reload actually
+     * happens. This test is related to CONFIGURATION-302.
+     */
+    public void testReloadingRequiredMultipleTimes()
+            throws ConfigurationException
     {
-        if (event.getType() == AbstractFileConfiguration.EVENT_CONFIG_CHANGED)
+        VFSFileChangedReloadingStrategy strategy = new VFSFileChangedReloadingStrategy()
         {
-            synchronized(this)
+            protected boolean hasChanged()
             {
-                configChanged = true;
-                this.notify();
+                // signal always a change
+                return true;
             }
-        }
+        };
+        strategy.setRefreshDelay(100000);
+        PropertiesConfiguration config = new PropertiesConfiguration(TEST_FILE);
+        config.setReloadingStrategy(strategy);
+        assertTrue("Reloading not required", strategy.reloadingRequired());
+        assertTrue("Reloading no more required", strategy.reloadingRequired());
+        strategy.reloadingPerformed();
+        assertFalse("Reloading still required", strategy.reloadingRequired());
     }
 }
\ No newline at end of file

Modified: commons/proper/configuration/branches/CONFIGURATION_390/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_390/xdocs/changes.xml?rev=819418&r1=819417&r2=819418&view=diff
==============================================================================
--- commons/proper/configuration/branches/CONFIGURATION_390/xdocs/changes.xml (original)
+++ commons/proper/configuration/branches/CONFIGURATION_390/xdocs/changes.xml Sun Sep 27 22:28:16 2009
@@ -23,6 +23,13 @@
 
   <body>
     <release version="1.7" date="in SVN" description="">
+      <action dev="rgoers" type="fix" issue="CONFIGURATION-397">
+        Schema violation exceptions are now propagated back to the caller.
+      </action>
+       <action dev="rgoers" type="fix" issue="CONFIGURATION-390">
+        XMLConfiguration and CombinedConfiguraton are now synchronized to fix problems
+        caused by reloading in a multithreaded environment.
+      </action>
       <action dev="oheger" type="fix" issue="CONFIGURATION-396">
         HierarchicalConfiguration.NodeVisitor is now passed the correct key to
         its visitAfterChildren() method.

Modified: commons/proper/configuration/branches/CONFIGURATION_390/xdocs/userguide/howto_filesystems.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_390/xdocs/userguide/howto_filesystems.xml?rev=819418&r1=819417&r2=819418&view=diff
==============================================================================
--- commons/proper/configuration/branches/CONFIGURATION_390/xdocs/userguide/howto_filesystems.xml (original)
+++ commons/proper/configuration/branches/CONFIGURATION_390/xdocs/userguide/howto_filesystems.xml Sun Sep 27 22:28:16 2009
@@ -77,7 +77,7 @@
     </xml>
   </override>
 </configuration>
-]]></source>       
+]]></source>
       </subsection>
       <subsection name="File Options Provider">
         <p>
@@ -95,15 +95,11 @@
       </subsection>
       <subsection name="File Reloading Strategy">
         <p>
-          The <code><a href="../apidocs/org/apache/commons/configuration/reloading/VFSFileMonitorReloadingStrategy.html">VFSFileMonitorReloadingStrategy</a></code>
+          The <code><a href="../apidocs/org/apache/commons/configuration/reloading/VFSFileChangedReloadingStrategy.html">VFSFileChangedReloadingStrategy</a></code>
           can be used to cause Configurations accessed via the <code>VFSFileSystem</code> to be
           monitored and reloaded when the files are modified. The example below shows how
           <code>DefaultConfigurationBuilder</code> can be configured to use
-          <code>VFSFileMonitorReloadingStrategy</code>. While each declaration will result in
-          a new reloading strategy object, each instance will share a common <code>FileMonitor</code>.
-          The delay setting controls how often the <code>FileMonitor</code> checks for changes
-          and since there is only a single <code>FileMonitor</code>, only the largest value
-          specified on any <code>VFSFileMonitorReloadingStrategy</code> is used.
+          <code>VFSFilChangedReloadingStrategy</code>.
           In the example below both test.properties and settings.xml would be checked for changes
           once per minute.
         </p>
@@ -117,12 +113,12 @@
   </header>
   <override>
     <properties fileName="test.properties" throwExceptionOnMissing="true">
-      <reloadingStrategy delay="60000"
-        config-class="org.apache.commons.configuration.reloading.VFSFileMonitorReloadingStrategy"/>
+      <reloadingStrategy refreshDelay="60000"
+        config-class="org.apache.commons.configuration.reloading.VFSFileChangedReloadingStrategy"/>
     </properties>
     <xml fileName="settings.xml" config-name="xml">
-      <reloadingStrategy
-         config-class="org.apache.commons.configuration.reloading.VFSFileMonitorReloadingStrategy"/>
+      <reloadingStrategy refreshDelay="60000"
+         config-class="org.apache.commons.configuration.reloading.VFSFileChangedReloadingStrategy"/>
     </xml>
   </override>
 </configuration>

Modified: commons/proper/configuration/branches/CONFIGURATION_390/xdocs/userguide/howto_multitenant.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_390/xdocs/userguide/howto_multitenant.xml?rev=819418&r1=819417&r2=819418&view=diff
==============================================================================
--- commons/proper/configuration/branches/CONFIGURATION_390/xdocs/userguide/howto_multitenant.xml (original)
+++ commons/proper/configuration/branches/CONFIGURATION_390/xdocs/userguide/howto_multitenant.xml Sun Sep 27 22:28:16 2009
@@ -54,6 +54,14 @@
           ReloadingStrategy and listeners will be propogated to each of the
           created configurations.
         </p>
+        <p>
+          When used in a combined configuration it is often acceptable for a file
+          matching a particular pattern to be missing so, by default, most exceptions
+          encountered when loading files are ignored. To change this behavior
+          call setIgnoreException(false) or configure the attribute to false in
+          DefaultConfigurationBuilder's configuration file. If schema validation
+          is enabled validation exceptions will always cause a failure.
+        </p>
       </subsection>
       <subsection name="DynamicCombinedConfiguration">
         <p>