1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.configuration;
19
20 import java.io.ByteArrayInputStream;
21 import java.io.File;
22 import java.io.FileOutputStream;
23 import java.io.FileWriter;
24 import java.io.IOException;
25 import java.io.PrintWriter;
26 import java.io.StringReader;
27 import java.io.StringWriter;
28 import java.net.URL;
29 import java.util.Iterator;
30 import java.util.List;
31
32 import javax.xml.parsers.DocumentBuilder;
33 import javax.xml.parsers.DocumentBuilderFactory;
34
35 import org.apache.commons.configuration.reloading.FileAlwaysReloadingStrategy;
36 import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
37 import org.apache.commons.configuration.reloading.InvariantReloadingStrategy;
38 import org.apache.commons.configuration.tree.ConfigurationNode;
39 import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
40 import org.xml.sax.SAXException;
41 import org.xml.sax.SAXParseException;
42 import org.xml.sax.helpers.DefaultHandler;
43
44 import junit.framework.TestCase;
45
46 /***
47 * test for loading and saving xml properties files
48 *
49 * @version $Id: TestXMLConfiguration.java 513498 2007-03-01 21:15:07Z oheger $
50 */
51 public class TestXMLConfiguration extends TestCase
52 {
53 /*** Constant for the used encoding.*/
54 static final String ENCODING = "ISO-8859-1";
55
56 /*** Constant for the test system ID.*/
57 static final String SYSTEM_ID = "properties.dtd";
58
59 /*** Constant for the test public ID.*/
60 static final String PUBLIC_ID = "-//Commons Configuration//DTD Test Configuration 1.3//EN";
61
62 /*** Constant for the DOCTYPE declaration.*/
63 static final String DOCTYPE_DECL = " PUBLIC \"" + PUBLIC_ID + "\" \"" + SYSTEM_ID + "\">";
64
65 /*** Constant for the DOCTYPE prefix.*/
66 static final String DOCTYPE = "<!DOCTYPE ";
67
68 /*** Constant for the transformer factory property.*/
69 static final String PROP_FACTORY = "javax.xml.transform.TransformerFactory";
70
71 /*** The File that we test with */
72 private String testProperties = new File("conf/test.xml").getAbsolutePath();
73 private String testProperties2 = new File("conf/testDigesterConfigurationInclude1.xml").getAbsolutePath();
74 private String testBasePath = new File("conf").getAbsolutePath();
75 private File testSaveConf = new File("target/testsave.xml");
76
77 private XMLConfiguration conf;
78
79 protected void setUp() throws Exception
80 {
81 conf = new XMLConfiguration();
82 conf.setFile(new File(testProperties));
83 conf.load();
84 removeTestFile();
85 }
86
87 public void testGetProperty()
88 {
89 assertEquals("value", conf.getProperty("element"));
90 }
91
92 public void testGetCommentedProperty()
93 {
94 assertEquals("", conf.getProperty("test.comment"));
95 }
96
97 public void testGetPropertyWithXMLEntity()
98 {
99 assertEquals("1<2", conf.getProperty("test.entity"));
100 }
101
102 public void testClearProperty() throws ConfigurationException, IOException
103 {
104
105 String key = "clearly";
106 conf.clearProperty(key);
107 assertNull(key, conf.getProperty(key));
108 assertNull(key, conf.getProperty(key));
109
110
111 conf.load();
112 key = "clear.element";
113 conf.clearProperty(key);
114 assertNull(key, conf.getProperty(key));
115 assertNull(key, conf.getProperty(key));
116
117
118 conf.load();
119 key = "clear.element2";
120 conf.clearProperty(key);
121 assertNull(key, conf.getProperty(key));
122 assertNull(key, conf.getProperty(key));
123 key = "clear.element2[@id]";
124 assertNotNull(key, conf.getProperty(key));
125 assertNotNull(key, conf.getProperty(key));
126
127
128 conf.load();
129 key = "clear.comment";
130 conf.clearProperty(key);
131 assertNull(key, conf.getProperty(key));
132 assertNull(key, conf.getProperty(key));
133
134
135 conf.load();
136 key = "clear.cdata";
137 conf.clearProperty(key);
138 assertNull(key, conf.getProperty(key));
139 assertNull(key, conf.getProperty(key));
140
141
142 conf.load();
143 key = "clear.list.item";
144 conf.clearProperty(key);
145 assertNull(key, conf.getProperty(key));
146 assertNull(key, conf.getProperty(key));
147 key = "clear.list.item[@id]";
148 assertNotNull(key, conf.getProperty(key));
149 assertNotNull(key, conf.getProperty(key));
150
151
152 conf.load();
153 key = "list.item";
154 conf.clearProperty(key);
155 assertNull(key, conf.getProperty(key));
156 assertNull(key, conf.getProperty(key));
157 }
158
159 public void testgetProperty() {
160
161 Object property = conf.getProperty("clear");
162 assertNull(property);
163
164
165 property = conf.getProperty("e");
166 assertNull(property);
167
168
169 property = conf.getProperty("element3[@n]");
170 assertNull(property);
171
172
173 property = conf.getProperty("element");
174 assertNotNull(property);
175 assertTrue(property instanceof String);
176 assertEquals("value", property);
177
178
179 property = conf.getProperty("element3[@name]");
180 assertNotNull(property);
181 assertTrue(property instanceof String);
182 assertEquals("foo", property);
183
184
185 property = conf.getProperty("test.comment");
186 assertEquals("", property);
187
188
189 property = conf.getProperty("test.cdata");
190 assertNotNull(property);
191 assertTrue(property instanceof String);
192 assertEquals("<cdata value>", property);
193
194
195 property = conf.getProperty("list.sublist.item");
196 assertNotNull(property);
197 assertTrue(property instanceof List);
198 List list = (List)property;
199 assertEquals(2, list.size());
200 assertEquals("five", list.get(0));
201 assertEquals("six", list.get(1));
202
203
204 property = conf.getProperty("list.item");
205 assertNotNull(property);
206 assertTrue(property instanceof List);
207 list = (List)property;
208 assertEquals(4, list.size());
209 assertEquals("one", list.get(0));
210 assertEquals("two", list.get(1));
211 assertEquals("three", list.get(2));
212 assertEquals("four", list.get(3));
213
214
215 property = conf.getProperty("list.item[@name]");
216 assertNotNull(property);
217 assertTrue(property instanceof List);
218 list = (List)property;
219 assertEquals(2, list.size());
220 assertEquals("one", list.get(0));
221 assertEquals("three", list.get(1));
222 }
223
224 public void testGetAttribute()
225 {
226 assertEquals("element3[@name]", "foo", conf.getProperty("element3[@name]"));
227 }
228
229 public void testClearAttribute() throws Exception
230 {
231
232 String key = "clear[@id]";
233 conf.clearProperty(key);
234 assertNull(key, conf.getProperty(key));
235 assertNull(key, conf.getProperty(key));
236
237
238 conf.load();
239 key = "clear.element2[@id]";
240 conf.clearProperty(key);
241 assertNull(key, conf.getProperty(key));
242 assertNull(key, conf.getProperty(key));
243 key = "clear.element2";
244 assertNotNull(key, conf.getProperty(key));
245 assertNotNull(key, conf.getProperty(key));
246
247
248 conf.load();
249 key = "clear.list.item[@id]";
250 conf.clearProperty(key);
251 assertNull(key, conf.getProperty(key));
252 assertNull(key, conf.getProperty(key));
253 key = "clear.list.item";
254 assertNotNull(key, conf.getProperty(key));
255 assertNotNull(key, conf.getProperty(key));
256 }
257
258 public void testSetAttribute()
259 {
260
261 conf.setProperty("element3[@name]", "bar");
262 assertEquals("element3[@name]", "bar", conf.getProperty("element3[@name]"));
263
264
265 conf.setProperty("foo[@bar]", "value");
266 assertEquals("foo[@bar]", "value", conf.getProperty("foo[@bar]"));
267
268 conf.setProperty("name1","value1");
269 assertEquals("value1",conf.getProperty("name1"));
270 }
271
272 public void testAddAttribute()
273 {
274 conf.addProperty("element3[@name]", "bar");
275
276 List list = conf.getList("element3[@name]");
277 assertNotNull("null list", list);
278 assertTrue("'foo' element missing", list.contains("foo"));
279 assertTrue("'bar' element missing", list.contains("bar"));
280 assertEquals("list size", 2, list.size());
281 }
282
283 public void testAddObjectAttribute()
284 {
285 conf.addProperty("test.boolean[@value]", Boolean.TRUE);
286 assertTrue("test.boolean[@value]", conf.getBoolean("test.boolean[@value]"));
287 }
288
289 public void testAddList()
290 {
291 conf.addProperty("test.array", "value1");
292 conf.addProperty("test.array", "value2");
293
294 List list = conf.getList("test.array");
295 assertNotNull("null list", list);
296 assertTrue("'value1' element missing", list.contains("value1"));
297 assertTrue("'value2' element missing", list.contains("value2"));
298 assertEquals("list size", 2, list.size());
299 }
300
301 public void testGetComplexProperty()
302 {
303 assertEquals("I'm complex!", conf.getProperty("element2.subelement.subsubelement"));
304 }
305
306 public void testSettingFileNames()
307 {
308 conf = new XMLConfiguration();
309 conf.setFileName(testProperties);
310 assertEquals(testProperties.toString(), conf.getFileName());
311
312 conf.setBasePath(testBasePath);
313 conf.setFileName("hello.xml");
314 assertEquals("hello.xml", conf.getFileName());
315 assertEquals(testBasePath.toString(), conf.getBasePath());
316 assertEquals(new File(testBasePath, "hello.xml"), conf.getFile());
317
318 conf.setBasePath(testBasePath);
319 conf.setFileName("subdir/hello.xml");
320 assertEquals("subdir/hello.xml", conf.getFileName());
321 assertEquals(testBasePath.toString(), conf.getBasePath());
322 assertEquals(new File(testBasePath, "subdir/hello.xml"), conf.getFile());
323 }
324
325 public void testLoad() throws Exception
326 {
327 conf = new XMLConfiguration();
328 conf.setFileName(testProperties);
329 conf.load();
330
331 assertEquals("I'm complex!", conf.getProperty("element2.subelement.subsubelement"));
332 }
333
334 public void testLoadWithBasePath() throws Exception
335 {
336 conf = new XMLConfiguration();
337
338 conf.setFileName("test.xml");
339 conf.setBasePath(testBasePath);
340 conf.load();
341
342 assertEquals("I'm complex!", conf.getProperty("element2.subelement.subsubelement"));
343 }
344
345 /***
346 * Tests constructing an XMLConfiguration from a non existing file and
347 * later saving to this file.
348 */
349 public void testLoadAndSaveFromFile() throws Exception
350 {
351
352 conf = new XMLConfiguration(testSaveConf);
353 assertTrue(conf.isEmpty());
354 conf.addProperty("test", "yes");
355 conf.save();
356
357 conf = new XMLConfiguration(testSaveConf);
358 assertEquals("yes", conf.getString("test"));
359 }
360
361 /***
362 * Tests loading a configuration from a URL.
363 */
364 public void testLoadFromURL() throws Exception
365 {
366 URL url = new File(testProperties).toURL();
367 conf = new XMLConfiguration(url);
368 assertEquals("value", conf.getProperty("element"));
369 assertEquals(url, conf.getURL());
370 }
371
372 /***
373 * Tests loading from a stream.
374 */
375 public void testLoadFromStream() throws Exception
376 {
377 String xml = "<?xml version=\"1.0\"?><config><test>1</test></config>";
378 conf = new XMLConfiguration();
379 conf.load(new ByteArrayInputStream(xml.getBytes()));
380 assertEquals(1, conf.getInt("test"));
381
382 conf = new XMLConfiguration();
383 conf.load(new ByteArrayInputStream(xml.getBytes()), "UTF8");
384 assertEquals(1, conf.getInt("test"));
385 }
386
387 /***
388 * Tests loading a non well formed XML from a string.
389 */
390 public void testLoadInvalidXML() throws Exception
391 {
392 String xml = "<?xml version=\"1.0\"?><config><test>1</rest></config>";
393 conf = new XMLConfiguration();
394 try
395 {
396 conf.load(new StringReader(xml));
397 fail("Could load invalid XML!");
398 }
399 catch(ConfigurationException cex)
400 {
401
402 }
403 }
404
405 public void testSetProperty() throws Exception
406 {
407 conf.setProperty("element.string", "hello");
408
409 assertEquals("'element.string'", "hello", conf.getString("element.string"));
410 assertEquals("XML value of element.string", "hello", conf.getProperty("element.string"));
411 }
412
413 public void testAddProperty()
414 {
415
416 XMLConfiguration config = new XMLConfiguration();
417 config.addProperty("test.string", "hello");
418
419 assertEquals("'test.string'", "hello", config.getString("test.string"));
420 }
421
422 public void testAddObjectProperty()
423 {
424
425 conf.addProperty("test.boolean", Boolean.TRUE);
426 assertTrue("'test.boolean'", conf.getBoolean("test.boolean"));
427 }
428
429 public void testSave() throws Exception
430 {
431
432 conf.addProperty("string", "value1");
433 for (int i = 1; i < 5; i++)
434 {
435 conf.addProperty("test.array", "value" + i);
436 }
437
438
439 for (int i = 1; i < 5; i++)
440 {
441 conf.addProperty("test.attribute[@array]", "value" + i);
442 }
443
444
445 conf.addProperty("split.list5", "a//,b//,c");
446 conf.setProperty("element3", "value//,value1//,value2");
447 conf.setProperty("element3[@name]", "foo//,bar");
448
449
450 conf.save(testSaveConf.getAbsolutePath());
451
452
453 XMLConfiguration checkConfig = new XMLConfiguration();
454 checkConfig.setFileName(testSaveConf.getAbsolutePath());
455 checkSavedConfig(checkConfig);
456 }
457
458 /***
459 * Tests saving to a URL.
460 */
461 public void testSaveToURL() throws Exception
462 {
463 conf.save(testSaveConf.toURL());
464 XMLConfiguration checkConfig = new XMLConfiguration();
465 checkConfig.setFile(testSaveConf);
466 checkSavedConfig(checkConfig);
467 }
468
469 /***
470 * Tests saving to a stream.
471 */
472 public void testSaveToStream() throws Exception
473 {
474 assertNull(conf.getEncoding());
475 conf.setEncoding("UTF8");
476 FileOutputStream out = null;
477 try
478 {
479 out = new FileOutputStream(testSaveConf);
480 conf.save(out);
481 }
482 finally
483 {
484 if(out != null)
485 {
486 out.close();
487 }
488 }
489
490 XMLConfiguration checkConfig = new XMLConfiguration();
491 checkConfig.setFile(testSaveConf);
492 checkSavedConfig(checkConfig);
493
494 try
495 {
496 out = new FileOutputStream(testSaveConf);
497 conf.save(out, "UTF8");
498 }
499 finally
500 {
501 if(out != null)
502 {
503 out.close();
504 }
505 }
506
507 checkConfig.clear();
508 checkSavedConfig(checkConfig);
509 }
510
511 public void testAutoSave() throws Exception
512 {
513 conf.setFile(new File("target/testsave.xml"));
514 assertFalse(conf.isAutoSave());
515 conf.setAutoSave(true);
516 assertTrue(conf.isAutoSave());
517 conf.setProperty("autosave", "ok");
518
519
520 XMLConfiguration conf2 = new XMLConfiguration(conf.getFile());
521 assertEquals("'autosave' property", "ok", conf2.getString("autosave"));
522
523 conf.clearTree("clear");
524 conf2 = new XMLConfiguration(conf.getFile());
525 Configuration sub = conf2.subset("clear");
526 assertTrue(sub.isEmpty());
527 }
528
529 /***
530 * Tests if a second file can be appended to a first.
531 */
532 public void testAppend() throws Exception
533 {
534 conf = new XMLConfiguration();
535 conf.setFileName(testProperties);
536 conf.load();
537 conf.load(testProperties2);
538 assertEquals("value", conf.getString("element"));
539 assertEquals("tasks", conf.getString("table.name"));
540
541 conf.save(testSaveConf);
542 conf = new XMLConfiguration(testSaveConf);
543 assertEquals("value", conf.getString("element"));
544 assertEquals("tasks", conf.getString("table.name"));
545 assertEquals("application", conf.getString("table[@tableType]"));
546 }
547
548 /***
549 * Tests saving attributes (related to issue 34442).
550 */
551 public void testSaveAttributes() throws Exception
552 {
553 conf.clear();
554 conf.load();
555 conf.save(testSaveConf);
556 conf = new XMLConfiguration();
557 conf.load(testSaveConf);
558 assertEquals("foo", conf.getString("element3[@name]"));
559 }
560
561 /***
562 * Tests collaboration between XMLConfiguration and a reloading strategy.
563 */
564 public void testReloading() throws Exception
565 {
566 assertNotNull(conf.getReloadingStrategy());
567 assertTrue(conf.getReloadingStrategy() instanceof InvariantReloadingStrategy);
568 PrintWriter out = null;
569
570 try
571 {
572 out = new PrintWriter(new FileWriter(testSaveConf));
573 out.println("<?xml version=\"1.0\"?><config><test>1</test></config>");
574 out.close();
575 out = null;
576 conf.setFile(testSaveConf);
577 FileAlwaysReloadingStrategy strategy = new FileAlwaysReloadingStrategy();
578 strategy.setRefreshDelay(100);
579 conf.setReloadingStrategy(strategy);
580 assertEquals(strategy, conf.getReloadingStrategy());
581 assertEquals("Wrong file monitored", testSaveConf.getAbsolutePath(),
582 strategy.getMonitoredFile().getAbsolutePath());
583 conf.load();
584 assertEquals(1, conf.getInt("test"));
585
586 out = new PrintWriter(new FileWriter(testSaveConf));
587 out.println("<?xml version=\"1.0\"?><config><test>2</test></config>");
588 out.close();
589 out = null;
590
591 int value = conf.getInt("test");
592 assertEquals("No reloading performed", 2, value);
593 }
594 finally
595 {
596 if (out != null)
597 {
598 out.close();
599 }
600 }
601 }
602
603 /***
604 * Tests access to tag names with delimiter characters.
605 */
606 public void testComplexNames()
607 {
608 assertEquals("Name with dot", conf.getString("complexNames.my..elem"));
609 assertEquals("Another dot", conf.getString("complexNames.my..elem.sub..elem"));
610 }
611
612 /***
613 * Tests setting a custom document builder.
614 */
615 public void testCustomDocBuilder() throws Exception
616 {
617
618
619 conf = new XMLConfiguration();
620 conf.load(new File("conf/testValidateInvalid.xml"));
621 assertEquals("customers", conf.getString("table.name"));
622 assertFalse(conf.containsKey("table.fields.field(1).type"));
623
624
625 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
626 factory.setValidating(true);
627 DocumentBuilder builder = factory.newDocumentBuilder();
628 builder.setErrorHandler(new DefaultHandler() {
629 public void error(SAXParseException ex) throws SAXException
630 {
631 throw ex;
632 }
633 });
634 conf = new XMLConfiguration();
635 conf.setDocumentBuilder(builder);
636 try
637 {
638 conf.load(new File("conf/testValidateInvalid.xml"));
639 fail("Could load invalid file with validating set to true!");
640 }
641 catch(ConfigurationException ex)
642 {
643
644 }
645
646
647 conf = new XMLConfiguration();
648 conf.setDocumentBuilder(builder);
649 conf.load(new File("conf/testValidateValid.xml"));
650 assertTrue(conf.containsKey("table.fields.field(1).type"));
651 }
652
653 /***
654 * Tests the clone() method.
655 */
656 public void testClone()
657 {
658 Configuration c = (Configuration) conf.clone();
659 assertTrue(c instanceof XMLConfiguration);
660 XMLConfiguration copy = (XMLConfiguration) c;
661 assertNotNull(conf.getDocument());
662 assertNull(copy.getDocument());
663 assertNotNull(conf.getFileName());
664 assertNull(copy.getFileName());
665
666 copy.setProperty("element3", "clonedValue");
667 assertEquals("value", conf.getString("element3"));
668 conf.setProperty("element3[@name]", "originalFoo");
669 assertEquals("foo", copy.getString("element3[@name]"));
670 }
671
672 /***
673 * Tests saving a configuration after cloning to ensure that the clone and
674 * the original are completely detachted.
675 */
676 public void testCloneWithSave() throws ConfigurationException
677 {
678 XMLConfiguration c = (XMLConfiguration) conf.clone();
679 c.addProperty("test.newProperty", Boolean.TRUE);
680 conf.addProperty("test.orgProperty", Boolean.TRUE);
681 c.save(testSaveConf);
682 XMLConfiguration c2 = new XMLConfiguration(testSaveConf);
683 assertTrue("New property after clone() was not saved", c2
684 .getBoolean("test.newProperty"));
685 assertFalse("Property of original config was saved", c2
686 .containsKey("test.orgProperty"));
687 }
688
689 /***
690 * Tests the subset() method. There was a bug that calling subset() had
691 * undesired side effects.
692 */
693 public void testSubset() throws ConfigurationException
694 {
695 conf = new XMLConfiguration();
696 conf.load(new File("conf/testHierarchicalXMLConfiguration.xml"));
697 conf.subset("tables.table(0)");
698 conf.save(testSaveConf);
699
700 conf = new XMLConfiguration(testSaveConf);
701 assertEquals("users", conf.getString("tables.table(0).name"));
702 }
703
704 /***
705 * Tests string properties with list delimiters and escaped delimiters.
706 */
707 public void testSplitLists()
708 {
709 assertEquals("a", conf.getString("split.list3[@values]"));
710 assertEquals(2, conf.getMaxIndex("split.list3[@values]"));
711 assertEquals("a,b,c", conf.getString("split.list4[@values]"));
712 assertEquals("a", conf.getString("split.list1"));
713 assertEquals(2, conf.getMaxIndex("split.list1"));
714 assertEquals("a,b,c", conf.getString("split.list2"));
715 }
716
717 /***
718 * Tests string properties with list delimiters when delimiter parsing
719 * is disabled
720 */
721 public void testDelimiterParsingDisabled() throws ConfigurationException {
722 XMLConfiguration conf2 = new XMLConfiguration();
723 conf2.setDelimiterParsingDisabled(true);
724 conf2.setFile(new File(testProperties));
725 conf2.load();
726
727 assertEquals("a,b,c", conf2.getString("split.list3[@values]"));
728 assertEquals(0, conf2.getMaxIndex("split.list3[@values]"));
729 assertEquals("a//,b//,c", conf2.getString("split.list4[@values]"));
730 assertEquals("a,b,c", conf2.getString("split.list1"));
731 assertEquals(0, conf2.getMaxIndex("split.list1"));
732 assertEquals("a//,b//,c", conf2.getString("split.list2"));
733 }
734
735 /***
736 * Tests whether a DTD can be accessed.
737 */
738 public void testDtd() throws ConfigurationException
739 {
740 conf = new XMLConfiguration("testDtd.xml");
741 assertEquals("value1", conf.getString("entry(0)"));
742 assertEquals("test2", conf.getString("entry(1)[@key]"));
743 }
744
745 /***
746 * Tests DTD validation using the setValidating() method.
747 */
748 public void testValidating() throws ConfigurationException
749 {
750 File nonValidFile = new File("conf/testValidateInvalid.xml");
751 conf = new XMLConfiguration();
752 assertFalse(conf.isValidating());
753
754
755 conf.load(nonValidFile);
756 assertEquals("customers", conf.getString("table.name"));
757 assertFalse(conf.containsKey("table.fields.field(1).type"));
758
759
760 conf.setValidating(true);
761 try
762 {
763 conf.load(nonValidFile);
764 fail("Validation was not performed!");
765 }
766 catch(ConfigurationException cex)
767 {
768
769 }
770 }
771
772 /***
773 * Tests handling of empty elements.
774 */
775 public void testEmptyElements() throws ConfigurationException
776 {
777 assertTrue(conf.containsKey("empty"));
778 assertEquals("", conf.getString("empty"));
779 conf.addProperty("empty2", "");
780 conf.setProperty("empty", "no more empty");
781 conf.save(testSaveConf);
782
783 conf = new XMLConfiguration(testSaveConf);
784 assertEquals("no more empty", conf.getString("empty"));
785 assertEquals("", conf.getProperty("empty2"));
786 }
787
788 /***
789 * Tests whether the encoding is correctly detected by the XML parser. This
790 * is done by loading an XML file with the encoding "UTF-16". If this
791 * encoding is not detected correctly, an exception will be thrown that
792 * "Content is not allowed in prolog". This test case is related to issue
793 * 34204.
794 */
795 public void testLoadWithEncoding() throws ConfigurationException
796 {
797 File file = new File("conf/testEncoding.xml");
798 conf = new XMLConfiguration();
799 conf.load(file);
800 assertEquals("test3_yoge", conf.getString("yoge"));
801 }
802
803 /***
804 * Tests whether the encoding is written to the generated XML file.
805 */
806 public void testSaveWithEncoding() throws ConfigurationException
807 {
808 conf = new XMLConfiguration();
809 conf.setProperty("test", "a value");
810 conf.setEncoding(ENCODING);
811
812 StringWriter out = new StringWriter();
813 conf.save(out);
814 assertTrue("Encoding was not written to file", out.toString().indexOf(
815 "encoding=\"" + ENCODING + "\"") >= 0);
816 }
817
818 /***
819 * Tests whether a default encoding is used if no specific encoding is set.
820 * According to the XSLT specification (http://www.w3.org/TR/xslt#output)
821 * this should be either UTF-8 or UTF-16.
822 */
823 public void testSaveWithNullEncoding() throws ConfigurationException
824 {
825 conf = new XMLConfiguration();
826 conf.setProperty("testNoEncoding", "yes");
827 conf.setEncoding(null);
828
829 StringWriter out = new StringWriter();
830 conf.save(out);
831 assertTrue("Encoding was written to file", out.toString().indexOf(
832 "encoding=\"UTF-") >= 0);
833 }
834
835 /***
836 * Tests whether the DOCTYPE survives a save operation.
837 */
838 public void testSaveWithDoctype() throws ConfigurationException
839 {
840 String content = "<?xml version=\"1.0\"?>"
841 + DOCTYPE
842 + "properties"
843 + DOCTYPE_DECL
844 + "<properties version=\"1.0\"><entry key=\"test\">value</entry></properties>";
845 StringReader in = new StringReader(content);
846 conf = new XMLConfiguration();
847 conf.setFileName("conf/testDtd.xml");
848 conf.load();
849 conf.clear();
850 conf.load(in);
851
852 assertEquals("Wrong public ID", PUBLIC_ID, conf.getPublicID());
853 assertEquals("Wrong system ID", SYSTEM_ID, conf.getSystemID());
854 StringWriter out = new StringWriter();
855 conf.save(out);
856 System.out.println(out.toString());
857 assertTrue("Did not find DOCTYPE", out.toString().indexOf(DOCTYPE) >= 0);
858 }
859
860 /***
861 * Tests setting public and system IDs for the D'OCTYPE and then saving the
862 * configuration. This should generate a DOCTYPE declaration.
863 */
864 public void testSaveWithDoctypeIDs() throws ConfigurationException
865 {
866 assertNull("A public ID was found", conf.getPublicID());
867 assertNull("A system ID was found", conf.getSystemID());
868 conf.setPublicID(PUBLIC_ID);
869 conf.setSystemID(SYSTEM_ID);
870 StringWriter out = new StringWriter();
871 conf.save(out);
872 assertTrue("Did not find DOCTYPE", out.toString().indexOf(
873 DOCTYPE + "testconfig" + DOCTYPE_DECL) >= 0);
874 }
875
876 /***
877 * Tests saving a configuration when an invalid transformer factory is
878 * specified. In this case the error thrown by the TransformerFactory class
879 * should be caught and re-thrown as a ConfigurationException.
880 */
881 public void testSaveWithInvalidTransformerFactory()
882 {
883 System.setProperty(PROP_FACTORY, "an.invalid.Class");
884 try
885 {
886 conf.save(testSaveConf);
887 fail("Could save with invalid TransformerFactory!");
888 }
889 catch (ConfigurationException cex)
890 {
891
892 }
893 finally
894 {
895 System.getProperties().remove(PROP_FACTORY);
896 }
897 }
898
899 /***
900 * Tests if reloads are recognized by subset().
901 */
902 public void testSubsetWithReload() throws ConfigurationException
903 {
904 XMLConfiguration c = setUpReloadTest();
905 Configuration sub = c.subset("test");
906 assertEquals("New value not read", "newValue", sub.getString("entity"));
907 }
908
909 /***
910 * Tests if reloads are recognized by configurationAt().
911 */
912 public void testConfigurationAtWithReload() throws ConfigurationException
913 {
914 XMLConfiguration c = setUpReloadTest();
915 HierarchicalConfiguration sub = c.configurationAt("test(0)");
916 assertEquals("New value not read", "newValue", sub.getString("entity"));
917 }
918
919 /***
920 * Tests if reloads are recognized by configurationsAt().
921 */
922 public void testConfigurationsAtWithReload() throws ConfigurationException
923 {
924 XMLConfiguration c = setUpReloadTest();
925 List configs = c.configurationsAt("test");
926 assertEquals("New value not read", "newValue",
927 ((HierarchicalConfiguration) configs.get(0))
928 .getString("entity"));
929 }
930
931 /***
932 * Tests accessing properties when the XPATH expression engine is set.
933 */
934 public void testXPathExpressionEngine()
935 {
936 conf.setExpressionEngine(new XPathExpressionEngine());
937 assertEquals("Wrong attribute value", "foo\"bar", conf
938 .getString("test[1]/entity/@name"));
939 conf.clear();
940 assertNull(conf.getString("test[1]/entity/@name"));
941 }
942
943 /***
944 * Tests the copy constructor.
945 */
946 public void testInitCopy() throws ConfigurationException
947 {
948 XMLConfiguration copy = new XMLConfiguration(conf);
949 assertEquals("value", copy.getProperty("element"));
950 assertNull("Document was copied, too", copy.getDocument());
951 ConfigurationNode root = copy.getRootNode();
952 for(Iterator it = root.getChildren().iterator(); it.hasNext();)
953 {
954 ConfigurationNode node = (ConfigurationNode) it.next();
955 assertNull("Reference was not cleared", node.getReference());
956 }
957
958 removeTestFile();
959 copy.setFile(testSaveConf);
960 copy.save();
961 copy.clear();
962 checkSavedConfig(copy);
963 }
964
965 /***
966 * Prepares a configuration object for testing a reload operation.
967 *
968 * @return the initialized configuration
969 * @throws ConfigurationException if an error occurs
970 */
971 private XMLConfiguration setUpReloadTest() throws ConfigurationException
972 {
973 removeTestFile();
974 conf.save(testSaveConf);
975 XMLConfiguration c = new XMLConfiguration(testSaveConf);
976 c.setReloadingStrategy(new FileChangedReloadingStrategy()
977 {
978
979 protected boolean hasChanged()
980 {
981 return true;
982 }
983 });
984 conf.setProperty("test(0).entity", "newValue");
985 conf.save(testSaveConf);
986 return c;
987 }
988
989 /***
990 * Removes the test output file if it exists.
991 */
992 private void removeTestFile()
993 {
994 if (testSaveConf.exists())
995 {
996 assertTrue(testSaveConf.delete());
997 }
998 }
999
1000 /***
1001 * Helper method for checking if a save operation was successful. Loads a
1002 * saved configuration and then tests against a reference configuration.
1003 * @param checkConfig the configuration to check
1004 * @throws ConfigurationException if an error occurs
1005 */
1006 private void checkSavedConfig(FileConfiguration checkConfig) throws ConfigurationException
1007 {
1008 checkConfig.load();
1009
1010 for (Iterator i = conf.getKeys(); i.hasNext();)
1011 {
1012 String key = (String) i.next();
1013 assertTrue("The saved configuration doesn't contain the key '" + key + "'", checkConfig.containsKey(key));
1014 assertEquals("Value of the '" + key + "' property", conf.getProperty(key), checkConfig.getProperty(key));
1015 }
1016 }
1017 }