001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.configuration; 019 020 import static org.junit.Assert.assertEquals; 021 import static org.junit.Assert.assertFalse; 022 import static org.junit.Assert.assertNotNull; 023 import static org.junit.Assert.assertNotSame; 024 import static org.junit.Assert.assertNull; 025 import static org.junit.Assert.assertTrue; 026 027 import java.io.File; 028 import java.io.FileInputStream; 029 import java.io.FileOutputStream; 030 import java.io.FileWriter; 031 import java.io.IOException; 032 import java.io.PrintWriter; 033 import java.net.URL; 034 import java.util.Iterator; 035 import java.util.Properties; 036 037 import org.apache.commons.configuration.reloading.FileAlwaysReloadingStrategy; 038 import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy; 039 import org.junit.Before; 040 import org.junit.Rule; 041 import org.junit.Test; 042 import org.junit.rules.TemporaryFolder; 043 044 /** 045 * @author Emmanuel Bourg 046 * @version $Id: TestFileConfiguration.java 1231721 2012-01-15 18:32:07Z oheger $ 047 */ 048 public class TestFileConfiguration 049 { 050 /** Constant for the name of a test file.*/ 051 private static final String TEST_FILENAME = "test.properties"; 052 053 /** Constant for a test file.*/ 054 private static final File TEST_FILE = ConfigurationAssert.getTestFile(TEST_FILENAME); 055 056 /** Constant for a test output file. */ 057 private static final File OUT_FILE = new File( 058 "target/test-resources/foo/bar/test.properties"); 059 060 /** Constant for the name of a resource to be resolved.*/ 061 private static final String RESOURCE_NAME = "config/deep/deeptest.properties"; 062 063 /** Helper object for managing temporary files. */ 064 @Rule 065 public TemporaryFolder folder = new TemporaryFolder(); 066 067 /** 068 * Initializes the test environment. This implementation ensures that the 069 * test output file does not exist. 070 */ 071 @Before 072 public void setUp() throws Exception 073 { 074 removeOutFile(); 075 } 076 077 /** 078 * Performs cleanup after a test case. This implementation removes temporary 079 * files that have been created. 080 */ 081 protected void tearDown() throws Exception 082 { 083 removeOutFile(); 084 } 085 086 /** 087 * Removes a file if it exists. 088 * 089 * @param file the file to be removed 090 */ 091 private static void removeFile(File file) 092 { 093 if (file.exists()) 094 { 095 assertTrue("Cannot remove file: " + file, file.delete()); 096 } 097 } 098 099 /** 100 * Removes the test output file if it exists. Its parent directories are 101 * also removed. 102 */ 103 private static void removeOutFile() 104 { 105 removeFile(OUT_FILE); 106 File parent = OUT_FILE.getParentFile(); 107 removeFile(parent); 108 parent = parent.getParentFile(); 109 removeFile(parent); 110 } 111 112 @Test 113 public void testSetURL() throws Exception 114 { 115 // http URL 116 FileConfiguration config = new PropertiesConfiguration(); 117 config.setURL(new URL("http://commons.apache.org/configuration/index.html")); 118 119 assertEquals("base path", "http://commons.apache.org/configuration/", config.getBasePath()); 120 assertEquals("file name", "index.html", config.getFileName()); 121 122 // file URL - This url is invalid, a valid url would be file:///temp/test.properties. 123 config.setURL(new URL("file:/temp/test.properties")); 124 assertEquals("base path", "file:///temp/", config.getBasePath()); 125 assertEquals("file name", "test.properties", config.getFileName()); 126 } 127 128 @Test 129 public void testSetURLWithParams() throws Exception 130 { 131 FileConfiguration config = new PropertiesConfiguration(); 132 URL url = new URL("http://issues.apache.org/bugzilla/show_bug.cgi?id=37886"); 133 config.setURL(url); 134 assertEquals("Base path incorrect", "http://issues.apache.org/bugzilla/", config.getBasePath()); 135 assertEquals("File name incorrect", "show_bug.cgi", config.getFileName()); 136 assertEquals("URL was not correctly stored", url, config.getURL()); 137 } 138 139 @Test 140 public void testLocations() throws Exception 141 { 142 PropertiesConfiguration config = new PropertiesConfiguration(); 143 144 File directory = ConfigurationAssert.TEST_DIR; 145 File file = TEST_FILE; 146 config.setFile(file); 147 assertEquals(directory.getAbsolutePath(), config.getBasePath()); 148 assertEquals(TEST_FILENAME, config.getFileName()); 149 assertEquals(file.getAbsolutePath(), config.getPath()); 150 151 config.setPath(ConfigurationAssert.TEST_DIR_NAME + File.separator + TEST_FILENAME); 152 assertEquals(TEST_FILENAME, config.getFileName()); 153 assertEquals(directory.getAbsolutePath(), config.getBasePath()); 154 assertEquals(file.getAbsolutePath(), config.getPath()); 155 assertEquals(file.toURI().toURL(), config.getURL()); 156 157 config.setBasePath(null); 158 config.setFileName(TEST_FILENAME); 159 assertNull(config.getBasePath()); 160 assertEquals(TEST_FILENAME, config.getFileName()); 161 } 162 163 @Test 164 public void testCreateFile1() throws Exception 165 { 166 assertFalse("The file should not exist", OUT_FILE.exists()); 167 168 FileConfiguration config = new PropertiesConfiguration(OUT_FILE); 169 config.save(); 170 171 assertTrue("The file doesn't exist", OUT_FILE.exists()); 172 } 173 174 @Test 175 public void testCreateFile2() throws Exception 176 { 177 FileConfiguration config = new PropertiesConfiguration(); 178 config.setFile(OUT_FILE); 179 config.save(); 180 181 assertTrue("The file doesn't exist", OUT_FILE.exists()); 182 } 183 184 @Test 185 public void testCreateFile3() throws Exception 186 { 187 FileConfiguration config = new PropertiesConfiguration(); 188 config.save(OUT_FILE); 189 190 assertTrue("The file doesn't exist", OUT_FILE.exists()); 191 } 192 193 /** 194 * Tests collaboration with ConfigurationFactory: Is the base path set on 195 * loading is valid in file based configurations? 196 * 197 * @throws Exception if an error occurs 198 */ 199 @SuppressWarnings("deprecation") 200 @Test 201 public void testWithConfigurationFactory() throws Exception 202 { 203 File file = folder.newFile(); 204 205 ConfigurationFactory factory = new ConfigurationFactory(); 206 factory.setConfigurationURL(ConfigurationAssert.getTestURL( 207 "testDigesterConfiguration2.xml")); 208 CompositeConfiguration cc = 209 (CompositeConfiguration) factory.getConfiguration(); 210 PropertiesConfiguration config = null; 211 for (int i = 0; config == null; i++) 212 { 213 if (cc.getConfiguration(i) instanceof PropertiesConfiguration) 214 { 215 config = (PropertiesConfiguration) cc.getConfiguration(i); 216 } 217 } 218 219 config.setProperty("test", "yes"); 220 config.save(file); 221 assertTrue(file.exists()); 222 config = new PropertiesConfiguration(); 223 config.setFile(file); 224 config.load(); 225 226 assertEquals("yes", config.getProperty("test")); 227 assertEquals("masterOfPost", config.getProperty("mail.account.user")); 228 } 229 230 /** 231 * Tests if invalid URLs cause an exception. 232 */ 233 @Test(expected = ConfigurationException.class) 234 public void testSaveInvalidURL() throws Exception 235 { 236 FileConfiguration config = new PropertiesConfiguration(); 237 config.save(new URL("http://jakarta.apache.org/test.properties")); 238 } 239 240 /** 241 * Tests if an invalid URL string causes an exception. 242 */ 243 @Test(expected = ConfigurationException.class) 244 public void testSaveInvalidURLString() throws ConfigurationException 245 { 246 FileConfiguration config = new PropertiesConfiguration(); 247 config.save("http://www.apache.org/test.properties"); 248 } 249 250 /** 251 * Tests if the URL used by the load() method is also used by save(). 252 */ 253 @Test 254 public void testFileOverwrite() throws Exception 255 { 256 FileOutputStream out = null; 257 FileInputStream in = null; 258 File tempFile = null; 259 try 260 { 261 tempFile = folder.newFile(); 262 Properties props = new Properties(); 263 props.setProperty("1", "one"); 264 out = new FileOutputStream(tempFile); 265 props.store(out, "TestFileOverwrite"); 266 out.close(); 267 out = null; 268 FileConfiguration config = new PropertiesConfiguration(tempFile); 269 config.load(); 270 String value = config.getString("1"); 271 assertTrue("one".equals(value)); 272 config.setProperty("1", "two"); 273 config.save(); 274 props = new Properties(); 275 in = new FileInputStream(tempFile); 276 props.load(in); 277 String value2 = props.getProperty("1"); 278 assertTrue("two".equals(value2)); 279 } 280 finally 281 { 282 if (out != null) 283 { 284 try 285 { 286 out.close(); 287 } 288 catch (IOException ioex) 289 { 290 ioex.printStackTrace(); 291 } 292 } 293 if (in != null) 294 { 295 try 296 { 297 in.close(); 298 } 299 catch (IOException ioex) 300 { 301 ioex.printStackTrace(); 302 } 303 } 304 } 305 } 306 307 /** 308 * Tests setting a file changed reloading strategy together with the auto 309 * save feature. 310 */ 311 @Test 312 public void testReloadingWithAutoSave() throws Exception 313 { 314 File configFile = folder.newFile(); 315 PrintWriter out = null; 316 317 try 318 { 319 out = new PrintWriter(new FileWriter(configFile)); 320 out.println("a = one"); 321 out.close(); 322 out = null; 323 324 PropertiesConfiguration config = new PropertiesConfiguration( 325 configFile); 326 config.setReloadingStrategy(new FileChangedReloadingStrategy()); 327 config.setAutoSave(true); 328 329 assertEquals("one", config.getProperty("a")); 330 config.setProperty("b", "two"); 331 assertEquals("one", config.getProperty("a")); 332 } 333 finally 334 { 335 if (out != null) 336 { 337 out.close(); 338 } 339 } 340 } 341 342 /** 343 * Tests loading and saving a configuration file with a complicated path 344 * name including spaces. (related to issue 35210) 345 */ 346 @Test 347 public void testPathWithSpaces() throws Exception 348 { 349 File path = folder.newFolder("path with spaces"); 350 File confFile = new File(path, "config-test.properties"); 351 PrintWriter out = null; 352 353 try 354 { 355 out = new PrintWriter(new FileWriter(confFile)); 356 out.println("saved = false"); 357 out.close(); 358 out = null; 359 360 URL url = confFile.toURI().toURL(); 361 PropertiesConfiguration config = new PropertiesConfiguration(url); 362 config.load(); 363 assertFalse(config.getBoolean("saved")); 364 365 config.setProperty("saved", Boolean.TRUE); 366 config.save(); 367 config = new PropertiesConfiguration(); 368 config.setFile(confFile); 369 config.load(); 370 assertTrue(config.getBoolean("saved")); 371 } 372 finally 373 { 374 if (out != null) 375 { 376 out.close(); 377 } 378 } 379 } 380 381 /** 382 * Tests whether file names containing a "+" character are handled 383 * correctly. This test is related to CONFIGURATION-415. 384 */ 385 @Test 386 public void testPathWithPlus() throws ConfigurationException, IOException 387 { 388 File saveFile = folder.newFile("test+config.properties"); 389 FileConfiguration config = new PropertiesConfiguration(saveFile); 390 config.addProperty("test", Boolean.TRUE); 391 config.save(); 392 File configFile = config.getFile(); 393 assertEquals("Wrong configuration file", saveFile, configFile); 394 } 395 396 /** 397 * Tests the getFile() method. 398 */ 399 @Test 400 public void testGetFile() throws ConfigurationException 401 { 402 FileConfiguration config = new PropertiesConfiguration(); 403 assertNull(config.getFile()); 404 File file = TEST_FILE.getAbsoluteFile(); 405 config.setFile(file); 406 assertEquals(file, config.getFile()); 407 config.load(); 408 assertEquals(file, config.getFile()); 409 } 410 411 /** 412 * Tests whether getFile() returns a valid file after a configuration has 413 * been loaded. 414 */ 415 @Test 416 public void testGetFileAfterLoad() throws ConfigurationException, 417 IOException 418 { 419 FileConfiguration config = new PropertiesConfiguration(); 420 config.load(TEST_FILE.getAbsolutePath()); 421 assertNotNull("No source URL set", config.getURL()); 422 assertEquals("Wrong source file", TEST_FILE.getCanonicalFile(), config 423 .getFile().getCanonicalFile()); 424 } 425 426 /** 427 * Tests whether calling load() multiple times changes the source. This 428 * should not be the case. 429 */ 430 @Test 431 public void testLoadMultiple() throws ConfigurationException 432 { 433 FileConfiguration config = new PropertiesConfiguration(); 434 config.load(TEST_FILE.getAbsolutePath()); 435 URL srcUrl = config.getURL(); 436 File srcFile = config.getFile(); 437 File file2 = ConfigurationAssert.getTestFile("testEqual.properties"); 438 config.load(file2.getAbsolutePath()); 439 assertEquals("Source URL was changed", srcUrl, config.getURL()); 440 assertEquals("Source file was changed", srcFile, config.getFile()); 441 } 442 443 @Test(expected = ConfigurationException.class) 444 public void testSaveWithoutFileNameFile() throws Exception 445 { 446 FileConfiguration config = new PropertiesConfiguration(); 447 config.load(TEST_FILE); 448 config.save(); 449 } 450 451 @Test(expected = ConfigurationException.class) 452 public void testSaveWithoutFileNameURL() throws Exception 453 { 454 FileConfiguration config = new PropertiesConfiguration(); 455 config.load(TEST_FILE.toURI().toURL()); 456 config.save(); 457 } 458 459 /** 460 * Checks that loading a directory instead of a file throws an exception. 461 */ 462 @Test(expected = ConfigurationException.class) 463 public void testLoadDirectoryString() throws ConfigurationException 464 { 465 PropertiesConfiguration config = new PropertiesConfiguration(); 466 config.load("target"); 467 } 468 469 /** 470 * Tests that it is not possible to load a directory using the load() method 471 * which expects a File. 472 */ 473 @Test(expected = ConfigurationException.class) 474 public void testLoadDirectoryFile() throws ConfigurationException 475 { 476 PropertiesConfiguration config = new PropertiesConfiguration(); 477 config.load(new File("target")); 478 } 479 480 /** 481 * Tests that it is not possible to load a directory using the String constructor. 482 */ 483 @Test(expected = ConfigurationException.class) 484 public void testLoadDirectoryConstrString() throws ConfigurationException 485 { 486 new PropertiesConfiguration("target"); 487 } 488 489 /** 490 * Tests that it is not possible to load a directory using the File constructor. 491 */ 492 @Test(expected = ConfigurationException.class) 493 public void testLoadDirectoryConstrFile() throws ConfigurationException 494 { 495 new PropertiesConfiguration(new File("target")); 496 } 497 498 /** 499 * Tests whether the constructor behaves the same as setFileName() when the 500 * configuration source is in the classpath. 501 */ 502 @Test 503 public void testInitFromClassPath() throws ConfigurationException 504 { 505 PropertiesConfiguration config1 = new PropertiesConfiguration(); 506 config1.setFileName(RESOURCE_NAME); 507 config1.load(); 508 PropertiesConfiguration config2 = new PropertiesConfiguration( 509 RESOURCE_NAME); 510 compare(config1, config2); 511 } 512 513 /** 514 * Tests the loading of configuration file in a Combined configuration 515 * when the configuration source is in the classpath. 516 */ 517 @Test 518 public void testLoadFromClassPath() throws ConfigurationException 519 { 520 DefaultConfigurationBuilder cf = 521 new DefaultConfigurationBuilder("config/deep/testFileFromClasspath.xml"); 522 CombinedConfiguration config = cf.getConfiguration(true); 523 Configuration config1 = config.getConfiguration("propConf"); 524 Configuration config2 = config.getConfiguration("propConfDeep"); 525 compare(config1, config2); 526 } 527 528 /** 529 * Tests cloning a file based configuration. 530 */ 531 @Test 532 public void testClone() throws ConfigurationException 533 { 534 PropertiesConfiguration config = new PropertiesConfiguration( 535 RESOURCE_NAME); 536 PropertiesConfiguration copy = (PropertiesConfiguration) config.clone(); 537 compare(config, copy); 538 assertNull("URL was not reset", copy.getURL()); 539 assertNull("Base path was not reset", copy.getBasePath()); 540 assertNull("File name was not reset", copy.getFileName()); 541 assertNotSame("Reloading strategy was not reset", config 542 .getReloadingStrategy(), copy.getReloadingStrategy()); 543 } 544 545 /** 546 * Tests whether an error log listener was registered at the configuration. 547 */ 548 @Test 549 public void testLogErrorListener() 550 { 551 PropertiesConfiguration config = new PropertiesConfiguration(); 552 assertEquals("No error log listener registered", 1, config 553 .getErrorListeners().size()); 554 } 555 556 /** 557 * Tests handling of errors in the reload() method. 558 */ 559 @Test 560 public void testReloadError() throws ConfigurationException 561 { 562 ConfigurationErrorListenerImpl l = new ConfigurationErrorListenerImpl(); 563 PropertiesConfiguration config = new PropertiesConfiguration( 564 RESOURCE_NAME); 565 config.clearErrorListeners(); 566 config.addErrorListener(l); 567 config.setReloadingStrategy(new FileAlwaysReloadingStrategy()); 568 config.getString("test"); 569 config.setFileName("Not existing file"); 570 config.getString("test"); 571 l.verify(AbstractFileConfiguration.EVENT_RELOAD, null, null); 572 assertNotNull("Exception is not set", l.getLastEvent().getCause()); 573 } 574 575 /** 576 * Tests iterating over the keys of a non hierarchical file-based 577 * configuration while a reload happens. This test is related to 578 * CONFIGURATION-347. 579 */ 580 @Test 581 public void testIterationWithReloadFlat() throws ConfigurationException 582 { 583 PropertiesConfiguration config = new PropertiesConfiguration(TEST_FILE); 584 checkIterationWithReload(config); 585 } 586 587 /** 588 * Tests iterating over the keys of a hierarchical file-based configuration 589 * while a reload happens. This test is related to CONFIGURATION-347. 590 */ 591 @Test 592 public void testIterationWithReloadHierarchical() 593 throws ConfigurationException 594 { 595 XMLConfiguration config = new XMLConfiguration("test.xml"); 596 checkIterationWithReload(config); 597 } 598 599 /** 600 * Tests whether a configuration can be refreshed. 601 */ 602 @Test 603 public void testRefresh() throws ConfigurationException 604 { 605 PropertiesConfiguration config = new PropertiesConfiguration(TEST_FILE); 606 assertEquals("Wrong value", 10, config.getInt("test.integer")); 607 config.setProperty("test.integer", new Integer(42)); 608 assertEquals("Wrong value after update", 42, 609 config.getInt("test.integer")); 610 config.refresh(); 611 assertEquals("Wrong value after refresh", 10, 612 config.getInt("test.integer")); 613 } 614 615 /** 616 * Tests refresh if the configuration is not associated with a file. 617 */ 618 @Test(expected = ConfigurationException.class) 619 public void testRefreshNoFile() throws ConfigurationException 620 { 621 PropertiesConfiguration config = new PropertiesConfiguration(); 622 config.refresh(); 623 } 624 625 /** 626 * Helper method for testing an iteration over the keys of a file-based 627 * configuration while a reload happens. 628 * 629 * @param config the configuration to test 630 */ 631 private void checkIterationWithReload(FileConfiguration config) 632 { 633 config.setReloadingStrategy(new FileAlwaysReloadingStrategy()); 634 for (Iterator<String> it = config.getKeys(); it.hasNext();) 635 { 636 String key = it.next(); 637 assertNotNull("No value for key " + key, config.getProperty(key)); 638 } 639 } 640 641 /** 642 * Helper method for comparing the content of two configuration objects. 643 * 644 * @param config1 the first configuration 645 * @param config2 the second configuration 646 */ 647 private void compare(Configuration config1, Configuration config2) 648 { 649 StrictConfigurationComparator cc = new StrictConfigurationComparator(); 650 assertTrue("Configurations are different", cc.compare(config1, config2)); 651 } 652 }