1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
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
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
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
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
336 PropertiesConfiguration pc = (PropertiesConfiguration) compositeConfiguration
337 .getConfiguration(0);
338 assertNotNull("Make sure we have a fileName: " + pc.getFileName(), pc
339 .getFileName());
340
341
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
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
393 assertEquals("masterOfPost", compositeConfiguration
394 .getString("mail.account.user"));
395 assertEquals("topsecret", compositeConfiguration
396 .getString("mail.account.psswd"));
397
398
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
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
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
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
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 }