    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  package org.apache.commons.configuration;
    18
    19  import java.io.File;
    20  import java.io.IOException;
    21  import java.util.Collection;
    22  import java.util.Set;
    23
    24  import org.apache.commons.configuration.beanutils.BeanHelper;
    25  import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
    26  import org.apache.commons.configuration.tree.DefaultConfigurationNode;
    27  import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
    28
    29  import junit.framework.TestCase;
    30
    31  /***
    32   * Test class for DefaultConfigurationBuilder.
    33   *
    34   * @author Oliver Heger
    35   * @version $Id: TestDefaultConfigurationBuilder.java 578455 2007-09-22 15:12:16Z oheger $
    36   */
    37  public class TestDefaultConfigurationBuilder extends TestCase
    38  {
    39      /*** Test configuration definition file. */
    40      private static final File TEST_FILE = new File(
    41              "conf/testDigesterConfiguration.xml");
    42
    43      private static final File ADDITIONAL_FILE = new File(
    44              "conf/testDigesterConfiguration2.xml");
    45
    46      private static final File OPTIONAL_FILE = new File(
    47              "conf/testDigesterOptionalConfiguration.xml");
    48
    49      private static final File OPTIONALEX_FILE = new File(
    50              "conf/testDigesterOptionalConfigurationEx.xml");
    51
    52      private static final File MULTI_FILE = new File(
    53              "conf/testDigesterConfiguration3.xml");
    54
    55      private static final File INIT_FILE = new File(
    56              "conf/testComplexInitialization.xml");
    57
    58      /*** Constant for the name of an optional configuration.*/
    59      private static final String OPTIONAL_NAME = "optionalConfig";
    60
    61      /*** Stores the object to be tested. */
    62      DefaultConfigurationBuilder factory;
    63
    64      protected void setUp() throws Exception
    65      {
    66          super.setUp();
    67          System
    68                  .setProperty("java.naming.factory.initial",
    69                          "org.apache.commons.configuration.MockInitialContextFactory");
    70          System.setProperty("test_file_xml", "test.xml");
    71          System.setProperty("test_file_combine", "testcombine1.xml");
    72          factory = new DefaultConfigurationBuilder();
    73          factory.clearErrorListeners();  // avoid exception messages
    74      }
    75
    76      /***
    77       * Tests the isReservedNode() method of ConfigurationDeclaration.
    78       */
    79      public void testConfigurationDeclarationIsReserved()
    80      {
    81          DefaultConfigurationBuilder.ConfigurationDeclaration decl = new DefaultConfigurationBuilder.ConfigurationDeclaration(
    82                  factory, factory);
    83          DefaultConfigurationNode parent = new DefaultConfigurationNode();
    84          DefaultConfigurationNode nd = new DefaultConfigurationNode("at");
    85          parent.addAttribute(nd);
    86          assertTrue("Attribute at not recognized", decl.isReservedNode(nd));
    87          nd = new DefaultConfigurationNode("optional");
    88          parent.addAttribute(nd);
    89          assertTrue("Attribute optional not recognized", decl.isReservedNode(nd));
    90          nd = new DefaultConfigurationNode("config-class");
    91          parent.addAttribute(nd);
    92          assertTrue("Inherited attribute not recognized", decl
    93                  .isReservedNode(nd));
    94          nd = new DefaultConfigurationNode("different");
    95          parent.addAttribute(nd);
    96          assertFalse("Wrong reserved attribute", decl.isReservedNode(nd));
    97          nd = new DefaultConfigurationNode("at");
    98          parent.addChild(nd);
    99          assertFalse("Node type not evaluated", decl.isReservedNode(nd));
    100     }
    101
    102     /***
    103      * Tests if the at attribute is correctly detected as reserved attribute.
    104      */
    105     public void testConfigurationDeclarationIsReservedAt()
    106     {
    107         checkOldReservedAttribute("at");
    108     }
    109
    110     /***
    111      * Tests if the optional attribute is correctly detected as reserved
    112      * attribute.
    113      */
    114     public void testConfigurationDeclarationIsReservedOptional()
    115     {
    116         checkOldReservedAttribute("optional");
    117     }
    118
    119     /***
    120      * Tests if special reserved attributes are recognized by the
    121      * isReservedNode() method. For compatibility reasons the attributes "at"
    122      * and "optional" are also treated as reserved attributes, but only if there
    123      * are no corresponding attributes with the "config-" prefix.
    124      *
    125      * @param name the attribute name
    126      */
    127     private void checkOldReservedAttribute(String name)
    128     {
    129         DefaultConfigurationBuilder.ConfigurationDeclaration decl = new DefaultConfigurationBuilder.ConfigurationDeclaration(
    130                 factory, factory);
    131         DefaultConfigurationNode parent = new DefaultConfigurationNode();
    132         DefaultConfigurationNode nd = new DefaultConfigurationNode("config-"
    133                 + name);
    134         parent.addAttribute(nd);
    135         assertTrue("config-" + name + " attribute not recognized", decl
    136                 .isReservedNode(nd));
    137         DefaultConfigurationNode nd2 = new DefaultConfigurationNode(name);
    138         parent.addAttribute(nd2);
    139         assertFalse(name + " is reserved though config- exists", decl
    140                 .isReservedNode(nd2));
    141         assertTrue("config- attribute not recognized when " + name + " exists",
    142                 decl.isReservedNode(nd));
    143     }
    144
    145     /***
    146      * Tests access to certain reserved attributes of a
    147      * ConfigurationDeclaration.
    148      */
    149     public void testConfigurationDeclarationGetAttributes()
    150     {
    151         factory.addProperty("xml.fileName", "test.xml");
    152         DefaultConfigurationBuilder.ConfigurationDeclaration decl = new DefaultConfigurationBuilder.ConfigurationDeclaration(
    153                 factory, factory.configurationAt("xml"));
    154         assertNull("Found an at attribute", decl.getAt());
    155         assertFalse("Found an optional attribute", decl.isOptional());
    156         factory.addProperty("xml[@config-at]", "test1");
    157         assertEquals("Wrong value of at attribute", "test1", decl.getAt());
    158         factory.addProperty("xml[@at]", "test2");
    159         assertEquals("Wrong value of config-at attribute", "test1", decl.getAt());
    160         factory.clearProperty("xml[@config-at]");
    161         assertEquals("Old at attribute not detected", "test2", decl.getAt());
    162         factory.addProperty("xml[@config-optional]", "true");
    163         assertTrue("Wrong value of optional attribute", decl.isOptional());
    164         factory.addProperty("xml[@optional]", "false");
    165         assertTrue("Wrong value of config-optional attribute", decl.isOptional());
    166         factory.clearProperty("xml[@config-optional]");
    167         factory.setProperty("xml[@optional]", Boolean.TRUE);
    168         assertTrue("Old optional attribute not detected", decl.isOptional());
    169         factory.setProperty("xml[@optional]", "invalid value");
    170         try
    171         {
    172             decl.isOptional();
    173             fail("Invalid optional attribute was not detected!");
    174         }
    175         catch (ConfigurationRuntimeException crex)
    176         {
    177             // ok
    178         }
    179     }
    180
    181     /***
    182      * Tests adding a new configuration provider.
    183      */
    184     public void testAddConfigurationProvider()
    185     {
    186         DefaultConfigurationBuilder.ConfigurationProvider provider = new DefaultConfigurationBuilder.ConfigurationProvider();
    187         assertNull("Provider already registered", factory
    188                 .providerForTag("test"));
    189         factory.addConfigurationProvider("test", provider);
    190         assertSame("Provider not registered", provider, factory
    191                 .providerForTag("test"));
    192     }
    193
    194     /***
    195      * Tries to register a null configuration provider. This should cause an
    196      * exception.
    197      */
    198     public void testAddConfigurationProviderNull()
    199     {
    200         try
    201         {
    202             factory.addConfigurationProvider("test", null);
    203             fail("Could register null provider");
    204         }
    205         catch (IllegalArgumentException iex)
    206         {
    207             // ok
    208         }
    209     }
    210
    211     /***
    212      * Tries to register a configuration provider for a null tag. This should
    213      * cause an exception to be thrown.
    214      */
    215     public void testAddConfigurationProviderNullTag()
    216     {
    217         try
    218         {
    219             factory.addConfigurationProvider(null,
    220                     new DefaultConfigurationBuilder.ConfigurationProvider());
    221             fail("Could register provider for null tag!");
    222         }
    223         catch (IllegalArgumentException iex)
    224         {
    225             // ok
    226         }
    227     }
    228
    229     /***
    230      * Tests removing configuration providers.
    231      */
    232     public void testRemoveConfigurationProvider()
    233     {
    234         assertNull("Removing unknown provider", factory
    235                 .removeConfigurationProvider("test"));
    236         assertNull("Removing provider for null tag", factory
    237                 .removeConfigurationProvider(null));
    238         DefaultConfigurationBuilder.ConfigurationProvider provider = new DefaultConfigurationBuilder.ConfigurationProvider();
    239         factory.addConfigurationProvider("test", provider);
    240         assertSame("Failed to remove provider", provider, factory
    241                 .removeConfigurationProvider("test"));
    242         assertNull("Provider still registered", factory.providerForTag("test"));
    243     }
    244
    245     /***
    246      * Tests creating a configuration object from a configuration declaration.
    247      */
    248     public void testConfigurationBeanFactoryCreateBean()
    249     {
    250         factory.addConfigurationProvider("test",
    251                 new DefaultConfigurationBuilder.ConfigurationProvider(
    252                         PropertiesConfiguration.class));
    253         factory.addProperty("test[@throwExceptionOnMissing]", "true");
    254         DefaultConfigurationBuilder.ConfigurationDeclaration decl = new DefaultConfigurationBuilder.ConfigurationDeclaration(
    255                 factory, factory.configurationAt("test"));
    256         PropertiesConfiguration conf = (PropertiesConfiguration) BeanHelper
    257                 .createBean(decl);
    258         assertTrue("Property was not initialized", conf
    259                 .isThrowExceptionOnMissing());
    260     }
    261
    262     /***
    263      * Tests creating a configuration object from an unknown tag. This should
    264      * cause an exception.
    265      */
    266     public void testConfigurationBeanFactoryCreateUnknownTag()
    267     {
    268         factory.addProperty("test[@throwExceptionOnMissing]", "true");
    269         DefaultConfigurationBuilder.ConfigurationDeclaration decl = new DefaultConfigurationBuilder.ConfigurationDeclaration(
    270                 factory, factory.configurationAt("test"));
    271         try
    272         {
    273             BeanHelper.createBean(decl);
    274             fail("Could create configuration from unknown tag!");
    275         }
    276         catch (ConfigurationRuntimeException crex)
    277         {
    278             // ok
    279         }
    280     }
    281
    282     /***
    283      * Tests loading a simple configuration definition file.
    284      */
    285     public void testLoadConfiguration() throws ConfigurationException
    286     {
    287         factory.setFile(TEST_FILE);
    288         checkConfiguration();
    289     }
    290
    291     /***
    292      * Tests the file constructor.
    293      */
    294     public void testLoadConfigurationFromFile() throws ConfigurationException
    295     {
    296         factory = new DefaultConfigurationBuilder(TEST_FILE);
    297         checkConfiguration();
    298     }
    299
    300     /***
    301      * Tests the file name constructor.
    302      */
    303     public void testLoadConfigurationFromFileName()
    304             throws ConfigurationException
    305     {
    306         factory = new DefaultConfigurationBuilder(TEST_FILE.getAbsolutePath());
    307         checkConfiguration();
    308     }
    309
    310     /***
    311      * Tests the URL constructor.
    312      */
    313     public void testLoadConfigurationFromURL() throws Exception
    314     {
    315         factory = new DefaultConfigurationBuilder(TEST_FILE.toURL());
    316         checkConfiguration();
    317     }
    318
    319     /***
    320      * Tests if the configuration was correctly created by the factory.
    321      */
    322     private void checkConfiguration() throws ConfigurationException
    323     {
    324         CombinedConfiguration compositeConfiguration = (CombinedConfiguration) factory
    325                 .getConfiguration();
    326
    327         assertEquals("Number of configurations", 3, compositeConfiguration
    328                 .getNumberOfConfigurations());
    329         assertEquals(PropertiesConfiguration.class, compositeConfiguration
    330                 .getConfiguration(0).getClass());
    331         assertEquals(XMLPropertiesConfiguration.class, compositeConfiguration
    332                 .getConfiguration(1).getClass());
    333         assertEquals(XMLConfiguration.class, compositeConfiguration
    334                 .getConfiguration(2).getClass());
    335
    336         // check the first configuration
    337         PropertiesConfiguration pc = (PropertiesConfiguration) compositeConfiguration
    338                 .getConfiguration(0);
    339         assertNotNull("Make sure we have a fileName: " + pc.getFileName(), pc
    340                 .getFileName());
    341
    342         // check some properties
    343         checkProperties(compositeConfiguration);
    344     }
    345
    346     /***
    347      * Checks if the passed in configuration contains the expected properties.
    348      *
    349      * @param compositeConfiguration the configuration to check
    350      */
    351     private void checkProperties(Configuration compositeConfiguration)
    352     {
    353         assertTrue("Make sure we have loaded our key", compositeConfiguration
    354                 .getBoolean("test.boolean"));
    355         assertEquals("I'm complex!", compositeConfiguration
    356                 .getProperty("element2.subelement.subsubelement"));
    357         assertEquals("property in the XMLPropertiesConfiguration", "value1",
    358                 compositeConfiguration.getProperty("key1"));
    359     }
    360
    361     /***
    362      * Tests loading a configuration definition file with an additional section.
    363      */
    364     public void testLoadAdditional() throws ConfigurationException
    365     {
    366         factory.setFile(ADDITIONAL_FILE);
    367         CombinedConfiguration compositeConfiguration = (CombinedConfiguration) factory
    368                 .getConfiguration();
    369         assertEquals("Verify how many configs", 2, compositeConfiguration
    370                 .getNumberOfConfigurations());
    371
    372         // Test if union was constructed correctly
    373         Object prop = compositeConfiguration.getProperty("tables.table.name");
    374         assertTrue(prop instanceof Collection);
    375         assertEquals(3, ((Collection) prop).size());
    376         assertEquals("users", compositeConfiguration
    377                 .getProperty("tables.table(0).name"));
    378         assertEquals("documents", compositeConfiguration
    379                 .getProperty("tables.table(1).name"));
    380         assertEquals("tasks", compositeConfiguration
    381                 .getProperty("tables.table(2).name"));
    382
    383         prop = compositeConfiguration
    384                 .getProperty("tables.table.fields.field.name");
    385         assertTrue(prop instanceof Collection);
    386         assertEquals(17, ((Collection) prop).size());
    387
    388         assertEquals("smtp.mydomain.org", compositeConfiguration
    389                 .getString("mail.host.smtp"));
    390         assertEquals("pop3.mydomain.org", compositeConfiguration
    391                 .getString("mail.host.pop"));
    392
    393         // This was overriden
    394         assertEquals("masterOfPost", compositeConfiguration
    395                 .getString("mail.account.user"));
    396         assertEquals("topsecret", compositeConfiguration
    397                 .getString("mail.account.psswd"));
    398
    399         // This was overriden, too, but not in additional section
    400         assertEquals("enhanced factory", compositeConfiguration
    401                 .getString("test.configuration"));
    402     }
    403
    404     /***
    405      * Tests whether a default log error listener is registered at the builder
    406      * instance.
    407      */
    408     public void testLogErrorListener()
    409     {
    410         assertEquals("No default error listener registered", 1,
    411                 new DefaultConfigurationBuilder().getErrorListeners().size());
    412     }
    413
    414     /***
    415      * Tests loading a definition file that contains optional configurations.
    416      */
    417     public void testLoadOptional() throws Exception
    418     {
    419         factory.setURL(OPTIONAL_FILE.toURL());
    420         Configuration config = factory.getConfiguration();
    421         assertTrue(config.getBoolean("test.boolean"));
    422         assertEquals("value", config.getProperty("element"));
    423     }
    424
    425     /***
    426      * Tests whether loading a failing optional configuration causes an error
    427      * event.
    428      */
    429     public void testLoadOptionalErrorEvent() throws Exception
    430     {
    431         factory.clearErrorListeners();
    432         ConfigurationErrorListenerImpl listener = new ConfigurationErrorListenerImpl();
    433         factory.addErrorListener(listener);
    434         prepareOptionalTest("configuration", false);
    435         listener.verify(DefaultConfigurationBuilder.EVENT_ERR_LOAD_OPTIONAL,
    436                 OPTIONAL_NAME, null);
    437     }
    438
    439     /***
    440      * Tests loading a definition file with optional and non optional
    441      * configuration sources. One non optional does not exist, so this should
    442      * cause an exception.
    443      */
    444     public void testLoadOptionalWithException()
    445     {
    446         factory.setFile(OPTIONALEX_FILE);
    447         try
    448         {
    449             factory.getConfiguration();
    450             fail("Non existing source did not cause an exception!");
    451         }
    452         catch (ConfigurationException cex)
    453         {
    454             // ok
    455         }
    456     }
    457
    458     /***
    459      * Tries to load a configuration file with an optional, non file-based
    460      * configuration. The optional attribute should work for other configuration
    461      * classes, too.
    462      */
    463     public void testLoadOptionalNonFileBased() throws ConfigurationException
    464     {
    465         CombinedConfiguration config = prepareOptionalTest("configuration", false);
    466         assertTrue("Configuration not empty", config.isEmpty());
    467         assertEquals("Wrong number of configurations", 0, config
    468                 .getNumberOfConfigurations());
    469     }
    470
    471     /***
    472      * Tests an optional, non existing configuration with the forceCreate
    473      * attribute. This configuration should be added to the resulting
    474      * configuration.
    475      */
    476     public void testLoadOptionalForceCreate() throws ConfigurationException
    477     {
    478         factory.setBasePath(TEST_FILE.getParent());
    479         CombinedConfiguration config = prepareOptionalTest("xml", true);
    480         assertEquals("Wrong number of configurations", 1, config
    481                 .getNumberOfConfigurations());
    482         FileConfiguration fc = (FileConfiguration) config
    483                 .getConfiguration(OPTIONAL_NAME);
    484         assertNotNull("Optional config not found", fc);
    485         assertEquals("File name was not set", "nonExisting.xml", fc
    486                 .getFileName());
    487         assertNotNull("Base path was not set", fc.getBasePath());
    488     }
    489
    490     /***
    491      * Tests loading an embedded optional configuration builder with the force
    492      * create attribute.
    493      */
    494     public void testLoadOptionalBuilderForceCreate()
    495             throws ConfigurationException
    496     {
    497         CombinedConfiguration config = prepareOptionalTest("configuration",
    498                 true);
    499         assertEquals("Wrong number of configurations", 1, config
    500                 .getNumberOfConfigurations());
    501         assertTrue(
    502                 "Wrong optional configuration type",
    503                 config.getConfiguration(OPTIONAL_NAME) instanceof CombinedConfiguration);
    504     }
    505
    506     /***
    507      * Tests loading an optional configuration with the force create attribute
    508      * set. The provider will always throw an exception. In this case the
    509      * configuration will not be added to the resulting combined configuration.
    510      */
    511     public void testLoadOptionalForceCreateWithException()
    512             throws ConfigurationException
    513     {
    514         factory.addConfigurationProvider("test",
    515                 new DefaultConfigurationBuilder.ConfigurationBuilderProvider()
    516                 {
    517                     // Throw an exception here, too
    518                     public AbstractConfiguration getEmptyConfiguration(
    519                             DefaultConfigurationBuilder.ConfigurationDeclaration decl) throws Exception
    520                     {
    521                         throw new Exception("Unable to create configuration!");
    522                     }
    523                 });
    524         CombinedConfiguration config = prepareOptionalTest("test", true);
    525         assertEquals("Optional configuration could be created", 0, config
    526                 .getNumberOfConfigurations());
    527     }
    528
    529     /***
    530      * Prepares a test for loading a configuration definition file with an
    531      * optional configuration declaration.
    532      *
    533      * @param tag the tag name with the optional configuration
    534      * @param force the forceCreate attribute
    535      * @return the combined configuration obtained from the builder
    536      * @throws ConfigurationException if an error occurs
    537      */
    538     private CombinedConfiguration prepareOptionalTest(String tag, boolean force)
    539             throws ConfigurationException
    540     {
    541         String prefix = "override." + tag;
    542         factory.addProperty(prefix + "[@fileName]", "nonExisting.xml");
    543         factory.addProperty(prefix + "[@config-optional]", Boolean.TRUE);
    544         factory.addProperty(prefix + "[@config-name]", OPTIONAL_NAME);
    545         if (force)
    546         {
    547             factory.addProperty(prefix + "[@config-forceCreate]", Boolean.TRUE);
    548         }
    549         return factory.getConfiguration(false);
    550     }
    551
    552     /***
    553      * Tests loading a definition file with multiple different sources.
    554      */
    555     public void testLoadDifferentSources() throws ConfigurationException
    556     {
    557         factory.setFile(MULTI_FILE);
    558         Configuration config = factory.getConfiguration();
    559         assertFalse(config.isEmpty());
    560         assertTrue(config instanceof CombinedConfiguration);
    561         CombinedConfiguration cc = (CombinedConfiguration) config;
    562         assertEquals("Wrong number of configurations", 1, cc
    563                 .getNumberOfConfigurations());
    564
    565         assertNotNull(config
    566                 .getProperty("tables.table(0).fields.field(2).name"));
    567         assertNotNull(config.getProperty("element2.subelement.subsubelement"));
    568         assertEquals("value", config.getProperty("element3"));
    569         assertEquals("foo", config.getProperty("element3[@name]"));
    570         assertNotNull(config.getProperty("mail.account.user"));
    571
    572         // test JNDIConfiguration
    573         assertNotNull(config.getProperty("test.onlyinjndi"));
    574         assertTrue(config.getBoolean("test.onlyinjndi"));
    575
    576         Configuration subset = config.subset("test");
    577         assertNotNull(subset.getProperty("onlyinjndi"));
    578         assertTrue(subset.getBoolean("onlyinjndi"));
    579
    580         // test SystemConfiguration
    581         assertNotNull(config.getProperty("java.version"));
    582         assertEquals(System.getProperty("java.version"), config
    583                 .getString("java.version"));
    584     }
    585
    586     /***
    587      * Tests if the base path is correctly evaluated.
    588      */
    589     public void testSetConfigurationBasePath() throws ConfigurationException
    590     {
    591         factory.addProperty("properties[@fileName]", "test.properties");
    592         File deepDir = new File("conf/config/deep");
    593         factory.setConfigurationBasePath(deepDir.getAbsolutePath());
    594
    595         Configuration config = factory.getConfiguration(false);
    596         assertEquals("Wrong property value", "somevalue", config
    597                 .getString("somekey"));
    598     }
    599
    600     /***
    601      * Tests reading a configuration definition file that contains complex
    602      * initialization of properties of the declared configuration sources.
    603      */
    604     public void testComplexInitialization() throws ConfigurationException
    605     {
    606         factory.setFile(INIT_FILE);
    607         CombinedConfiguration cc = (CombinedConfiguration) factory
    608                 .getConfiguration();
    609
    610         assertEquals("System property not found", "test.xml",
    611                 cc.getString("test_file_xml"));
    612         PropertiesConfiguration c1 = (PropertiesConfiguration) cc
    613                 .getConfiguration(1);
    614         assertTrue(
    615                 "Reloading strategy was not set",
    616                 c1.getReloadingStrategy() instanceof FileChangedReloadingStrategy);
    617         assertEquals("Refresh delay was not set", 10000,
    618                 ((FileChangedReloadingStrategy) c1.getReloadingStrategy())
    619                         .getRefreshDelay());
    620
    621         Configuration xmlConf = cc.getConfiguration("xml");
    622         assertEquals("Property not found", "I'm complex!", xmlConf
    623                 .getString("element2/subelement/subsubelement"));
    624         assertEquals("List index not found", "two", xmlConf
    625                 .getString("list[0]/item[1]"));
    626         assertEquals("Property in combiner file not found", "yellow", cc
    627                 .getString("/gui/selcolor"));
    628
    629         assertTrue("Delimiter flag was not set", cc
    630                 .isDelimiterParsingDisabled());
    631         assertTrue("Expression engine was not set",
    632                 cc.getExpressionEngine() instanceof XPathExpressionEngine);
    633     }
    634
    635     /***
    636      * Tests if the returned combined configuration has the expected structure.
    637      */
    638     public void testCombinedConfiguration() throws ConfigurationException
    639     {
    640         factory.setFile(INIT_FILE);
    641         CombinedConfiguration cc = (CombinedConfiguration) factory
    642                 .getConfiguration();
    643         assertNotNull("Properties configuration not found", cc
    644                 .getConfiguration("properties"));
    645         assertNotNull("XML configuration not found", cc.getConfiguration("xml"));
    646         assertEquals("Wrong number of contained configs", 4, cc
    647                 .getNumberOfConfigurations());
    648
    649         CombinedConfiguration cc2 = (CombinedConfiguration) cc
    650                 .getConfiguration(DefaultConfigurationBuilder.ADDITIONAL_NAME);
    651         assertNotNull("No additional configuration found", cc2);
    652         Set names = cc2.getConfigurationNames();
    653         assertEquals("Wrong number of contained additional configs", 2, names
    654                 .size());
    655         assertTrue("Config 1 not contained", names.contains("combiner1"));
    656         assertTrue("Config 2 not contained", names.contains("combiner2"));
    657     }
    658
    659     /***
    660      * Tests the structure of the returned combined configuration if there is no
    661      * additional section.
    662      */
    663     public void testCombinedConfigurationNoAdditional()
    664             throws ConfigurationException
    665     {
    666         factory.setFile(TEST_FILE);
    667         CombinedConfiguration cc = factory.getConfiguration(true);
    668         assertNull("Additional configuration was found", cc
    669                 .getConfiguration(DefaultConfigurationBuilder.ADDITIONAL_NAME));
    670     }
    671
    672     /***
    673      * Tests whether the list node definition was correctly processed.
    674      */
    675     public void testCombinedConfigurationListNodes()
    676             throws ConfigurationException
    677     {
    678         factory.setFile(INIT_FILE);
    679         CombinedConfiguration cc = factory.getConfiguration(true);
    680         Set listNodes = cc.getNodeCombiner().getListNodes();
    681         assertEquals("Wrong number of list nodes", 2, listNodes.size());
    682         assertTrue("table node not a list node", listNodes.contains("table"));
    683         assertTrue("list node not a list node", listNodes.contains("list"));
    684
    685         CombinedConfiguration cca = (CombinedConfiguration) cc
    686                 .getConfiguration(DefaultConfigurationBuilder.ADDITIONAL_NAME);
    687         listNodes = cca.getNodeCombiner().getListNodes();
    688         assertTrue("Found list nodes for additional combiner", listNodes
    689                 .isEmpty());
    690     }
    691
    692     /***
    693      * Tests whether a configuration builder can itself be declared in a
    694      * configuration definition file.
    695      */
    696     public void testConfigurationBuilderProvider()
    697             throws ConfigurationException
    698     {
    699         factory.addProperty("override.configuration[@fileName]", TEST_FILE
    700                 .getAbsolutePath());
    701         CombinedConfiguration cc = factory.getConfiguration(false);
    702         assertEquals("Wrong number of configurations", 1, cc
    703                 .getNumberOfConfigurations());
    704         checkProperties(cc);
    705     }
    706
    707     /***
    708      * Tests whether XML settings can be inherited.
    709      */
    710     public void testLoadXMLWithSettings() throws ConfigurationException,
    711             IOException
    712     {
    713         File confDir = new File("conf");
    714         File targetDir = new File("target");
    715         File testXMLSource = new File(confDir, "testDtd.xml");
    716         File testXMLValidationSource = new File(confDir,
    717                 "testValidateInvalid.xml");
    718         File testSavedXML = new File(targetDir, "testSave.xml");
    719         File testSavedFactory = new File(targetDir, "testSaveFactory.xml");
    720         File dtdFile = new File(confDir, "properties.dtd");
    721         final String publicId = "http://commons.apache.org/test.dtd";
    722
    723         XMLConfiguration config = new XMLConfiguration(testXMLSource);
    724         config.setPublicID(publicId);
    725         config.save(testSavedXML);
    726         factory.addProperty("xml[@fileName]", testSavedXML.getAbsolutePath());
    727         factory.addProperty("xml(0)[@validating]", "true");
    728         factory.addProperty("xml(-1)[@fileName]", testXMLValidationSource
    729                 .getAbsolutePath());
    730         factory.addProperty("xml(1)[@config-optional]", "true");
    731         factory.addProperty("xml(1)[@validating]", "true");
    732         factory.save(testSavedFactory);
    733
    734         factory = new DefaultConfigurationBuilder();
    735         factory.setFile(testSavedFactory);
    736         factory.registerEntityId(publicId, dtdFile.toURL());
    737         factory.clearErrorListeners();
    738         Configuration c = factory.getConfiguration();
    739         assertEquals("Wrong property value", "value1", c.getString("entry(0)"));
    740         assertFalse("Invalid XML source was loaded", c
    741                 .containsKey("table.name"));
    742
    743         testSavedXML.delete();
    744         testSavedFactory.delete();
    745     }
    746 }