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