You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by oh...@apache.org on 2013/01/27 21:40:34 UTC

svn commit: r1439172 - in /commons/proper/configuration/trunk/src: main/java/org/apache/commons/configuration/builder/combined/ test/java/org/apache/commons/configuration/builder/combined/ test/resources/

Author: oheger
Date: Sun Jan 27 20:40:33 2013
New Revision: 1439172

URL: http://svn.apache.org/viewvc?rev=1439172&view=rev
Log:
Initial integration of MultiFileConfigurationBuilder with CombinedConfigurationBuilder.

Added:
    commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/MultiFileConfigurationBuilderProvider.java   (with props)
    commons/proper/configuration/trunk/src/test/resources/testCCMultiTenent.xml   (with props)
Modified:
    commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedConfigurationBuilder.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/CombinedConfigurationBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedConfigurationBuilder.java?rev=1439172&r1=1439171&r2=1439172&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedConfigurationBuilder.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/CombinedConfigurationBuilder.java Sun Jan 27 20:40:33 2013
@@ -26,7 +26,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.commons.configuration.AbstractConfiguration;
 import org.apache.commons.configuration.CombinedConfiguration;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
@@ -455,16 +454,23 @@ public class CombinedConfigurationBuilde
     private static final BaseConfigurationBuilderProvider COMBINED_PROVIDER =
             new CombinedConfigurationBuilderProvider();
 
+    /** Constant for the provider for multiple XML configurations. */
+    private static final MultiFileConfigurationBuilderProvider MULTI_XML_PROVIDER =
+            new MultiFileConfigurationBuilderProvider(
+                    "org.apache.commons.configuration.XMLConfiguration",
+                    "org.apache.commons.configuration.builder.XMLBuilderParametersImpl");
+
     /** An array with the names of the default tags. */
     private static final String[] DEFAULT_TAGS = {
             "properties", "xml", "hierarchicalXml", "plist",
-            "ini", "system", "env", "jndi", "configuration"
+            "ini", "system", "env", "jndi", "configuration", "multiXml"
     };
 
     /** An array with the providers for the default tags. */
     private static final ConfigurationBuilderProvider[] DEFAULT_PROVIDERS = {
             PROPERTIES_PROVIDER, XML_PROVIDER, XML_PROVIDER, PLIST_PROVIDER, INI_PROVIDER,
-            SYSTEM_PROVIDER, ENV_PROVIDER, JNDI_PROVIDER, COMBINED_PROVIDER
+            SYSTEM_PROVIDER, ENV_PROVIDER, JNDI_PROVIDER, COMBINED_PROVIDER,
+            MULTI_XML_PROVIDER
     };
 
     /** A map with the default configuration builder providers. */
@@ -1496,7 +1502,7 @@ public class CombinedConfigurationBuilde
             try
             {
                 ccResult.addConfiguration(
-                        (AbstractConfiguration) builder.getConfiguration(),
+                        builder.getConfiguration(),
                         decl.getName(), decl.getAt());
             }
             catch (ConfigurationException cex)

