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.File;
21 import java.io.FileOutputStream;
22 import java.io.FileWriter;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.io.PrintWriter;
27 import java.io.Reader;
28 import java.io.StringReader;
29 import java.io.StringWriter;
30 import java.net.HttpURLConnection;
31 import java.net.URL;
32 import java.net.URLConnection;
33 import java.net.URLStreamHandler;
34 import java.util.ArrayList;
35 import java.util.Iterator;
36 import java.util.List;
37
38 import junit.framework.TestCase;
39
40 import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
41 import org.apache.commons.lang.SystemUtils;
42
43 /***
44 * Test for loading and saving properties files.
45 *
46 * @version $Id: TestPropertiesConfiguration.java 712431 2008-11-08 21:05:23Z oheger $
47 */
48 public class TestPropertiesConfiguration extends TestCase
49 {
50 private PropertiesConfiguration conf;
51
52 /*** The File that we test with */
53 private String testProperties = new File("conf/test.properties").getAbsolutePath();
54
55 private String testBasePath = new File("conf").getAbsolutePath();
56 private String testBasePath2 = new File("conf").getAbsoluteFile().getParentFile().getAbsolutePath();
57 private File testSavePropertiesFile = new File("target/testsave.properties");
58
59 protected void setUp() throws Exception
60 {
61 conf = new PropertiesConfiguration(testProperties);
62
63
64 if (testSavePropertiesFile.exists())
65 {
66 assertTrue("Test output file could not be deleted",
67 testSavePropertiesFile.delete());
68 }
69 }
70
71 public void testLoad() throws Exception
72 {
73 String loaded = conf.getString("configuration.loaded");
74 assertEquals("true", loaded);
75 }
76
77 /***
78 * Tests if properties can be appended by simply calling load() another
79 * time.
80 */
81 public void testAppend() throws Exception
82 {
83 File file2 = new File("conf/threesome.properties");
84 conf.load(file2);
85 assertEquals("aaa", conf.getString("test.threesome.one"));
86 assertEquals("true", conf.getString("configuration.loaded"));
87 }
88
89 /***
90 * Tests that empty properties are treated as the empty string
91 * (rather than as null).
92 */
93 public void testEmpty() throws Exception
94 {
95 String empty = conf.getString("test.empty");
96 assertNotNull(empty);
97 assertEquals("", empty);
98 }
99
100 /***
101 * Tests that references to other properties work
102 */
103 public void testReference() throws Exception
104 {
105 assertEquals("baseextra", conf.getString("base.reference"));
106 }
107
108 /***
109 * test if includes properties get loaded too
110 */
111 public void testLoadInclude() throws Exception
112 {
113 String loaded = conf.getString("include.loaded");
114 assertEquals("true", loaded);
115 }
116
117 /***
118 * test if includes properties from interpolated file
119 * name get loaded
120 */
121 public void testLoadIncludeInterpol() throws Exception
122 {
123 String loaded = conf.getString("include.interpol.loaded");
124 assertEquals("true", loaded);
125 }
126
127 public void testSetInclude() throws Exception
128 {
129
130 PropertiesConfiguration.setInclude("import");
131
132
133 PropertiesConfiguration conf = new PropertiesConfiguration();
134 conf.load("conf/test.properties");
135
136
137 PropertiesConfiguration.setInclude("include");
138
139 assertNull(conf.getString("include.loaded"));
140 }
141
142 /***
143 * Tests <code>List</code> parsing.
144 */
145 public void testList() throws Exception
146 {
147 List packages = conf.getList("packages");
148
149 assertEquals(3, packages.size());
150 }
151
152 public void testSave() throws Exception
153 {
154
155 conf.addProperty("string", "value1");
156 List list = new ArrayList();
157 for (int i = 1; i < 5; i++)
158 {
159 list.add("value" + i);
160 }
161 conf.addProperty("array", list);
162
163
164 String filename = testSavePropertiesFile.getAbsolutePath();
165 conf.save(filename);
166
167 assertTrue("The saved file doesn't exist", testSavePropertiesFile.exists());
168
169
170 PropertiesConfiguration checkConfig = new PropertiesConfiguration(filename);
171 ConfigurationAssert.assertEquals(conf, checkConfig);
172
173
174 checkConfig.save();
175 }
176
177 public void testSaveToCustomURL() throws Exception
178 {
179
180 URL url = new URL("foo", "", 0, "./target/testsave-custom-url.properties", new FileURLStreamHandler());
181 conf.save(url);
182
183
184 Configuration config2 = new PropertiesConfiguration(url);
185 assertEquals("true", config2.getString("configuration.loaded"));
186 }
187
188 public void testInMemoryCreatedSave() throws Exception
189 {
190 PropertiesConfiguration pc = new PropertiesConfiguration();
191
192 pc.addProperty("string", "value1");
193 List list = new ArrayList();
194 for (int i = 1; i < 5; i++)
195 {
196 list.add("value" + i);
197 }
198 pc.addProperty("array", list);
199
200
201 String filename = testSavePropertiesFile.getAbsolutePath();
202 pc.save(filename);
203
204 assertTrue("The saved file doesn't exist", testSavePropertiesFile.exists());
205
206
207 PropertiesConfiguration checkConfig = new PropertiesConfiguration(filename);
208 ConfigurationAssert.assertEquals(pc, checkConfig);
209
210
211 checkConfig.save();
212 }
213
214 /***
215 * Tests saving a configuration when delimiter parsing is disabled.
216 */
217 public void testSaveWithDelimiterParsingDisabled() throws ConfigurationException
218 {
219 conf.clear();
220 conf.setDelimiterParsingDisabled(true);
221 conf.addProperty("test.list", "a,b,c");
222 conf.addProperty("test.dirs", "C://Temp//,D://Data//");
223 conf.save(testSavePropertiesFile);
224
225 PropertiesConfiguration checkConfig = new PropertiesConfiguration();
226 checkConfig.setDelimiterParsingDisabled(true);
227 checkConfig.setFile(testSavePropertiesFile);
228 checkConfig.load();
229 ConfigurationAssert.assertEquals(conf, checkConfig);
230 }
231
232 public void testSaveMissingFilename()
233 {
234 PropertiesConfiguration pc = new PropertiesConfiguration();
235 try
236 {
237 pc.save();
238 fail("Should have throw ConfigurationException");
239 }
240 catch (ConfigurationException ce)
241 {
242
243 }
244 }
245
246 /***
247 * Tests if the base path is taken into account by the save() method.
248 * @throws Exception if an error occurs
249 */
250 public void testSaveWithBasePath() throws Exception
251 {
252 conf.setProperty("test", "true");
253 conf.setBasePath(testSavePropertiesFile.getParentFile().toURL().toString());
254 conf.setFileName(testSavePropertiesFile.getName());
255 conf.save();
256 assertTrue(testSavePropertiesFile.exists());
257 }
258
259 /***
260 * Tests whether the escape character for list delimiters can be itself
261 * escaped and survives a save operation.
262 */
263 public void testSaveEscapedEscapingCharacter()
264 throws ConfigurationException
265 {
266 conf.addProperty("test.dirs", "C://Temp////,D://Data////,E://Test//");
267 List dirs = conf.getList("test.dirs");
268 assertEquals("Wrong number of list elements", 3, dirs.size());
269 conf.save(testSavePropertiesFile);
270
271 PropertiesConfiguration checkConfig = new PropertiesConfiguration(
272 testSavePropertiesFile);
273 ConfigurationAssert.assertEquals(conf, checkConfig);
274 }
275
276 public void testLoadViaProperty() throws Exception
277 {
278 PropertiesConfiguration pc = new PropertiesConfiguration();
279 pc.setFileName(testProperties);
280 pc.load();
281
282 assertTrue("Make sure we have multiple keys", pc.getBoolean("test.boolean"));
283 }
284
285 public void testLoadViaPropertyWithBasePath() throws Exception
286 {
287 PropertiesConfiguration pc = new PropertiesConfiguration();
288 pc.setBasePath(testBasePath);
289 pc.setFileName("test.properties");
290 pc.load();
291
292 assertTrue("Make sure we have multiple keys", pc.getBoolean("test.boolean"));
293 }
294
295 public void testLoadViaPropertyWithBasePath2() throws Exception
296 {
297 PropertiesConfiguration pc = new PropertiesConfiguration();
298 pc.setBasePath(testBasePath2);
299 pc.setFileName("conf/test.properties");
300 pc.load();
301
302 assertTrue("Make sure we have multiple keys", pc.getBoolean("test.boolean"));
303
304 pc = new PropertiesConfiguration();
305 pc.setBasePath(testBasePath2);
306 pc.setFileName("conf/test.properties");
307 pc.load();
308
309 assertTrue("Make sure we have multiple keys", pc.getBoolean("test.boolean"));
310 }
311
312 public void testLoadFromFile() throws Exception
313 {
314 File file = new File("conf/test.properties");
315 conf = new PropertiesConfiguration(file);
316
317 assertEquals("true", conf.getString("configuration.loaded"));
318 }
319
320 public void testLoadUnexistingFile()
321 {
322 try
323 {
324 conf = new PropertiesConfiguration("Unexisting file");
325 fail("Unexisting file was loaded.");
326 }
327 catch(ConfigurationException cex)
328 {
329
330 }
331 }
332
333 /***
334 * Tests to load a file with enabled auto save mode.
335 */
336 public void testLoadWithAutoSave() throws Exception
337 {
338 setUpSavedProperties();
339 }
340
341 /***
342 * Tests the auto save functionality when an existing property is modified.
343 */
344 public void testLoadWithAutoSaveAndSetExisting() throws Exception
345 {
346 setUpSavedProperties();
347 conf.setProperty("a", "moreThanOne");
348 checkSavedConfig();
349 }
350
351 /***
352 * Tests the auto save functionality when a new property is added using the
353 * setProperty() method.
354 */
355 public void testLoadWithAutoSaveAndSetNew() throws Exception
356 {
357 setUpSavedProperties();
358 conf.setProperty("d", "four");
359 checkSavedConfig();
360 }
361
362 /***
363 * Tests the auto save functionality when a new property is added using the
364 * addProperty() method.
365 */
366 public void testLoadWithAutoSaveAndAdd() throws Exception
367 {
368 setUpSavedProperties();
369 conf.addProperty("d", "four");
370 checkSavedConfig();
371 }
372
373 /***
374 * Tests the auto save functionality when a property is removed.
375 */
376 public void testLoadWithAutoSaveAndClear() throws Exception
377 {
378 setUpSavedProperties();
379 conf.clearProperty("c");
380 PropertiesConfiguration checkConfig = checkSavedConfig();
381 assertFalse("The saved configuration contain the key '" + "c" + "'", checkConfig.containsKey("c"));
382 }
383
384 /***
385 * Creates a properties file on disk. Used for testing load and save
386 * operations.
387 *
388 * @throws IOException if an I/O error occurs
389 */
390 private void setUpSavedProperties() throws IOException, ConfigurationException
391 {
392 PrintWriter out = null;
393
394 try
395 {
396 out = new PrintWriter(new FileWriter(testSavePropertiesFile));
397 out.println("a = one");
398 out.println("b = two");
399 out.println("c = three");
400 out.close();
401 out = null;
402
403 conf = new PropertiesConfiguration();
404 conf.setAutoSave(true);
405 conf.setFile(testSavePropertiesFile);
406 conf.load();
407 assertEquals("one", conf.getString("a"));
408 assertEquals("two", conf.getString("b"));
409 assertEquals("three", conf.getString("c"));
410 }
411 finally
412 {
413 if (out != null)
414 {
415 out.close();
416 }
417 }
418 }
419
420 /***
421 * Helper method for testing a saved configuration. Reads in the file using
422 * a new instance and compares this instance with the original one.
423 *
424 * @return the newly created configuration instance
425 * @throws ConfigurationException if an error occurs
426 */
427 private PropertiesConfiguration checkSavedConfig()
428 throws ConfigurationException
429 {
430 PropertiesConfiguration checkConfig = new PropertiesConfiguration(testSavePropertiesFile);
431 for (Iterator i = conf.getKeys(); i.hasNext();)
432 {
433 String key = (String) i.next();
434 assertTrue("The saved configuration doesn't contain the key '" + key + "'", checkConfig.containsKey(key));
435 assertEquals("Value of the '" + key + "' property", conf.getProperty(key), checkConfig.getProperty(key));
436 }
437 return checkConfig;
438 }
439
440 public void testGetStringWithEscapedChars()
441 {
442 String property = conf.getString("test.unescape");
443 assertEquals("String with escaped characters", "This \n string \t contains \" escaped // characters", property);
444 }
445
446 public void testGetStringWithEscapedComma()
447 {
448 String property = conf.getString("test.unescape.list-separator");
449 assertEquals("String with an escaped list separator", "This string contains , an escaped list separator", property);
450 }
451
452 public void testUnescapeJava()
453 {
454 assertEquals("test//,test", PropertiesConfiguration.unescapeJava("test//,test", ','));
455 }
456
457 public void testEscapedKey() throws Exception
458 {
459 PropertiesConfiguration conf = new PropertiesConfiguration();
460 conf.load(new StringReader("//u0066//u006f//u006f=bar"));
461
462 assertEquals("value of the 'foo' property", "bar", conf.getString("foo"));
463 }
464
465 public void testMixedArray()
466 {
467 String[] array = conf.getStringArray("test.mixed.array");
468
469 assertEquals("array length", 4, array.length);
470 assertEquals("1st element", "a", array[0]);
471 assertEquals("2nd element", "b", array[1]);
472 assertEquals("3rd element", "c", array[2]);
473 assertEquals("4th element", "d", array[3]);
474 }
475
476 public void testMultilines()
477 {
478 String property = "This is a value spread out across several adjacent "
479 + "natural lines by escaping the line terminator with "
480 + "a backslash character.";
481
482 assertEquals("'test.multilines' property", property, conf.getString("test.multilines"));
483 }
484
485 public void testChangingDefaultListDelimiter() throws Exception
486 {
487 PropertiesConfiguration pc = new PropertiesConfiguration(testProperties);
488 assertEquals(4, pc.getList("test.mixed.array").size());
489
490 char delimiter = PropertiesConfiguration.getDefaultListDelimiter();
491 PropertiesConfiguration.setDefaultListDelimiter('^');
492 pc = new PropertiesConfiguration(testProperties);
493 assertEquals(2, pc.getList("test.mixed.array").size());
494 PropertiesConfiguration.setDefaultListDelimiter(delimiter);
495 }
496
497 public void testChangingListDelimiter() throws Exception
498 {
499 PropertiesConfiguration pc1 = new PropertiesConfiguration(testProperties);
500 assertEquals(4, pc1.getList("test.mixed.array").size());
501
502 PropertiesConfiguration pc2 = new PropertiesConfiguration();
503 pc2.setListDelimiter('^');
504 pc2.setFileName(testProperties);
505 pc2.load();
506 assertEquals("Should obtain the first value", "a", pc2.getString("test.mixed.array"));
507 assertEquals(2, pc2.getList("test.mixed.array").size());
508 }
509
510 public void testDisableListDelimiter() throws Exception
511 {
512 PropertiesConfiguration pc1 = new PropertiesConfiguration(testProperties);
513 assertEquals(4, pc1.getList("test.mixed.array").size());
514
515 PropertiesConfiguration pc2 = new PropertiesConfiguration();
516 pc2.setDelimiterParsingDisabled(true);
517 pc2.setFileName(testProperties);
518 pc2.load();
519 assertEquals(2, pc2.getList("test.mixed.array").size());
520 }
521
522 /***
523 * Tests escaping of an end of line with a backslash.
524 */
525 public void testNewLineEscaping()
526 {
527 List list = conf.getList("test.path");
528 assertEquals(3, list.size());
529 assertEquals("C://path1//", list.get(0));
530 assertEquals("C://path2//", list.get(1));
531 assertEquals("C://path3//complex//test//", list.get(2));
532 }
533
534 /***
535 * Tests if included files are loaded when the source lies in the class path.
536 */
537 public void testLoadIncludeFromClassPath() throws ConfigurationException
538 {
539 conf = new PropertiesConfiguration("test.properties");
540 assertEquals("true", conf.getString("include.loaded"));
541 }
542
543 /***
544 * Test if the lines starting with # or ! are properly ignored.
545 */
546 public void testComment() {
547 assertFalse("comment line starting with '#' parsed as a property", conf.containsKey("#comment"));
548 assertFalse("comment line starting with '!' parsed as a property", conf.containsKey("!comment"));
549 }
550
551 /***
552 * Check that key/value separators can be part of a key.
553 */
554 public void testEscapedKeyValueSeparator()
555 {
556 assertEquals("Escaped separator '=' not supported in keys", "foo", conf.getProperty("test.separator=in.key"));
557 assertEquals("Escaped separator ':' not supported in keys", "bar", conf.getProperty("test.separator:in.key"));
558 assertEquals("Escaped separator '//t' not supported in keys", "foo", conf.getProperty("test.separator\tin.key"));
559 assertEquals("Escaped separator '//f' not supported in keys", "bar", conf.getProperty("test.separator\fin.key"));
560 assertEquals("Escaped separator ' ' not supported in keys" , "foo", conf.getProperty("test.separator in.key"));
561 }
562
563 /***
564 * Test all acceptable key/value separators ('=', ':' or white spaces).
565 */
566 public void testKeyValueSeparators() {
567 assertEquals("equal separator not properly parsed", "foo", conf.getProperty("test.separator.equal"));
568 assertEquals("colon separator not properly parsed", "foo", conf.getProperty("test.separator.colon"));
569 assertEquals("tab separator not properly parsed", "foo", conf.getProperty("test.separator.tab"));
570 assertEquals("formfeed separator not properly parsed", "foo", conf.getProperty("test.separator.formfeed"));
571 assertEquals("whitespace separator not properly parsed", "foo", conf.getProperty("test.separator.whitespace"));
572 }
573
574 /***
575 * Tests including properties when they are loaded from a nested directory
576 * structure.
577 */
578 public void testIncludeInSubDir() throws ConfigurationException
579 {
580 ConfigurationFactory factory = new ConfigurationFactory("conf/testFactoryPropertiesInclude.xml");
581 Configuration config = factory.getConfiguration();
582 assertEquals(true, config.getBoolean("deeptest"));
583 assertEquals(true, config.getBoolean("deepinclude"));
584 assertFalse(config.containsKey("deeptestinvalid"));
585 }
586
587 /***
588 * Tests whether the correct line separator is used.
589 */
590 public void testLineSeparator() throws ConfigurationException
591 {
592 final String EOL = System.getProperty("line.separator");
593 conf = new PropertiesConfiguration();
594 conf.setHeader("My header");
595 conf.setProperty("prop", "value");
596
597 StringWriter out = new StringWriter();
598 conf.save(out);
599 String content = out.toString();
600 assertTrue("Header could not be found", content.indexOf("# My header"
601 + EOL + EOL) == 0);
602 assertTrue("Property could not be found", content.indexOf("prop = value" + EOL) > 0);
603 }
604
605 /***
606 * Tests what happens if a reloading strategy's <code>reloadingRequired()</code>
607 * implementation accesses methods of the configuration that in turn cause a reload.
608 */
609 public void testReentrantReload()
610 {
611 conf.setProperty("shouldReload", Boolean.FALSE);
612 conf.setReloadingStrategy(new FileChangedReloadingStrategy()
613 {
614 public boolean reloadingRequired()
615 {
616 return configuration.getBoolean("shouldReload");
617 }
618 });
619 assertFalse("Property has wrong value", conf.getBoolean("shouldReload"));
620 }
621
622 /***
623 * Tests accessing the layout object.
624 */
625 public void testGetLayout()
626 {
627 PropertiesConfigurationLayout layout = conf.getLayout();
628 assertNotNull("Layout is null", layout);
629 assertSame("Different object returned", layout, conf.getLayout());
630 conf.setLayout(null);
631 PropertiesConfigurationLayout layout2 = conf.getLayout();
632 assertNotNull("Layout 2 is null", layout2);
633 assertNotSame("Same object returned", layout, layout2);
634 }
635
636 /***
637 * Tests the propertyLoaded() method for a simple property.
638 */
639 public void testPropertyLoaded() throws ConfigurationException
640 {
641 DummyLayout layout = new DummyLayout(conf);
642 conf.setLayout(layout);
643 conf.propertyLoaded("layoutLoadedProperty", "yes");
644 assertEquals("Layout's load() was called", 0, layout.loadCalls);
645 assertEquals("Property not added", "yes", conf.getString("layoutLoadedProperty"));
646 }
647
648 /***
649 * Tests the propertyLoaded() method for an include property.
650 */
651 public void testPropertyLoadedInclude() throws ConfigurationException
652 {
653 DummyLayout layout = new DummyLayout(conf);
654 conf.setLayout(layout);
655 conf.propertyLoaded(PropertiesConfiguration.getInclude(), "testClasspath.properties,testEqual.properties");
656 assertEquals("Layout's load() was not correctly called", 2, layout.loadCalls);
657 assertFalse("Property was added", conf.containsKey(PropertiesConfiguration.getInclude()));
658 }
659
660 /***
661 * Tests propertyLoaded() for an include property, when includes are
662 * disabled.
663 */
664 public void testPropertyLoadedIncludeNotAllowed() throws ConfigurationException
665 {
666 DummyLayout layout = new DummyLayout(conf);
667 conf.setLayout(layout);
668 conf.setIncludesAllowed(false);
669 conf.propertyLoaded(PropertiesConfiguration.getInclude(), "testClassPath.properties,testEqual.properties");
670 assertEquals("Layout's load() was called", 0, layout.loadCalls);
671 assertFalse("Property was added", conf.containsKey(PropertiesConfiguration.getInclude()));
672 }
673
674 /***
675 * Tests whether comment lines are correctly detected.
676 */
677 public void testIsCommentLine()
678 {
679 assertTrue("Comment not detected", PropertiesConfiguration.isCommentLine("# a comment"));
680 assertTrue("Alternative comment not detected", PropertiesConfiguration.isCommentLine("! a comment"));
681 assertTrue("Comment with no space not detected", PropertiesConfiguration.isCommentLine("#a comment"));
682 assertTrue("Comment with leading space not detected", PropertiesConfiguration.isCommentLine(" ! a comment"));
683 assertFalse("Wrong comment", PropertiesConfiguration.isCommentLine(" a#comment"));
684 }
685
686 /***
687 * Tests whether a properties configuration can be successfully cloned. It
688 * is especially checked whether the layout object is taken into account.
689 */
690 public void testClone() throws ConfigurationException
691 {
692 PropertiesConfiguration copy = (PropertiesConfiguration) conf.clone();
693 assertNotSame("Copy has same layout object", conf.getLayout(), copy.getLayout());
694 assertEquals("Wrong number of event listeners for original", 1, conf.getConfigurationListeners().size());
695 assertEquals("Wrong number of event listeners for clone", 1, copy.getConfigurationListeners().size());
696 assertSame("Wrong event listener for original", conf.getLayout(), conf.getConfigurationListeners().iterator().next());
697 assertSame("Wrong event listener for clone", copy.getLayout(), copy.getConfigurationListeners().iterator().next());
698 StringWriter outConf = new StringWriter();
699 conf.save(outConf);
700 StringWriter outCopy = new StringWriter();
701 copy.save(outCopy);
702 assertEquals("Output from copy is different", outConf.toString(), outCopy.toString());
703 }
704
705 /***
706 * Tests the clone() method when no layout object exists yet.
707 */
708 public void testCloneNullLayout()
709 {
710 conf = new PropertiesConfiguration();
711 PropertiesConfiguration copy = (PropertiesConfiguration) conf.clone();
712 assertNotSame("Layout objects are the same", conf.getLayout(), copy.getLayout());
713 }
714
715 /***
716 * Tests saving a file-based configuration to a HTTP server.
717 */
718 public void testSaveToHTTPServerSuccess() throws Exception
719 {
720 MockHttpURLStreamHandler handler = new MockHttpURLStreamHandler(
721 HttpURLConnection.HTTP_OK, testSavePropertiesFile);
722 URL url = new URL(null, "http://jakarta.apache.org", handler);
723 conf.save(url);
724 MockHttpURLConnection con = handler.getMockConnection();
725 assertTrue("Wrong output flag", con.getDoOutput());
726 assertEquals("Wrong method", "PUT", con.getRequestMethod());
727
728 PropertiesConfiguration checkConfig = new PropertiesConfiguration(
729 testSavePropertiesFile);
730 ConfigurationAssert.assertEquals(conf, checkConfig);
731 }
732
733 /***
734 * Tests saving a file-based configuration to a HTTP server when the server
735 * reports a failure. This should cause an exception.
736 */
737 public void testSaveToHTTPServerFail() throws Exception
738 {
739 MockHttpURLStreamHandler handler = new MockHttpURLStreamHandler(
740 HttpURLConnection.HTTP_BAD_REQUEST, testSavePropertiesFile);
741 URL url = new URL(null, "http://jakarta.apache.org", handler);
742 try
743 {
744 conf.save(url);
745 fail("Response code was not checked!");
746 }
747 catch (ConfigurationException cex)
748 {
749 assertTrue("Wrong root cause: " + cex,
750 cex.getCause() instanceof IOException);
751 }
752 }
753
754 /***
755 * Test the creation of a file containing a '#' in its name. This test is
756 * skipped on Java 1.3 as it always fails.
757 */
758 public void testFileWithSharpSymbol() throws Exception
759 {
760 if (SystemUtils.isJavaVersionAtLeast(1.4f))
761 {
762 File file = new File("target/sharp#1.properties");
763 file.createNewFile();
764
765 PropertiesConfiguration conf = new PropertiesConfiguration(file);
766 conf.save();
767
768 assertTrue("Missing file " + file, file.exists());
769 }
770 }
771
772 /***
773 * Tests initializing a properties configuration from a non existing file.
774 * There was a bug, which caused properties getting lost when later save()
775 * is called.
776 */
777 public void testInitFromNonExistingFile() throws ConfigurationException
778 {
779 final String testProperty = "test.successfull";
780 conf = new PropertiesConfiguration(testSavePropertiesFile);
781 conf.addProperty(testProperty, Boolean.TRUE);
782 conf.save();
783 PropertiesConfiguration checkConfig = new PropertiesConfiguration(
784 testSavePropertiesFile);
785 assertTrue("Test property not found", checkConfig
786 .getBoolean(testProperty));
787 }
788
789 /***
790 * Tests copying another configuration into the test configuration. This
791 * test ensures that the layout object is informed about the newly added
792 * properties.
793 */
794 public void testCopyAndSave() throws ConfigurationException
795 {
796 Configuration copyConf = setUpCopyConfig();
797 conf.copy(copyConf);
798 checkCopiedConfig(copyConf);
799 }
800
801 /***
802 * Tests appending a configuration to the test configuration. Again it has
803 * to be ensured that the layout object is correctly updated.
804 */
805 public void testAppendAndSave() throws ConfigurationException
806 {
807 Configuration copyConf = setUpCopyConfig();
808 conf.append(copyConf);
809 checkCopiedConfig(copyConf);
810 }
811
812 /***
813 * Tests adding properties through a DataConfiguration. This is related to
814 * CONFIGURATION-332.
815 */
816 public void testSaveWithDataConfig() throws ConfigurationException
817 {
818 conf = new PropertiesConfiguration(testSavePropertiesFile);
819 DataConfiguration dataConfig = new DataConfiguration(conf);
820 dataConfig.setProperty("foo", "bar");
821 assertEquals("Property not set", "bar", conf.getString("foo"));
822
823 conf.save();
824 PropertiesConfiguration config2 = new PropertiesConfiguration(
825 testSavePropertiesFile);
826 assertEquals("Property not saved", "bar", config2.getString("foo"));
827 }
828
829 /***
830 * Tests whether the correct default encoding is used when loading a
831 * properties file. This test is related to CONFIGURATION-345.
832 */
833 public void testLoadWithDefaultEncoding() throws ConfigurationException
834 {
835 class PropertiesConfigurationTestImpl extends PropertiesConfiguration
836 {
837 String loadEncoding;
838
839 public PropertiesConfigurationTestImpl(String fileName)
840 throws ConfigurationException
841 {
842 super(fileName);
843 }
844
845 public void load(InputStream in, String encoding)
846 throws ConfigurationException
847 {
848 loadEncoding = encoding;
849 super.load(in, encoding);
850 }
851 }
852
853 PropertiesConfigurationTestImpl testConf = new PropertiesConfigurationTestImpl(
854 testProperties);
855 assertEquals("Default encoding not used", "ISO-8859-1",
856 testConf.loadEncoding);
857 }
858
859 /***
860 * Creates a configuration that can be used for testing copy operations.
861 *
862 * @return the configuration to be copied
863 */
864 private Configuration setUpCopyConfig()
865 {
866 final int count = 25;
867 Configuration result = new BaseConfiguration();
868 for (int i = 1; i <= count; i++)
869 {
870 result.addProperty("copyKey" + i, "copyValue" + i);
871 }
872 return result;
873 }
874
875 /***
876 * Tests whether the data of a configuration that was copied into the test
877 * configuration is correctly saved.
878 *
879 * @param copyConf the copied configuration
880 * @throws ConfigurationException if an error occurs
881 */
882 private void checkCopiedConfig(Configuration copyConf)
883 throws ConfigurationException
884 {
885 conf.save(testSavePropertiesFile);
886 PropertiesConfiguration checkConf = new PropertiesConfiguration(
887 testSavePropertiesFile);
888 for (Iterator it = copyConf.getKeys(); it.hasNext();)
889 {
890 String key = (String) it.next();
891 assertEquals("Wrong value for property " + key, checkConf
892 .getProperty(key), copyConf.getProperty(key));
893 }
894 }
895
896 /***
897 * A dummy layout implementation for checking whether certain methods are
898 * correctly called by the configuration.
899 */
900 static class DummyLayout extends PropertiesConfigurationLayout
901 {
902 /*** Stores the number how often load() was called. */
903 public int loadCalls;
904
905 public DummyLayout(PropertiesConfiguration config)
906 {
907 super(config);
908 }
909
910 public void load(Reader in) throws ConfigurationException
911 {
912 loadCalls++;
913 }
914 }
915
916 /***
917 * A mock implementation of a HttpURLConnection used for testing saving to
918 * a HTTP server.
919 */
920 static class MockHttpURLConnection extends HttpURLConnection
921 {
922 /*** The response code to return.*/
923 private int responseCode;
924
925 /*** The output file. The output stream will point to this file.*/
926 private File outputFile;
927
928 protected MockHttpURLConnection(URL u, int respCode, File outFile)
929 {
930 super(u);
931 responseCode = respCode;
932 outputFile = outFile;
933 }
934
935 public void disconnect()
936 {
937 }
938
939 public boolean usingProxy()
940 {
941 return false;
942 }
943
944 public void connect() throws IOException
945 {
946 }
947
948 public int getResponseCode() throws IOException
949 {
950 return responseCode;
951 }
952
953 public OutputStream getOutputStream() throws IOException
954 {
955 return new FileOutputStream(outputFile);
956 }
957 }
958
959 /***
960 * A mock stream handler for working with the mock HttpURLConnection.
961 */
962 static class MockHttpURLStreamHandler extends URLStreamHandler
963 {
964 /*** Stores the response code.*/
965 private int responseCode;
966
967 /*** Stores the output file.*/
968 private File outputFile;
969
970 /*** Stores the connection.*/
971 private MockHttpURLConnection connection;
972
973 public MockHttpURLStreamHandler(int respCode, File outFile)
974 {
975 responseCode = respCode;
976 outputFile = outFile;
977 }
978
979 public MockHttpURLConnection getMockConnection()
980 {
981 return connection;
982 }
983
984 protected URLConnection openConnection(URL u) throws IOException
985 {
986 connection = new MockHttpURLConnection(u, responseCode, outputFile);
987 return connection;
988 }
989 }
990 }