Author: oheger
Date: Mon Jan 28 20:58:46 2013
New Revision: 1439624

URL: http://svn.apache.org/viewvc?rev=1439624&view=rev
Log:
Added reloading support for the integration of MultiFileConfigurationBuilder 
with CombinedConfigurationBuilder.

Added:
    
commons/proper/configuration/trunk/src/test/resources/testCCMultiTenentReloading.xml
   (with props)
Modified:
    
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/MultiFileConfigurationBuilderProvider.java
    
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/combined/TestCombinedConfigurationBuilder.java

Modified: 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/MultiFileConfigurationBuilderProvider.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/MultiFileConfigurationBuilderProvider.java?rev=1439624&r1=1439623&r2=1439624&view=diff
==============================================================================
--- 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/MultiFileConfigurationBuilderProvider.java
 (original)
+++ 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/MultiFileConfigurationBuilderProvider.java
 Mon Jan 28 20:58:46 2013
@@ -26,6 +26,8 @@ import org.apache.commons.configuration.
 import 
org.apache.commons.configuration.builder.BuilderConfigurationWrapperFactory.EventSourceSupport;
 import org.apache.commons.configuration.builder.BuilderListener;
 import org.apache.commons.configuration.builder.ConfigurationBuilder;
+import org.apache.commons.configuration.reloading.ReloadingController;
+import org.apache.commons.configuration.reloading.ReloadingControllerSupport;
 
 /**
  * <p>
@@ -123,33 +125,100 @@ public class MultiFileConfigurationBuild
      * Creates the {@code ConfigurationBuilder} to be returned by this 
provider.
      * This is a very simple implementation which always returns the same
      * wrapper configuration instance. The handling of builder listeners is
-     * delegated to the wrapped {@code MultiFileConfigurationBuilder}.
+     * delegated to the wrapped {@code MultiFileConfigurationBuilder}. If
+     * reloading is support, the builder returned by this method also 
implements
+     * the {@link ReloadingControllerSupport} interface.
      *
      * @param multiBuilder the {@code MultiFileConfigurationBuilder}
      * @param wrapConfig the configuration to be returned
      * @return the wrapper builder
      */
     private static ConfigurationBuilder<? extends Configuration> 
createWrapperBuilder(
-            final ConfigurationBuilder<? extends Configuration> multiBuilder,
-            final Configuration wrapConfig)
+            ConfigurationBuilder<? extends Configuration> multiBuilder,
+            Configuration wrapConfig)
     {
-        return new ConfigurationBuilder<Configuration>()
+        if (multiBuilder instanceof ReloadingControllerSupport)
         {
-            public Configuration getConfiguration()
-                    throws ConfigurationException
-            {
-                return wrapConfig;
-            }
-
-            public void addBuilderListener(BuilderListener l)
-            {
-                multiBuilder.addBuilderListener(l);
-            }
-
-            public void removeBuilderListener(BuilderListener l)
-            {
-                multiBuilder.removeBuilderListener(l);
-            }
-        };
+            return new ReloadableWrapperBuilder(wrapConfig, multiBuilder);
+        }
+        else
+        {
+            return new WrapperBuilder(wrapConfig, multiBuilder);
+        }
+    }
+
+    /**
+     * A simple wrapper implementation of the {@code ConfigurationBuilder}
+     * interface which returns a fix configuration and delegates to another
+     * builder for event listener management.
+     */
+    private static class WrapperBuilder implements
+            ConfigurationBuilder<Configuration>
+    {
+        /** The configuration managed by this builder. */
+        private final Configuration configuration;
+
+        /** The builder to which this instance delegates. */
+        private final ConfigurationBuilder<? extends Configuration> builder;
+
+        /**
+         * Creates a new instance of {@code WrapperBuilder}.
+         *
+         * @param conf the managed configuration
+         * @param bldr the underlying builder
+         */
+        public WrapperBuilder(Configuration conf,
+                ConfigurationBuilder<? extends Configuration> bldr)
+        {
+            configuration = conf;
+            builder = bldr;
+        }
+
+        public Configuration getConfiguration() throws ConfigurationException
+        {
+            return configuration;
+        }
+
+        public void addBuilderListener(BuilderListener l)
+        {
+            builder.addBuilderListener(l);
+        }
+
+        public void removeBuilderListener(BuilderListener l)
+        {
+            builder.removeBuilderListener(l);
+        }
+    }
+
+    /**
+     * A wrapper builder implementation which also provides a
+     * {@code ReloadingController}. This class assumes that the wrapped builder
+     * implements {@code ReloadingControllerSupport}. So the reloading
+     * controller can be obtained from this object.
+     */
+    private static class ReloadableWrapperBuilder extends WrapperBuilder
+            implements ReloadingControllerSupport
+    {
+        /** The object for obtaining the reloading controller. */
+        private final ReloadingControllerSupport ctrlSupport;
+
+        /**
+         * Creates a new instance of {@code ReloadableWrapperBuilder}.
+         *
+         * @param conf the managed configuration
+         * @param bldr the underlying builder (must implement
+         *        {@code ReloadingControllerSupport})
+         */
+        public ReloadableWrapperBuilder(Configuration conf,
+                ConfigurationBuilder<? extends Configuration> bldr)
+        {
+            super(conf, bldr);
+            ctrlSupport = (ReloadingControllerSupport) bldr;
+        }
+
+        public ReloadingController getReloadingController()
+        {
+            return ctrlSupport.getReloadingController();
+        }
     }
 }