Added: 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=1439172&view=auto
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/MultiFileConfigurationBuilderProvider.java (added)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/MultiFileConfigurationBuilderProvider.java Sun Jan 27 20:40:33 2013
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.builder.combined;
+
+import java.util.Arrays;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.ConfigurationUtils;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.apache.commons.configuration.builder.BuilderConfigurationWrapperFactory;
+import org.apache.commons.configuration.builder.BuilderConfigurationWrapperFactory.EventSourceSupport;
+import org.apache.commons.configuration.builder.BuilderListener;
+import org.apache.commons.configuration.builder.ConfigurationBuilder;
+
+/**
+ * <p>
+ * A specialized {@code ConfigurationBuilderProvider} implementation for
+ * integrating {@link MultiFileConfigurationBuilder} with
+ * {@code CombinedConfigurationBuilder}.
+ * </p>
+ * <p>
+ * When using a configuration source managed by
+ * {@code MultiFileConfigurationBuilder} it is not sufficient to store the
+ * configuration once obtained from the builder in the resulting combined
+ * configuration. Rather, it has to be ensured that each access to this
+ * configuration queries the builder anew so that it can evaluate its file
+ * pattern and return a different configuration if necessary. Therefore, this
+ * class returns a specialized wrapper over a
+ * {@code MultiFileConfigurationBuilder} which returns a configuration wrapping
+ * the builder; so accessing the configuration's properties actually calls back
+ * to the builder. This constellation is compatible with the way
+ * {@code DynamicCombinedConfiguration} manages its data.
+ * </p>
+ *
+ * @version $Id$
+ * @since 2.0
+ */
+public class MultiFileConfigurationBuilderProvider extends
+        BaseConfigurationBuilderProvider
+{
+    /** Constant for the name of the builder class. */
+    private static final String BUILDER_CLASS =
+            "org.apache.commons.configuration.builder.combined.MultiFileConfigurationBuilder";
+
+    /** Constant for the name of the reloading builder class. */
+    private static final String RELOADING_BUILDER_CLASS =
+            "org.apache.commons.configuration.builder.combined.ReloadingMultiFileConfigurationBuilder";
+
+    /** Constant for the name of the parameters class. */
+    private static final String PARAM_CLASS =
+            "org.apache.commons.configuration.builder.combined.MultiFileBuilderParametersImpl";
+
+    /**
+     * Creates a new instance of {@code MultiFileConfigurationBuilderProvider}
+     * and sets the name of the configuration class to be returned by
+     * {@code MultiFileConfigurationBuilder}.
+     *
+     * @param configCls the name of the managed configuration class
+     * @param paramCls the name of the class of the parameters object to
+     *        configure the managed configuration
+     */
+    public MultiFileConfigurationBuilderProvider(String configCls,
+            String paramCls)
+    {
+        super(BUILDER_CLASS, RELOADING_BUILDER_CLASS, configCls, Arrays.asList(
+                paramCls, PARAM_CLASS));
+    }
+
+    /**
+     * {@inheritDoc} This implementation lets the super class create a fully
+     * configured builder. Then it returns a special wrapper around it.
+     */
+    @Override
+    public ConfigurationBuilder<? extends Configuration> getConfigurationBuilder(
+            ConfigurationDeclaration decl) throws ConfigurationException
+    {
+        ConfigurationBuilder<? extends Configuration> multiBuilder =
+                super.getConfigurationBuilder(decl);
+        Configuration wrapConfig = createWrapperConfiguration(multiBuilder);
+        return createWrapperBuilder(multiBuilder, wrapConfig);
+    }
+
+    /**
+     * Creates a configuration which wraps the specified builder.
+     *
+     * @param builder the builder
+     * @return the wrapping configuration
+     */
+    // It is safe to disable any type checks because we manually determine
+    // the interface class to be passed to BuilderConfigurationWrapperFactory
+    @SuppressWarnings({
+            "unchecked", "rawtypes"
+    })
+    private Configuration createWrapperConfiguration(
+            ConfigurationBuilder builder)
+    {
+        Class<?> configClass =
+                ConfigurationUtils.loadClassNoEx(getConfigurationClass());
+        Class ifcClass =
+                HierarchicalConfiguration.class.isAssignableFrom(configClass) ? HierarchicalConfiguration.class
+                        : Configuration.class;
+        return BuilderConfigurationWrapperFactory
+                .createBuilderConfigurationWrapper(ifcClass, builder,
+                        EventSourceSupport.BUILDER_OPTIONAL);
+    }
+
+    /**
+     * 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}.
+     *
+     * @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)
+    {
+        return new ConfigurationBuilder<Configuration>()
+        {
+            public Configuration getConfiguration()
+                    throws ConfigurationException
+            {
+                return wrapConfig;
+            }
+
+            public void addBuilderListener(BuilderListener l)
+            {
+                multiBuilder.addBuilderListener(l);
+            }
+
+            public void removeBuilderListener(BuilderListener l)
+            {
+                multiBuilder.removeBuilderListener(l);
+            }
+        };
+    }
+}

Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/MultiFileConfigurationBuilderProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/MultiFileConfigurationBuilderProvider.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/builder/combined/MultiFileConfigurationBuilderProvider.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

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=1439172&r1=1439171&r2=1439172&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 Sun Jan 27 20:40:33 2013
@@ -38,6 +38,7 @@ import org.apache.commons.configuration.
 import org.apache.commons.configuration.ConfigurationAssert;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.DefaultFileSystem;
+import org.apache.commons.configuration.DynamicCombinedConfiguration;
 import org.apache.commons.configuration.FileSystem;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.commons.configuration.PropertiesConfiguration;
@@ -55,7 +56,9 @@ import org.apache.commons.configuration.
 import org.apache.commons.configuration.interpol.ConfigurationInterpolator;
 import org.apache.commons.configuration.interpol.Lookup;
 import org.apache.commons.configuration.resolver.CatalogResolver;
+import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
 import org.easymock.EasyMock;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -76,6 +79,12 @@ public class TestCombinedConfigurationBu
     /** Constant for a named builder. */
     private static final String BUILDER_NAME = "subBuilderName";
 
+    /**
+     * The name of the system property for selecting a file managed by a
+     * MultiFileConfigurationBuilder.
+     */
+    private static final String MULTI_FILE_PROPERTY = "Id";
+
     /** Stores the object to be tested. */
     protected CombinedConfigurationBuilder builder;
 
@@ -89,6 +98,12 @@ public class TestCombinedConfigurationBu
         builder = new CombinedConfigurationBuilder();
     }
 
