| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.commons.configuration; |
| |
| import java.io.BufferedReader; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.FileReader; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.io.PrintWriter; |
| import java.io.Reader; |
| import java.io.StringReader; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| import java.net.HttpURLConnection; |
| import java.net.URL; |
| import java.net.URLConnection; |
| import java.net.URLStreamHandler; |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| |
| import junit.framework.TestCase; |
| |
| import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy; |
| import org.apache.commons.lang.SystemUtils; |
| |
| /** |
| * Test for loading and saving properties files. |
| * |
| * @version $Id$ |
| */ |
| public class TestPropertiesConfiguration extends TestCase |
| { |
| /** Constant for a test property name.*/ |
| private static final String PROP_NAME = "testProperty"; |
| |
| /** Constant for a test property value.*/ |
| private static final String PROP_VALUE = "value"; |
| |
| /** The configuration to be tested.*/ |
| private PropertiesConfiguration conf; |
| |
| /** The File that we test with */ |
| private static String testProperties = new File("conf/test.properties").getAbsolutePath(); |
| |
| private static String testBasePath = new File("conf").getAbsolutePath(); |
| private static String testBasePath2 = new File("conf").getAbsoluteFile().getParentFile().getAbsolutePath(); |
| private static File testSavePropertiesFile = new File("target/testsave.properties"); |
| |
| protected void setUp() throws Exception |
| { |
| conf = new PropertiesConfiguration(testProperties); |
| |
| // remove the test save file if it exists |
| if (testSavePropertiesFile.exists()) |
| { |
| assertTrue("Test output file could not be deleted", |
| testSavePropertiesFile.delete()); |
| } |
| } |
| |
| public void testLoad() throws Exception |
| { |
| String loaded = conf.getString("configuration.loaded"); |
| assertEquals("true", loaded); |
| } |
| |
| /** |
| * Tests if properties can be appended by simply calling load() another |
| * time. |
| */ |
| public void testAppend() throws Exception |
| { |
| File file2 = new File("conf/threesome.properties"); |
| conf.load(file2); |
| assertEquals("aaa", conf.getString("test.threesome.one")); |
| assertEquals("true", conf.getString("configuration.loaded")); |
| } |
| |
| /** |
| * Tests that empty properties are treated as the empty string |
| * (rather than as null). |
| */ |
| public void testEmpty() throws Exception |
| { |
| String empty = conf.getString("test.empty"); |
| assertNotNull(empty); |
| assertEquals("", empty); |
| } |
| |
| /** |
| * Tests that references to other properties work |
| */ |
| public void testReference() throws Exception |
| { |
| assertEquals("baseextra", conf.getString("base.reference")); |
| } |
| |
| /** |
| * test if includes properties get loaded too |
| */ |
| public void testLoadInclude() throws Exception |
| { |
| String loaded = conf.getString("include.loaded"); |
| assertEquals("true", loaded); |
| } |
| |
| /** |
| * test if includes properties from interpolated file |
| * name get loaded |
| */ |
| public void testLoadIncludeInterpol() throws Exception |
| { |
| String loaded = conf.getString("include.interpol.loaded"); |
| assertEquals("true", loaded); |
| } |
| |
| public void testSetInclude() throws Exception |
| { |
| // change the include key |
| PropertiesConfiguration.setInclude("import"); |
| |
| // load the configuration |
| PropertiesConfiguration conf = new PropertiesConfiguration(); |
| conf.load("conf/test.properties"); |
| |
| // restore the previous value for the other tests |
| PropertiesConfiguration.setInclude("include"); |
| |
| assertNull(conf.getString("include.loaded")); |
| } |
| |
| /** |
| * Tests <code>List</code> parsing. |
| */ |
| public void testList() throws Exception |
| { |
| List packages = conf.getList("packages"); |
| // we should get 3 packages here |
| assertEquals(3, packages.size()); |
| } |
| |
| public void testSave() throws Exception |
| { |
| // add an array of strings to the configuration |
| conf.addProperty("string", "value1"); |
| List list = new ArrayList(); |
| for (int i = 1; i < 5; i++) |
| { |
| list.add("value" + i); |
| } |
| conf.addProperty("array", list); |
| |
| // save the configuration |
| String filename = testSavePropertiesFile.getAbsolutePath(); |
| conf.save(filename); |
| |
| assertTrue("The saved file doesn't exist", testSavePropertiesFile.exists()); |
| |
| // read the configuration and compare the properties |
| PropertiesConfiguration checkConfig = new PropertiesConfiguration(filename); |
| ConfigurationAssert.assertEquals(conf, checkConfig); |
| |
| // Save it again, verifing a save with a filename works. |
| checkConfig.save(); |
| } |
| |
| public void testSaveToCustomURL() throws Exception |
| { |
| // save the configuration to a custom URL |
| URL url = new URL("foo", "", 0, "./target/testsave-custom-url.properties", new FileURLStreamHandler()); |
| conf.save(url); |
| |
| // reload the configuration |
| Configuration config2 = new PropertiesConfiguration(url); |
| assertEquals("true", config2.getString("configuration.loaded")); |
| } |
| |
| public void testInMemoryCreatedSave() throws Exception |
| { |
| PropertiesConfiguration pc = new PropertiesConfiguration(); |
| // add an array of strings to the configuration |
| pc.addProperty("string", "value1"); |
| List list = new ArrayList(); |
| for (int i = 1; i < 5; i++) |
| { |
| list.add("value" + i); |
| } |
| pc.addProperty("array", list); |
| |
| // save the configuration |
| String filename = testSavePropertiesFile.getAbsolutePath(); |
| pc.save(filename); |
| |
| assertTrue("The saved file doesn't exist", testSavePropertiesFile.exists()); |
| |
| // read the configuration and compare the properties |
| PropertiesConfiguration checkConfig = new PropertiesConfiguration(filename); |
| ConfigurationAssert.assertEquals(pc, checkConfig); |
| |
| // Save it again, verifing a save with a filename works. |
| checkConfig.save(); |
| } |
| |
| /** |
| * Tests saving a configuration when delimiter parsing is disabled. |
| */ |
| public void testSaveWithDelimiterParsingDisabled() throws ConfigurationException |
| { |
| conf.clear(); |
| conf.setDelimiterParsingDisabled(true); |
| conf.addProperty("test.list", "a,b,c"); |
| conf.addProperty("test.dirs", "C:\\Temp\\,D:\\Data\\"); |
| conf.save(testSavePropertiesFile); |
| |
| PropertiesConfiguration checkConfig = new PropertiesConfiguration(); |
| checkConfig.setDelimiterParsingDisabled(true); |
| checkConfig.setFile(testSavePropertiesFile); |
| checkConfig.load(); |
| ConfigurationAssert.assertEquals(conf, checkConfig); |
| } |
| |
| public void testSaveMissingFilename() |
| { |
| PropertiesConfiguration pc = new PropertiesConfiguration(); |
| try |
| { |
| pc.save(); |
| fail("Should have throw ConfigurationException"); |
| } |
| catch (ConfigurationException ce) |
| { |
| //good |
| } |
| } |
| |
| /** |
| * Tests if the base path is taken into account by the save() method. |
| * @throws Exception if an error occurs |
| */ |
| public void testSaveWithBasePath() throws Exception |
| { |
| conf.setProperty("test", "true"); |
| conf.setBasePath(testSavePropertiesFile.getParentFile().toURL().toString()); |
| conf.setFileName(testSavePropertiesFile.getName()); |
| conf.save(); |
| assertTrue(testSavePropertiesFile.exists()); |
| } |
| |
| /** |
| * Tests whether the escape character for list delimiters can be itself |
| * escaped and survives a save operation. |
| */ |
| public void testSaveEscapedEscapingCharacter() |
| throws ConfigurationException |
| { |
| conf.addProperty("test.dirs", "C:\\Temp\\\\,D:\\Data\\\\,E:\\Test\\"); |
| List dirs = conf.getList("test.dirs"); |
| assertEquals("Wrong number of list elements", 3, dirs.size()); |
| conf.save(testSavePropertiesFile); |
| |
| PropertiesConfiguration checkConfig = new PropertiesConfiguration( |
| testSavePropertiesFile); |
| ConfigurationAssert.assertEquals(conf, checkConfig); |
| } |
| |
| public void testLoadViaProperty() throws Exception |
| { |
| PropertiesConfiguration pc = new PropertiesConfiguration(); |
| pc.setFileName(testProperties); |
| pc.load(); |
| |
| assertTrue("Make sure we have multiple keys", pc.getBoolean("test.boolean")); |
| } |
| |
| public void testLoadViaPropertyWithBasePath() throws Exception |
| { |
| PropertiesConfiguration pc = new PropertiesConfiguration(); |
| pc.setBasePath(testBasePath); |
| pc.setFileName("test.properties"); |
| pc.load(); |
| |
| assertTrue("Make sure we have multiple keys", pc.getBoolean("test.boolean")); |
| } |
| |
| public void testLoadViaPropertyWithBasePath2() throws Exception |
| { |
| PropertiesConfiguration pc = new PropertiesConfiguration(); |
| pc.setBasePath(testBasePath2); |
| pc.setFileName("conf/test.properties"); |
| pc.load(); |
| |
| assertTrue("Make sure we have multiple keys", pc.getBoolean("test.boolean")); |
| |
| pc = new PropertiesConfiguration(); |
| pc.setBasePath(testBasePath2); |
| pc.setFileName("conf/test.properties"); |
| pc.load(); |
| |
| assertTrue("Make sure we have multiple keys", pc.getBoolean("test.boolean")); |
| } |
| |
| public void testLoadFromFile() throws Exception |
| { |
| File file = new File("conf/test.properties"); |
| conf = new PropertiesConfiguration(file); |
| |
| assertEquals("true", conf.getString("configuration.loaded")); |
| } |
| |
| public void testLoadUnexistingFile() |
| { |
| try |
| { |
| conf = new PropertiesConfiguration("Unexisting file"); |
| fail("Unexisting file was loaded."); |
| } |
| catch(ConfigurationException cex) |
| { |
| // fine |
| } |
| } |
| |
| /** |
| * Tests to load a file with enabled auto save mode. |
| */ |
| public void testLoadWithAutoSave() throws Exception |
| { |
| setUpSavedProperties(); |
| } |
| |
| /** |
| * Tests the auto save functionality when an existing property is modified. |
| */ |
| public void testLoadWithAutoSaveAndSetExisting() throws Exception |
| { |
| setUpSavedProperties(); |
| conf.setProperty("a", "moreThanOne"); |
| checkSavedConfig(); |
| } |
| |
| /** |
| * Tests the auto save functionality when a new property is added using the |
| * setProperty() method. |
| */ |
| public void testLoadWithAutoSaveAndSetNew() throws Exception |
| { |
| setUpSavedProperties(); |
| conf.setProperty("d", "four"); |
| checkSavedConfig(); |
| } |
| |
| /** |
| * Tests the auto save functionality when a new property is added using the |
| * addProperty() method. |
| */ |
| public void testLoadWithAutoSaveAndAdd() throws Exception |
| { |
| setUpSavedProperties(); |
| conf.addProperty("d", "four"); |
| checkSavedConfig(); |
| } |
| |
| /** |
| * Tests the auto save functionality when a property is removed. |
| */ |
| public void testLoadWithAutoSaveAndClear() throws Exception |
| { |
| setUpSavedProperties(); |
| conf.clearProperty("c"); |
| PropertiesConfiguration checkConfig = checkSavedConfig(); |
| assertFalse("The saved configuration contain the key '" + "c" + "'", checkConfig.containsKey("c")); |
| } |
| |
| /** |
| * Creates a properties file on disk. Used for testing load and save |
| * operations. |
| * |
| * @throws IOException if an I/O error occurs |
| */ |
| private void setUpSavedProperties() throws IOException, ConfigurationException |
| { |
| PrintWriter out = null; |
| |
| try |
| { |
| out = new PrintWriter(new FileWriter(testSavePropertiesFile)); |
| out.println("a = one"); |
| out.println("b = two"); |
| out.println("c = three"); |
| out.close(); |
| out = null; |
| |
| conf = new PropertiesConfiguration(); |
| conf.setAutoSave(true); |
| conf.setFile(testSavePropertiesFile); |
| conf.load(); |
| assertEquals("one", conf.getString("a")); |
| assertEquals("two", conf.getString("b")); |
| assertEquals("three", conf.getString("c")); |
| } |
| finally |
| { |
| if (out != null) |
| { |
| out.close(); |
| } |
| } |
| } |
| |
| /** |
| * Helper method for testing a saved configuration. Reads in the file using |
| * a new instance and compares this instance with the original one. |
| * |
| * @return the newly created configuration instance |
| * @throws ConfigurationException if an error occurs |
| */ |
| private PropertiesConfiguration checkSavedConfig() |
| throws ConfigurationException |
| { |
| PropertiesConfiguration checkConfig = new PropertiesConfiguration(testSavePropertiesFile); |
| ConfigurationAssert.assertEquals(conf, checkConfig); |
| return checkConfig; |
| } |
| |
| public void testGetStringWithEscapedChars() |
| { |
| String property = conf.getString("test.unescape"); |
| assertEquals("String with escaped characters", "This \n string \t contains \" escaped \\ characters", property); |
| } |
| |
| public void testGetStringWithEscapedComma() |
| { |
| String property = conf.getString("test.unescape.list-separator"); |
| assertEquals("String with an escaped list separator", "This string contains , an escaped list separator", property); |
| } |
| |
| public void testUnescapeJava() |
| { |
| assertEquals("test\\,test", PropertiesConfiguration.unescapeJava("test\\,test", ',')); |
| } |
| |
| public void testEscapedKey() throws Exception |
| { |
| PropertiesConfiguration conf = new PropertiesConfiguration(); |
| conf.load(new StringReader("\\u0066\\u006f\\u006f=bar")); |
| |
| assertEquals("value of the 'foo' property", "bar", conf.getString("foo")); |
| } |
| |
| public void testMixedArray() |
| { |
| String[] array = conf.getStringArray("test.mixed.array"); |
| |
| assertEquals("array length", 4, array.length); |
| assertEquals("1st element", "a", array[0]); |
| assertEquals("2nd element", "b", array[1]); |
| assertEquals("3rd element", "c", array[2]); |
| assertEquals("4th element", "d", array[3]); |
| } |
| |
| public void testMultilines() |
| { |
| String property = "This is a value spread out across several adjacent " |
| + "natural lines by escaping the line terminator with " |
| + "a backslash character."; |
| |
| assertEquals("'test.multilines' property", property, conf.getString("test.multilines")); |
| } |
| |
| public void testChangingDefaultListDelimiter() throws Exception |
| { |
| PropertiesConfiguration pc = new PropertiesConfiguration(testProperties); |
| assertEquals(4, pc.getList("test.mixed.array").size()); |
| |
| char delimiter = PropertiesConfiguration.getDefaultListDelimiter(); |
| PropertiesConfiguration.setDefaultListDelimiter('^'); |
| pc = new PropertiesConfiguration(testProperties); |
| assertEquals(2, pc.getList("test.mixed.array").size()); |
| PropertiesConfiguration.setDefaultListDelimiter(delimiter); |
| } |
| |
| public void testChangingListDelimiter() throws Exception |
| { |
| PropertiesConfiguration pc1 = new PropertiesConfiguration(testProperties); |
| assertEquals(4, pc1.getList("test.mixed.array").size()); |
| |
| PropertiesConfiguration pc2 = new PropertiesConfiguration(); |
| pc2.setListDelimiter('^'); |
| pc2.setFileName(testProperties); |
| pc2.load(); |
| assertEquals("Should obtain the first value", "a", pc2.getString("test.mixed.array")); |
| assertEquals(2, pc2.getList("test.mixed.array").size()); |
| } |
| |
| public void testDisableListDelimiter() throws Exception |
| { |
| PropertiesConfiguration pc1 = new PropertiesConfiguration(testProperties); |
| assertEquals(4, pc1.getList("test.mixed.array").size()); |
| |
| PropertiesConfiguration pc2 = new PropertiesConfiguration(); |
| pc2.setDelimiterParsingDisabled(true); |
| pc2.setFileName(testProperties); |
| pc2.load(); |
| assertEquals(2, pc2.getList("test.mixed.array").size()); |
| } |
| |
| /** |
| * Tests escaping of an end of line with a backslash. |
| */ |
| public void testNewLineEscaping() |
| { |
| List list = conf.getList("test.path"); |
| assertEquals(3, list.size()); |
| assertEquals("C:\\path1\\", list.get(0)); |
| assertEquals("C:\\path2\\", list.get(1)); |
| assertEquals("C:\\path3\\complex\\test\\", list.get(2)); |
| } |
| |
| /** |
| * Tests if included files are loaded when the source lies in the class path. |
| */ |
| public void testLoadIncludeFromClassPath() throws ConfigurationException |
| { |
| conf = new PropertiesConfiguration("test.properties"); |
| assertEquals("true", conf.getString("include.loaded")); |
| } |
| |
| /** |
| * Test if the lines starting with # or ! are properly ignored. |
| */ |
| public void testComment() { |
| assertFalse("comment line starting with '#' parsed as a property", conf.containsKey("#comment")); |
| assertFalse("comment line starting with '!' parsed as a property", conf.containsKey("!comment")); |
| } |
| |
| /** |
| * Check that key/value separators can be part of a key. |
| */ |
| public void testEscapedKeyValueSeparator() |
| { |
| assertEquals("Escaped separator '=' not supported in keys", "foo", conf.getProperty("test.separator=in.key")); |
| assertEquals("Escaped separator ':' not supported in keys", "bar", conf.getProperty("test.separator:in.key")); |
| assertEquals("Escaped separator '\\t' not supported in keys", "foo", conf.getProperty("test.separator\tin.key")); |
| assertEquals("Escaped separator '\\f' not supported in keys", "bar", conf.getProperty("test.separator\fin.key")); |
| assertEquals("Escaped separator ' ' not supported in keys" , "foo", conf.getProperty("test.separator in.key")); |
| } |
| |
| /** |
| * Test all acceptable key/value separators ('=', ':' or white spaces). |
| */ |
| public void testKeyValueSeparators() { |
| assertEquals("equal separator not properly parsed", "foo", conf.getProperty("test.separator.equal")); |
| assertEquals("colon separator not properly parsed", "foo", conf.getProperty("test.separator.colon")); |
| assertEquals("tab separator not properly parsed", "foo", conf.getProperty("test.separator.tab")); |
| assertEquals("formfeed separator not properly parsed", "foo", conf.getProperty("test.separator.formfeed")); |
| assertEquals("whitespace separator not properly parsed", "foo", conf.getProperty("test.separator.whitespace")); |
| } |
| |
| /** |
| * Tests including properties when they are loaded from a nested directory |
| * structure. |
| */ |
| public void testIncludeInSubDir() throws ConfigurationException |
| { |
| ConfigurationFactory factory = new ConfigurationFactory("conf/testFactoryPropertiesInclude.xml"); |
| Configuration config = factory.getConfiguration(); |
| assertEquals(true, config.getBoolean("deeptest")); |
| assertEquals(true, config.getBoolean("deepinclude")); |
| assertFalse(config.containsKey("deeptestinvalid")); |
| } |
| |
| /** |
| * Tests whether the correct line separator is used. |
| */ |
| public void testLineSeparator() throws ConfigurationException |
| { |
| final String EOL = System.getProperty("line.separator"); |
| conf = new PropertiesConfiguration(); |
| conf.setHeader("My header"); |
| conf.setProperty("prop", "value"); |
| |
| StringWriter out = new StringWriter(); |
| conf.save(out); |
| String content = out.toString(); |
| assertTrue("Header could not be found", content.indexOf("# My header" |
| + EOL + EOL) == 0); |
| assertTrue("Property could not be found", content.indexOf("prop = value" + EOL) > 0); |
| } |
| |
| /** |
| * Tests what happens if a reloading strategy's <code>reloadingRequired()</code> |
| * implementation accesses methods of the configuration that in turn cause a reload. |
| */ |
| public void testReentrantReload() |
| { |
| conf.setProperty("shouldReload", Boolean.FALSE); |
| conf.setReloadingStrategy(new FileChangedReloadingStrategy() |
| { |
| public boolean reloadingRequired() |
| { |
| return configuration.getBoolean("shouldReload"); |
| } |
| }); |
| assertFalse("Property has wrong value", conf.getBoolean("shouldReload")); |
| } |
| |
| /** |
| * Tests accessing the layout object. |
| */ |
| public void testGetLayout() |
| { |
| PropertiesConfigurationLayout layout = conf.getLayout(); |
| assertNotNull("Layout is null", layout); |
| assertSame("Different object returned", layout, conf.getLayout()); |
| conf.setLayout(null); |
| PropertiesConfigurationLayout layout2 = conf.getLayout(); |
| assertNotNull("Layout 2 is null", layout2); |
| assertNotSame("Same object returned", layout, layout2); |
| } |
| |
| /** |
| * Tests the propertyLoaded() method for a simple property. |
| */ |
| public void testPropertyLoaded() throws ConfigurationException |
| { |
| DummyLayout layout = new DummyLayout(conf); |
| conf.setLayout(layout); |
| conf.propertyLoaded("layoutLoadedProperty", "yes"); |
| assertEquals("Layout's load() was called", 0, layout.loadCalls); |
| assertEquals("Property not added", "yes", conf.getString("layoutLoadedProperty")); |
| } |
| |
| /** |
| * Tests the propertyLoaded() method for an include property. |
| */ |
| public void testPropertyLoadedInclude() throws ConfigurationException |
| { |
| DummyLayout layout = new DummyLayout(conf); |
| conf.setLayout(layout); |
| conf.propertyLoaded(PropertiesConfiguration.getInclude(), "testClasspath.properties,testEqual.properties"); |
| assertEquals("Layout's load() was not correctly called", 2, layout.loadCalls); |
| assertFalse("Property was added", conf.containsKey(PropertiesConfiguration.getInclude())); |
| } |
| |
| /** |
| * Tests propertyLoaded() for an include property, when includes are |
| * disabled. |
| */ |
| public void testPropertyLoadedIncludeNotAllowed() throws ConfigurationException |
| { |
| DummyLayout layout = new DummyLayout(conf); |
| conf.setLayout(layout); |
| conf.setIncludesAllowed(false); |
| conf.propertyLoaded(PropertiesConfiguration.getInclude(), "testClassPath.properties,testEqual.properties"); |
| assertEquals("Layout's load() was called", 0, layout.loadCalls); |
| assertFalse("Property was added", conf.containsKey(PropertiesConfiguration.getInclude())); |
| } |
| |
| /** |
| * Tests whether comment lines are correctly detected. |
| */ |
| public void testIsCommentLine() |
| { |
| assertTrue("Comment not detected", PropertiesConfiguration.isCommentLine("# a comment")); |
| assertTrue("Alternative comment not detected", PropertiesConfiguration.isCommentLine("! a comment")); |
| assertTrue("Comment with no space not detected", PropertiesConfiguration.isCommentLine("#a comment")); |
| assertTrue("Comment with leading space not detected", PropertiesConfiguration.isCommentLine(" ! a comment")); |
| assertFalse("Wrong comment", PropertiesConfiguration.isCommentLine(" a#comment")); |
| } |
| |
| /** |
| * Tests whether a properties configuration can be successfully cloned. It |
| * is especially checked whether the layout object is taken into account. |
| */ |
| public void testClone() throws ConfigurationException |
| { |
| PropertiesConfiguration copy = (PropertiesConfiguration) conf.clone(); |
| assertNotSame("Copy has same layout object", conf.getLayout(), copy.getLayout()); |
| assertEquals("Wrong number of event listeners for original", 1, conf.getConfigurationListeners().size()); |
| assertEquals("Wrong number of event listeners for clone", 1, copy.getConfigurationListeners().size()); |
| assertSame("Wrong event listener for original", conf.getLayout(), conf.getConfigurationListeners().iterator().next()); |
| assertSame("Wrong event listener for clone", copy.getLayout(), copy.getConfigurationListeners().iterator().next()); |
| StringWriter outConf = new StringWriter(); |
| conf.save(outConf); |
| StringWriter outCopy = new StringWriter(); |
| copy.save(outCopy); |
| assertEquals("Output from copy is different", outConf.toString(), outCopy.toString()); |
| } |
| |
| /** |
| * Tests the clone() method when no layout object exists yet. |
| */ |
| public void testCloneNullLayout() |
| { |
| conf = new PropertiesConfiguration(); |
| PropertiesConfiguration copy = (PropertiesConfiguration) conf.clone(); |
| assertNotSame("Layout objects are the same", conf.getLayout(), copy.getLayout()); |
| } |
| |
| /** |
| * Tests saving a file-based configuration to a HTTP server. |
| */ |
| public void testSaveToHTTPServerSuccess() throws Exception |
| { |
| MockHttpURLStreamHandler handler = new MockHttpURLStreamHandler( |
| HttpURLConnection.HTTP_OK, testSavePropertiesFile); |
| URL url = new URL(null, "http://jakarta.apache.org", handler); |
| conf.save(url); |
| MockHttpURLConnection con = handler.getMockConnection(); |
| assertTrue("Wrong output flag", con.getDoOutput()); |
| assertEquals("Wrong method", "PUT", con.getRequestMethod()); |
| |
| PropertiesConfiguration checkConfig = new PropertiesConfiguration( |
| testSavePropertiesFile); |
| ConfigurationAssert.assertEquals(conf, checkConfig); |
| } |
| |
| /** |
| * Tests saving a file-based configuration to a HTTP server when the server |
| * reports a failure. This should cause an exception. |
| */ |
| public void testSaveToHTTPServerFail() throws Exception |
| { |
| MockHttpURLStreamHandler handler = new MockHttpURLStreamHandler( |
| HttpURLConnection.HTTP_BAD_REQUEST, testSavePropertiesFile); |
| URL url = new URL(null, "http://jakarta.apache.org", handler); |
| try |
| { |
| conf.save(url); |
| fail("Response code was not checked!"); |
| } |
| catch (ConfigurationException cex) |
| { |
| assertTrue("Wrong root cause: " + cex, |
| cex.getCause() instanceof IOException); |
| } |
| } |
| |
| /** |
| * Test the creation of a file containing a '#' in its name. This test is |
| * skipped on Java 1.3 as it always fails. |
| */ |
| public void testFileWithSharpSymbol() throws Exception |
| { |
| if (SystemUtils.isJavaVersionAtLeast(1.4f)) |
| { |
| File file = new File("target/sharp#1.properties"); |
| file.createNewFile(); |
| |
| PropertiesConfiguration conf = new PropertiesConfiguration(file); |
| conf.save(); |
| |
| assertTrue("Missing file " + file, file.exists()); |
| } |
| } |
| |
| /** |
| * Tests initializing a properties configuration from a non existing file. |
| * There was a bug, which caused properties getting lost when later save() |
| * is called. |
| */ |
| public void testInitFromNonExistingFile() throws ConfigurationException |
| { |
| final String testProperty = "test.successfull"; |
| conf = new PropertiesConfiguration(testSavePropertiesFile); |
| conf.addProperty(testProperty, Boolean.TRUE); |
| conf.save(); |
| PropertiesConfiguration checkConfig = new PropertiesConfiguration( |
| testSavePropertiesFile); |
| assertTrue("Test property not found", checkConfig |
| .getBoolean(testProperty)); |
| } |
| |
| /** |
| * Tests copying another configuration into the test configuration. This |
| * test ensures that the layout object is informed about the newly added |
| * properties. |
| */ |
| public void testCopyAndSave() throws ConfigurationException |
| { |
| Configuration copyConf = setUpCopyConfig(); |
| conf.copy(copyConf); |
| checkCopiedConfig(copyConf); |
| } |
| |
| /** |
| * Tests appending a configuration to the test configuration. Again it has |
| * to be ensured that the layout object is correctly updated. |
| */ |
| public void testAppendAndSave() throws ConfigurationException |
| { |
| Configuration copyConf = setUpCopyConfig(); |
| conf.append(copyConf); |
| checkCopiedConfig(copyConf); |
| } |
| |
| /** |
| * Tests adding properties through a DataConfiguration. This is related to |
| * CONFIGURATION-332. |
| */ |
| public void testSaveWithDataConfig() throws ConfigurationException |
| { |
| conf = new PropertiesConfiguration(testSavePropertiesFile); |
| DataConfiguration dataConfig = new DataConfiguration(conf); |
| dataConfig.setProperty("foo", "bar"); |
| assertEquals("Property not set", "bar", conf.getString("foo")); |
| |
| conf.save(); |
| PropertiesConfiguration config2 = new PropertiesConfiguration( |
| testSavePropertiesFile); |
| assertEquals("Property not saved", "bar", config2.getString("foo")); |
| } |
| |
| /** |
| * Tests whether the correct default encoding is used when loading a |
| * properties file. This test is related to CONFIGURATION-345. |
| */ |
| public void testLoadWithDefaultEncoding() throws ConfigurationException |
| { |
| class PropertiesConfigurationTestImpl extends PropertiesConfiguration |
| { |
| String loadEncoding; |
| |
| public PropertiesConfigurationTestImpl(String fileName) |
| throws ConfigurationException |
| { |
| super(fileName); |
| } |
| |
| public void load(InputStream in, String encoding) |
| throws ConfigurationException |
| { |
| loadEncoding = encoding; |
| super.load(in, encoding); |
| } |
| } |
| |
| PropertiesConfigurationTestImpl testConf = new PropertiesConfigurationTestImpl( |
| testProperties); |
| assertEquals("Default encoding not used", "ISO-8859-1", |
| testConf.loadEncoding); |
| } |
| |
| /** |
| * Tests whether a default IOFactory is set. |
| */ |
| public void testGetIOFactoryDefault() |
| { |
| assertNotNull("No default IO factory", conf.getIOFactory()); |
| } |
| |
| /** |
| * Tests setting the IOFactory to null. This should cause an exception. |
| */ |
| public void testSetIOFactoryNull() |
| { |
| try |
| { |
| conf.setIOFactory(null); |
| fail("Could set IO factory to null!"); |
| } |
| catch (IllegalArgumentException iex) |
| { |
| // ok |
| } |
| } |
| |
| /** |
| * Tests setting an IOFactory that uses a specialized reader. |
| */ |
| public void testSetIOFactoryReader() throws ConfigurationException |
| { |
| final int propertyCount = 10; |
| conf.clear(); |
| conf.setIOFactory(new PropertiesConfiguration.IOFactory() |
| { |
| public PropertiesConfiguration.PropertiesReader createPropertiesReader( |
| Reader in, char delimiter) |
| { |
| return new PropertiesReaderTestImpl(in, delimiter, |
| propertyCount); |
| } |
| |
| public PropertiesConfiguration.PropertiesWriter createPropertiesWriter( |
| Writer out, char delimiter) |
| { |
| throw new UnsupportedOperationException("Unexpected call!"); |
| } |
| }); |
| conf.load(); |
| for (int i = 1; i <= propertyCount; i++) |
| { |
| assertEquals("Wrong property value at " + i, PROP_VALUE + i, conf |
| .getString(PROP_NAME + i)); |
| } |
| } |
| |
| /** |
| * Tests setting an IOFactory that uses a specialized writer. |
| */ |
| public void testSetIOFactoryWriter() throws ConfigurationException, IOException |
| { |
| final PropertiesWriterTestImpl testWriter = new PropertiesWriterTestImpl(','); |
| conf.setIOFactory(new PropertiesConfiguration.IOFactory() |
| { |
| public PropertiesConfiguration.PropertiesReader createPropertiesReader( |
| Reader in, char delimiter) |
| { |
| throw new UnsupportedOperationException("Unexpected call!"); |
| } |
| |
| public PropertiesConfiguration.PropertiesWriter createPropertiesWriter( |
| Writer out, char delimiter) |
| { |
| return testWriter; |
| } |
| }); |
| conf.save(new StringWriter()); |
| testWriter.close(); |
| checkSavedConfig(); |
| } |
| |
| /** |
| * Tests that the property separators are retained when saving the |
| * configuration. |
| */ |
| public void testKeepSeparators() throws ConfigurationException, IOException |
| { |
| conf.save(testSavePropertiesFile); |
| final String[] separatorTests = { |
| "test.separator.equal = foo", "test.separator.colon : foo", |
| "test.separator.tab\tfoo", "test.separator.whitespace foo", |
| "test.separator.no.space=foo" |
| }; |
| Set foundLines = new HashSet(); |
| BufferedReader in = new BufferedReader(new FileReader( |
| testSavePropertiesFile)); |
| try |
| { |
| String s; |
| while ((s = in.readLine()) != null) |
| { |
| for (int i = 0; i < separatorTests.length; i++) |
| { |
| if (separatorTests[i].equals(s)) |
| { |
| foundLines.add(s); |
| } |
| } |
| } |
| } |
| finally |
| { |
| in.close(); |
| } |
| assertEquals("No all separators were found: " + foundLines, |
| separatorTests.length, foundLines.size()); |
| } |
| |
| /** |
| * Creates a configuration that can be used for testing copy operations. |
| * |
| * @return the configuration to be copied |
| */ |
| private Configuration setUpCopyConfig() |
| { |
| final int count = 25; |
| Configuration result = new BaseConfiguration(); |
| for (int i = 1; i <= count; i++) |
| { |
| result.addProperty("copyKey" + i, "copyValue" + i); |
| } |
| return result; |
| } |
| |
| /** |
| * Tests whether the data of a configuration that was copied into the test |
| * configuration is correctly saved. |
| * |
| * @param copyConf the copied configuration |
| * @throws ConfigurationException if an error occurs |
| */ |
| private void checkCopiedConfig(Configuration copyConf) |
| throws ConfigurationException |
| { |
| conf.save(testSavePropertiesFile); |
| PropertiesConfiguration checkConf = new PropertiesConfiguration( |
| testSavePropertiesFile); |
| for (Iterator it = copyConf.getKeys(); it.hasNext();) |
| { |
| String key = (String) it.next(); |
| assertEquals("Wrong value for property " + key, checkConf |
| .getProperty(key), copyConf.getProperty(key)); |
| } |
| } |
| |
| /** |
| * A dummy layout implementation for checking whether certain methods are |
| * correctly called by the configuration. |
| */ |
| static class DummyLayout extends PropertiesConfigurationLayout |
| { |
| /** Stores the number how often load() was called. */ |
| public int loadCalls; |
| |
| public DummyLayout(PropertiesConfiguration config) |
| { |
| super(config); |
| } |
| |
| public void load(Reader in) throws ConfigurationException |
| { |
| loadCalls++; |
| } |
| } |
| |
| /** |
| * A mock implementation of a HttpURLConnection used for testing saving to |
| * a HTTP server. |
| */ |
| static class MockHttpURLConnection extends HttpURLConnection |
| { |
| /** The response code to return.*/ |
| private int responseCode; |
| |
| /** The output file. The output stream will point to this file.*/ |
| private File outputFile; |
| |
| protected MockHttpURLConnection(URL u, int respCode, File outFile) |
| { |
| super(u); |
| responseCode = respCode; |
| outputFile = outFile; |
| } |
| |
| public void disconnect() |
| { |
| } |
| |
| public boolean usingProxy() |
| { |
| return false; |
| } |
| |
| public void connect() throws IOException |
| { |
| } |
| |
| public int getResponseCode() throws IOException |
| { |
| return responseCode; |
| } |
| |
| public OutputStream getOutputStream() throws IOException |
| { |
| return new FileOutputStream(outputFile); |
| } |
| } |
| |
| /** |
| * A mock stream handler for working with the mock HttpURLConnection. |
| */ |
| static class MockHttpURLStreamHandler extends URLStreamHandler |
| { |
| /** Stores the response code.*/ |
| private int responseCode; |
| |
| /** Stores the output file.*/ |
| private File outputFile; |
| |
| /** Stores the connection.*/ |
| private MockHttpURLConnection connection; |
| |
| public MockHttpURLStreamHandler(int respCode, File outFile) |
| { |
| responseCode = respCode; |
| outputFile = outFile; |
| } |
| |
| public MockHttpURLConnection getMockConnection() |
| { |
| return connection; |
| } |
| |
| protected URLConnection openConnection(URL u) throws IOException |
| { |
| connection = new MockHttpURLConnection(u, responseCode, outputFile); |
| return connection; |
| } |
| } |
| |
| /** |
| * A test PropertiesReader for testing whether a custom reader can be |
| * injected. This implementation creates a configurable number of synthetic |
| * test properties. |
| */ |
| private static class PropertiesReaderTestImpl extends |
| PropertiesConfiguration.PropertiesReader |
| { |
| /** The number of test properties to be created. */ |
| private final int maxProperties; |
| |
| /** The current number of properties. */ |
| private int propertyCount; |
| |
| public PropertiesReaderTestImpl(Reader reader, char listDelimiter, |
| int maxProps) |
| { |
| super(reader, listDelimiter); |
| assertEquals("Wrong list delimiter", ',', listDelimiter); |
| maxProperties = maxProps; |
| } |
| |
| public String getPropertyName() |
| { |
| return PROP_NAME + propertyCount; |
| } |
| |
| public String getPropertyValue() |
| { |
| return PROP_VALUE + propertyCount; |
| } |
| |
| public boolean nextProperty() throws IOException |
| { |
| propertyCount++; |
| return propertyCount <= maxProperties; |
| } |
| } |
| |
| /** |
| * A test PropertiesWriter for testing whether a custom writer can be |
| * injected. This implementation simply redirects all output into a test |
| * file. |
| */ |
| private static class PropertiesWriterTestImpl extends |
| PropertiesConfiguration.PropertiesWriter |
| { |
| public PropertiesWriterTestImpl(char delimiter) throws IOException |
| { |
| super(new FileWriter(testSavePropertiesFile), delimiter); |
| } |
| } |
| } |