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