Modified: 
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/combined/TestCombinedConfigurationBuilder.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/combined/TestCombinedConfigurationBuilder.java?rev=1439624&r1=1439623&r2=1439624&view=diff
==============================================================================
--- 
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/combined/TestCombinedConfigurationBuilder.java
 (original)
+++ 
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/builder/combined/TestCombinedConfigurationBuilder.java
 Mon Jan 28 20:58:46 2013
@@ -28,6 +28,7 @@ import java.io.File;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -46,6 +47,7 @@ import org.apache.commons.configuration.
 import org.apache.commons.configuration.XMLConfiguration;
 import org.apache.commons.configuration.XMLPropertiesConfiguration;
 import org.apache.commons.configuration.builder.BasicConfigurationBuilder;
+import org.apache.commons.configuration.builder.BuilderListener;
 import org.apache.commons.configuration.builder.ConfigurationBuilder;
 import org.apache.commons.configuration.builder.FileBasedBuilderParametersImpl;
 import org.apache.commons.configuration.builder.FileBasedConfigurationBuilder;
@@ -55,6 +57,8 @@ import org.apache.commons.configuration.
 import org.apache.commons.configuration.event.ConfigurationListener;
 import org.apache.commons.configuration.interpol.ConfigurationInterpolator;
 import org.apache.commons.configuration.interpol.Lookup;
+import org.apache.commons.configuration.reloading.ReloadingController;
+import org.apache.commons.configuration.reloading.ReloadingControllerSupport;
 import org.apache.commons.configuration.resolver.CatalogResolver;
 import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
 import org.easymock.EasyMock;
@@ -1006,14 +1010,14 @@ public class TestCombinedConfigurationBu
      * Loads a test file which includes a MultiFileConfigurationBuilder
      * declaration and returns the resulting configuration.
      *
+     * @param fileName the name of the file to be loaded
      * @return the resulting combined configuration
      * @throws ConfigurationException if an error occurs
      */
