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