+    @After
+    public void tearDown() throws Exception
+    {
+        System.getProperties().remove(MULTI_FILE_PROPERTY);
+    }
+
     /**
      * Creates a configuration builder for the definition configuration which
      * always returns the passed in definition configuration.
@@ -988,6 +1003,88 @@ public class TestCombinedConfigurationBu
     }
 
     /**
+     * Loads a test file which includes a MultiFileConfigurationBuilder
+     * declaration and returns the resulting configuration.
+     *
+     * @return the resulting combined configuration
+     * @throws ConfigurationException if an error occurs
+     */
+    private CombinedConfiguration createMultiFileConfig()
+            throws ConfigurationException
+    {
+        File testFile =
+                ConfigurationAssert.getTestFile("testCCMultiTenent.xml");
+        builder.configure(new FileBasedBuilderParametersImpl()
+                .setFile(testFile));
+        CombinedConfiguration config = builder.getConfiguration();
+        assertTrue("Incorrect result configuration",
+                config instanceof DynamicCombinedConfiguration);
+        return config;
+    }
+
+    /**
+     * Tests whether a MultiFileConfigurationBuilder can be integrated into a
+     * combined configuration definition.
+     */
+    @Test
+    public void testMultiTenentConfiguration() throws ConfigurationException
+    {
+        CombinedConfiguration config = createMultiFileConfig();
+        checkMultiFile("1001", config, 15);
+        checkMultiFile("1002", config, 25);
+        checkMultiFile("1003", config, 35);
+        checkMultiFile("1004", config, 50);
+    }
+
+    /**
+     * Tests whether a configuration created by a MultiFileConfigurationBuilder
+     * has been initialized correctly.
+     */
+    @Test
+    public void testMultiTenentConfigurationProperties()
+            throws ConfigurationException
+    {
+        CombinedConfiguration config = createMultiFileConfig();
+        switchToMultiFile("1001");
+        HierarchicalConfiguration multiConf =
+                (HierarchicalConfiguration) config
+                        .getConfiguration("clientConfig");
+        assertTrue(
+                "Expression engine not configured",
+                multiConf.getExpressionEngine() instanceof XPathExpressionEngine);
+        assertEquals("Wrong bg color", "#808080",
+                config.getString("colors.background"));
+        assertEquals("Wrong text color", "#000000",
+                multiConf.getString("colors/text"));
+    }
+
+    /**
+     * Helper method for testing whether properties of a MultiFileConfiguration
+     * can be obtained.
+     *
+     * @param key the key of the file to be accessed
+     * @param config the configuration to check
+     * @param rows the expected value of the test property
+     */
+    private void checkMultiFile(String key, CombinedConfiguration config,
+            int rows)
+    {
+        switchToMultiFile(key);
+        assertEquals("Wrong property value", rows, config.getInt("rowsPerPage"));
+    }
+
+    /**
+     * Sets the system property which selects a specific file managed by a
+     * MultiFileConfigurationBuilder.
+     *
+     * @param key the key to select the desired file
+     */
+    private static void switchToMultiFile(String key)
+    {
+        System.setProperty(MULTI_FILE_PROPERTY, key);
+    }
+
+    /**
      * A test builder provider implementation for testing whether providers can
      * be defined in the definition file.
      */

Added: commons/proper/configuration/trunk/src/test/resources/testCCMultiTenent.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/resources/testCCMultiTenent.xml?rev=1439172&view=auto
==============================================================================
--- commons/proper/configuration/trunk/src/test/resources/testCCMultiTenent.xml (added)
+++ commons/proper/configuration/trunk/src/test/resources/testCCMultiTenent.xml Sun Jan 27 20:40:33 2013
@@ -0,0 +1,43 @@
+<?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. It collaborates with a
+     DynamicCombinedConfiguration.
+     $Id$
+-->
+<configuration>
+  <header>
+    <result loggerName="TestLogger"
+            config-class="org.apache.commons.configuration.DynamicCombinedConfiguration"
+            keyPattern="$${sys:Id}">
+      <nodeCombiner config-class="org.apache.commons.configuration.tree.MergeCombiner"/>
+    </result>
+  </header>
+  <override>
+    <multiXml filePattern="testMultiConfiguration_$${sys:Id}.xml"
+               config-name="clientConfig" schemaValidation="false">
+       <expressionEngine
+          config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/>
+    </multiXml>
+    <xml fileName="testMultiConfiguration_default.xml"
+         config-name="defaultConfig" delimiterParsingDisabled="true">
+      <expressionEngine
+          config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/>
+    </xml>
+  </override>
+</configuration>
\ No newline at end of file

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

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

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