-    private CombinedConfiguration createMultiFileConfig()
+    private CombinedConfiguration createMultiFileConfig(String fileName)
             throws ConfigurationException
     {
-        File testFile =
-                ConfigurationAssert.getTestFile("testCCMultiTenent.xml");
+        File testFile = ConfigurationAssert.getTestFile(fileName);
         builder.configure(new FileBasedBuilderParametersImpl()
                 .setFile(testFile));
         CombinedConfiguration config = builder.getConfiguration();
@@ -1029,7 +1033,7 @@ public class TestCombinedConfigurationBu
     @Test
     public void testMultiTenentConfiguration() throws ConfigurationException
     {
-        CombinedConfiguration config = createMultiFileConfig();
+        CombinedConfiguration config = 
createMultiFileConfig("testCCMultiTenent.xml");
         checkMultiFile("1001", config, 15);
         checkMultiFile("1002", config, 25);
         checkMultiFile("1003", config, 35);
@@ -1044,7 +1048,7 @@ public class TestCombinedConfigurationBu
     public void testMultiTenentConfigurationProperties()
             throws ConfigurationException
     {
-        CombinedConfiguration config = createMultiFileConfig();
+        CombinedConfiguration config = 
createMultiFileConfig("testCCMultiTenent.xml");
         switchToMultiFile("1001");
         HierarchicalConfiguration multiConf =
                 (HierarchicalConfiguration) config
@@ -1085,6 +1089,66 @@ public class TestCombinedConfigurationBu
     }
 
     /**
+     * Tests whether reloading support works for MultiFileConfigurationBuilder.
+     */
+    @Test
+    public void testMultiTenentConfigurationReloading()
+            throws ConfigurationException, InterruptedException
+    {
+        CombinedConfiguration config =
+                createMultiFileConfig("testCCMultiTenentReloading.xml");
+        File outFile =
+                ConfigurationAssert.getOutFile("MultiFileReloadingTest.xml");
+        switchToMultiFile(outFile.getAbsolutePath());
+        XMLConfiguration reloadConfig = new XMLConfiguration();
+        final String key = "test.reload";
+        reloadConfig.setProperty(key, "no");
+        reloadConfig.save(outFile);
+        try
+        {
+            assertEquals("Wrong property", "no", config.getString(key));
+            ConfigurationBuilder<? extends Configuration> childBuilder =
+                    builder.getNamedBuilder("clientConfig");
+            assertTrue("Not a reloading builder",
+                    childBuilder instanceof ReloadingControllerSupport);
+            ReloadingController ctrl =
+                    ((ReloadingControllerSupport) childBuilder)
+                            .getReloadingController();
+            ctrl.checkForReloading(null); // initialize reloading
+            BuilderListenerTestImpl l = new BuilderListenerTestImpl();
+            childBuilder.addBuilderListener(l);
+            reloadConfig.setProperty(key, "yes");
+            reloadConfig.save(outFile);
+
+            int attempts = 10;
+            boolean changeDetected;
+            do
+            {
+                changeDetected = ctrl.checkForReloading(null);
+                if (!changeDetected)
+                {
+                    Thread.sleep(1000);
+                }
+            } while (!changeDetected && --attempts > 0);
+            assertTrue("No change detected", changeDetected);
+            assertEquals("Wrong updated property", "yes", builder
+                    .getConfiguration().getString(key));
+            assertEquals("No change event received", 1, 
l.getBuilders().size());
+            BasicConfigurationBuilder<? extends Configuration> multiBuilder =
+                    (BasicConfigurationBuilder<? extends Configuration>) l
+                            .getBuilders().get(0);
+            childBuilder.removeBuilderListener(l);
+            multiBuilder.resetResult();
+            assertEquals("Got another change event received", 1, l
+                    .getBuilders().size());
+        }
+        finally
+        {
+            outFile.delete();
+        }
+    }
+
+    /**
      * A test builder provider implementation for testing whether providers can
      * be defined in the definition file.
      */
@@ -1231,4 +1295,31 @@ public class TestCombinedConfigurationBu
             return map.get(key);
         }
     }
+
+    /**
+     * A test implementation of the BuilderListener interface.
+     */
+    private static class BuilderListenerTestImpl implements BuilderListener
+    {
+        /** A list for the notified builders. */
+        private final List<ConfigurationBuilder<? extends Configuration>> 
builders =
+                new LinkedList<ConfigurationBuilder<? extends 
Configuration>>();
+
+        public void builderReset(
+                ConfigurationBuilder<? extends Configuration> builder)
+        {
+            builders.add(builder);
+        }
+
+        /**
+         * Returns a list with builders for which a reset notification was
+         * received.
+         *
+         * @return the list with builders
+         */
+        public List<ConfigurationBuilder<? extends Configuration>> 
getBuilders()
+        {
+            return builders;
+        }
+    }
 }

Added: 
commons/proper/configuration/trunk/src/test/resources/testCCMultiTenentReloading.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/resources/testCCMultiTenentReloading.xml?rev=1439624&view=auto
==============================================================================
--- 
commons/proper/configuration/trunk/src/test/resources/testCCMultiTenentReloading.xml
 (added)
+++ 
commons/proper/configuration/trunk/src/test/resources/testCCMultiTenentReloading.xml
 Mon Jan 28 20:58:46 2013
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<!-- Test configuration definition file that includes a builder for
+     multiple configuration files that is configured to support reloading.
+     $Id$
+-->
+<configuration>
+  <header>
+    <result keyPattern="$${sys:Id}"
+            
config-class="org.apache.commons.configuration.DynamicCombinedConfiguration">
+    </result>
+  </header>
+  <override>
+    <multiXml filePattern="$${sys:Id}"
+               config-name="clientConfig" config-reload="true"/>
+  </override>
+</configuration>
\ No newline at end of file

Propchange: 
commons/proper/configuration/trunk/src/test/resources/testCCMultiTenentReloading.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
commons/proper/configuration/trunk/src/test/resources/testCCMultiTenentReloading.xml
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: 
commons/proper/configuration/trunk/src/test/resources/testCCMultiTenentReloading.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml


Reply via email to