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.assertNotSame;
023    import static org.junit.Assert.assertNull;
024    import static org.junit.Assert.assertSame;
025    import static org.junit.Assert.assertTrue;
026    
027    import java.io.File;
028    import java.net.MalformedURLException;
029    import java.net.URL;
030    import java.util.ArrayList;
031    import java.util.Iterator;
032    import java.util.List;
033    
034    import junitx.framework.ListAssert;
035    
036    import org.apache.commons.configuration.tree.DefaultExpressionEngine;
037    import org.apache.commons.configuration.tree.ExpressionEngine;
038    import org.junit.Test;
039    
040    import com.mockobjects.dynamic.Mock;
041    
042    /**
043     * Tests the ConfigurationUtils class
044     *
045     * @version $Id: TestConfigurationUtils.java 1301996 2012-03-17 20:30:39Z sebb $
046     */
047    public class TestConfigurationUtils
048    {
049        protected Configuration config = new BaseConfiguration();
050    
051        @Test
052        public void testToString()
053        {
054            String lineSeparator = System.getProperty("line.separator");
055    
056            assertEquals("String representation of an empty configuration", "", ConfigurationUtils.toString(config));
057    
058            config.setProperty("one", "1");
059            assertEquals("String representation of a configuration", "one=1", ConfigurationUtils.toString(config));
060    
061            config.setProperty("two", "2");
062            assertEquals("String representation of a configuration", "one=1" + lineSeparator + "two=2" , ConfigurationUtils.toString(config));
063    
064            config.clearProperty("one");
065            assertEquals("String representation of a configuration", "two=2" , ConfigurationUtils.toString(config));
066    
067            config.setProperty("one","1");
068            assertEquals("String representation of a configuration", "two=2" + lineSeparator + "one=1" , ConfigurationUtils.toString(config));
069        }
070    
071        @Test
072        public void testGetURL() throws Exception
073        {
074            assertEquals(
075                "http://localhost:8080/webapp/config/config.xml",
076                ConfigurationUtils
077                    .getURL(
078                        "http://localhost:8080/webapp/config/baseConfig.xml",
079                        "config.xml")
080                    .toString());
081            assertEquals(
082                "http://localhost:8080/webapp/config/config.xml",
083                ConfigurationUtils
084                    .getURL(
085                        "http://localhost:8080/webapp/baseConfig.xml",
086                        "config/config.xml")
087                    .toString());
088            URL url = ConfigurationUtils.getURL(null, "config.xml");
089            assertEquals("file", url.getProtocol());
090            assertEquals("", url.getHost());
091    
092            assertEquals(
093                "http://localhost:8080/webapp/config/config.xml",
094                ConfigurationUtils
095                    .getURL(
096                        "ftp://ftp.server.com/downloads/baseConfig.xml",
097                        "http://localhost:8080/webapp/config/config.xml")
098                    .toString());
099            assertEquals(
100                "http://localhost:8080/webapp/config/config.xml",
101                ConfigurationUtils
102                    .getURL(null, "http://localhost:8080/webapp/config/config.xml")
103                    .toString());
104            File absFile = new File("config.xml").getAbsoluteFile();
105            assertEquals(
106                absFile.toURI().toURL(),
107                ConfigurationUtils.getURL(
108                    "http://localhost:8080/webapp/config/baseConfig.xml",
109                    absFile.getAbsolutePath()));
110            assertEquals(
111                absFile.toURI().toURL(),
112                ConfigurationUtils.getURL(null, absFile.getAbsolutePath()));
113    
114            assertEquals(absFile.toURI().toURL(),
115            ConfigurationUtils.getURL(absFile.getParent(), "config.xml"));
116        }
117    
118        @Test
119        public void testGetBasePath() throws Exception
120        {
121            URL url = new URL("http://xyz.net/foo/bar.xml");
122            assertEquals("base path of " + url, "http://xyz.net/foo/", ConfigurationUtils.getBasePath(url));
123    
124            url = new URL("http://xyz.net/foo/");
125            assertEquals("base path of " + url, "http://xyz.net/foo/", ConfigurationUtils.getBasePath(url));
126    
127            url = new URL("http://xyz.net/foo");
128            assertEquals("base path of " + url, "http://xyz.net/", ConfigurationUtils.getBasePath(url));
129    
130            url = new URL("http://xyz.net/");
131            assertEquals("base path of " + url, "http://xyz.net/", ConfigurationUtils.getBasePath(url));
132    
133            url = new URL("http://xyz.net");
134            assertEquals("base path of " + url, "http://xyz.net", ConfigurationUtils.getBasePath(url));
135        }
136    
137        @Test
138        public void testGetFileName() throws Exception
139        {
140            assertEquals("file name for a null URL", null, ConfigurationUtils.getFileName(null));
141    
142            URL url = new URL("http://xyz.net/foo/");
143            assertEquals("file for a directory URL " + url, null, ConfigurationUtils.getFileName(url));
144    
145            url = new URL("http://xyz.net/foo/bar.xml");
146            assertEquals("file name for a valid URL " + url, "bar.xml", ConfigurationUtils.getFileName(url));
147        }
148    
149        @Test
150        public void testCopy()
151        {
152            // create the source configuration
153            Configuration conf1 = new BaseConfiguration();
154            conf1.addProperty("key1", "value1");
155            conf1.addProperty("key2", "value2");
156    
157            // create the target configuration
158            Configuration conf2 = new BaseConfiguration();
159            conf2.addProperty("key1", "value3");
160            conf2.addProperty("key2", "value4");
161    
162            // copy the source configuration into the target configuration
163            ConfigurationUtils.copy(conf1, conf2);
164    
165            assertEquals("'key1' property", "value1", conf2.getProperty("key1"));
166            assertEquals("'key2' property", "value2", conf2.getProperty("key2"));
167        }
168    
169        @Test
170        public void testAppend()
171        {
172            // create the source configuration
173            Configuration conf1 = new BaseConfiguration();
174            conf1.addProperty("key1", "value1");
175            conf1.addProperty("key2", "value2");
176    
177            // create the target configuration
178            Configuration conf2 = new BaseConfiguration();
179            conf2.addProperty("key1", "value3");
180            conf2.addProperty("key2", "value4");
181    
182            // append the source configuration to the target configuration
183            ConfigurationUtils.append(conf1, conf2);
184    
185            List<Object> expected = new ArrayList<Object>();
186            expected.add("value3");
187            expected.add("value1");
188            ListAssert.assertEquals("'key1' property", expected, conf2.getList("key1"));
189    
190            expected = new ArrayList<Object>();
191            expected.add("value4");
192            expected.add("value2");
193            ListAssert.assertEquals("'key2' property", expected, conf2.getList("key2"));
194        }
195    
196        @Test
197        public void testGetFile() throws Exception
198        {
199            File directory = new File("target");
200            File reference = new File(directory, "test.txt").getAbsoluteFile();
201    
202            assertEquals(reference, ConfigurationUtils.getFile(null, reference.getAbsolutePath()));
203            assertEquals(reference, ConfigurationUtils.getFile(directory.getAbsolutePath(), reference.getAbsolutePath()));
204            assertEquals(reference, ConfigurationUtils.getFile(directory.getAbsolutePath(), reference.getName()));
205            assertEquals(reference, ConfigurationUtils.getFile(directory.toURI().toURL().toString(), reference.getName()));
206            assertEquals(reference, ConfigurationUtils.getFile("invalid", reference.toURI().toURL().toString()));
207            assertEquals(reference, ConfigurationUtils.getFile(
208                    "jar:file:/C:/myjar.jar!/my-config.xml/someprops.properties",
209                    reference.getAbsolutePath()));
210        }
211    
212        /**
213         * Tests whether a "+" character in the file name is handled correctly by
214         * fileFromURL(). This test is related to CONFIGURATION-415.
215         */
216        @Test
217        public void testFileFromURLWithPlus() throws MalformedURLException
218        {
219            File file = new File(new File("target"), "foo+bar.txt")
220                    .getAbsoluteFile();
221            URL fileURL = file.toURI().toURL();
222            File file2 = ConfigurationUtils.fileFromURL(fileURL);
223            assertEquals("Wrong file", file, file2);
224        }
225    
226        /**
227         * Tests whether fileFromURL() handles null URLs correctly.
228         */
229        @Test
230        public void testFileFromURLNull() throws Exception
231        {
232            assertNull("Wrong file for null URL", ConfigurationUtils
233                    .fileFromURL(null));
234        }
235    
236        @Test
237        public void testLocateWithNullTCCL() throws Exception
238        {
239            ClassLoader cl = Thread.currentThread().getContextClassLoader();
240            try
241            {
242                Thread.currentThread().setContextClassLoader(null);
243                assertNull(ConfigurationUtils.locate("abase", "aname"));
244                // This assert fails when maven 2 is used, so commented out
245                //assertNotNull(ConfigurationUtils.locate("test.xml"));
246            }
247            finally
248            {
249                Thread.currentThread().setContextClassLoader(cl);
250            }
251        }
252    
253        /**
254         * Tests converting a configuration into a hierarchical one.
255         */
256        @Test
257        public void testConvertToHierarchical()
258        {
259            Configuration conf = new BaseConfiguration();
260            for (int i = 0; i < 10; i++)
261            {
262                conf.addProperty("test" + i, "value" + i);
263                conf.addProperty("test.list", "item" + i);
264            }
265    
266            HierarchicalConfiguration hc = ConfigurationUtils
267                    .convertToHierarchical(conf);
268            for (Iterator<String> it = conf.getKeys(); it.hasNext();)
269            {
270                String key = it.next();
271                assertEquals("Wrong value for key " + key, conf.getProperty(key),
272                        hc.getProperty(key));
273            }
274        }
275    
276        /**
277         * Tests converting a configuration into a hierarchical one that is already
278         * hierarchical.
279         */
280        @Test
281        public void testConvertHierarchicalToHierarchical()
282        {
283            Configuration conf = new HierarchicalConfiguration();
284            conf.addProperty("test", "yes");
285            assertSame("Wrong configuration returned", conf, ConfigurationUtils
286                    .convertToHierarchical(conf));
287        }
288    
289        /**
290         * Tests converting a null configuration to a hierarchical one. The result
291         * should be null, too.
292         */
293        @Test
294        public void testConvertNullToHierarchical()
295        {
296            assertNull("Wrong conversion result for null config",
297                    ConfigurationUtils.convertToHierarchical(null));
298        }
299    
300        /**
301         * Tests converting a configuration into a hierarchical one if some of its
302         * properties contain escaped list delimiter characters.
303         */
304        @Test
305        public void testConvertToHierarchicalDelimiters()
306        {
307            Configuration conf = new BaseConfiguration();
308            conf.addProperty("test.key", "1\\,2\\,3");
309            assertEquals("Wrong property value", "1,2,3", conf
310                    .getString("test.key"));
311            HierarchicalConfiguration hc = ConfigurationUtils
312                    .convertToHierarchical(conf);
313            assertEquals("Escaped list delimiters not correctly handled", "1,2,3",
314                    hc.getString("test.key"));
315        }
316    
317        /**
318         * Tests converting a configuration to a hierarchical one using a specific
319         * expression engine.
320         */
321        @Test
322        public void testConvertToHierarchicalEngine()
323        {
324            Configuration conf = new BaseConfiguration();
325            conf.addProperty("test(a)", Boolean.TRUE);
326            conf.addProperty("test(b)", Boolean.FALSE);
327            DefaultExpressionEngine engine = new DefaultExpressionEngine();
328            engine.setIndexStart("[");
329            engine.setIndexEnd("]");
330            HierarchicalConfiguration hc = ConfigurationUtils
331                    .convertToHierarchical(conf, engine);
332            assertTrue("Wrong value for test(a)", hc.getBoolean("test(a)"));
333            assertFalse("Wrong value for test(b)", hc.getBoolean("test(b)"));
334        }
335    
336        /**
337         * Tests converting an already hierarchical configuration using an
338         * expression engine. The new engine should be set.
339         */
340        @Test
341        public void testConvertHierarchicalToHierarchicalEngine()
342        {
343            HierarchicalConfiguration hc = new HierarchicalConfiguration();
344            ExpressionEngine engine = new DefaultExpressionEngine();
345            assertSame("Created new configuration", hc, ConfigurationUtils
346                    .convertToHierarchical(hc, engine));
347            assertSame("Engine was not set", engine, hc.getExpressionEngine());
348        }
349    
350        /**
351         * Tests converting an already hierarchical configuration using a null
352         * expression engine. In this case the expression engine of the
353         * configuration should not be touched.
354         */
355        @Test
356        public void testConvertHierarchicalToHierarchicalNullEngine()
357        {
358            HierarchicalConfiguration hc = new HierarchicalConfiguration();
359            ExpressionEngine engine = new DefaultExpressionEngine();
360            hc.setExpressionEngine(engine);
361            assertSame("Created new configuration", hc, ConfigurationUtils
362                    .convertToHierarchical(hc, null));
363            assertSame("Expression engine was changed", engine, hc
364                    .getExpressionEngine());
365        }
366    
367        /**
368         * Tests converting a configuration to a hierarchical one that contains a
369         * property with multiple values. This test is related to CONFIGURATION-346.
370         */
371        @Test
372        public void testConvertToHierarchicalMultiValues()
373        {
374            BaseConfiguration config = new BaseConfiguration();
375            config.addProperty("test", "1,2,3");
376            HierarchicalConfiguration hc = ConfigurationUtils
377                    .convertToHierarchical(config);
378            assertEquals("Wrong value 1", 1, hc.getInt("test(0)"));
379            assertEquals("Wrong value 2", 2, hc.getInt("test(1)"));
380            assertEquals("Wrong value 3", 3, hc.getInt("test(2)"));
381        }
382    
383        /**
384         * Tests cloning a configuration that supports this operation.
385         */
386        @Test
387        public void testCloneConfiguration()
388        {
389            HierarchicalConfiguration conf = new HierarchicalConfiguration();
390            conf.addProperty("test", "yes");
391            HierarchicalConfiguration copy = (HierarchicalConfiguration) ConfigurationUtils
392                    .cloneConfiguration(conf);
393            assertNotSame("Same object was returned", conf, copy);
394            assertEquals("Property was not cloned", "yes", copy.getString("test"));
395        }
396    
397        /**
398         * Tests cloning a configuration that does not support this operation. This
399         * should cause an exception.
400         */
401        @Test(expected = ConfigurationRuntimeException.class)
402        public void testCloneConfigurationNotSupported()
403        {
404            Configuration myNonCloneableConfig = new NonCloneableConfiguration();
405            ConfigurationUtils.cloneConfiguration(myNonCloneableConfig);
406        }
407    
408        /**
409         * Tests cloning a <b>null</b> configuration.
410         */
411        @Test
412        public void testCloneConfigurationNull()
413        {
414            assertNull("Wrong return value", ConfigurationUtils
415                    .cloneConfiguration(null));
416        }
417    
418        /**
419         * Tests whether runtime exceptions can be enabled.
420         */
421        @Test(expected = ConfigurationRuntimeException.class)
422        public void testEnableRuntimeExceptions()
423        {
424            PropertiesConfiguration config = new PropertiesConfiguration()
425            {
426                @Override
427                protected void addPropertyDirect(String key, Object value)
428                {
429                    // always simulate an exception
430                    fireError(EVENT_ADD_PROPERTY, key, value, new RuntimeException(
431                            "A faked exception!"));
432                }
433            };
434            config.clearErrorListeners();
435            ConfigurationUtils.enableRuntimeExceptions(config);
436            config.addProperty("test", "testValue");
437        }
438    
439        /**
440         * Tries to enable runtime exceptions for a configuration that does not
441         * inherit from EventSource. This should cause an exception.
442         */
443        @Test(expected = IllegalArgumentException.class)
444        public void testEnableRuntimeExceptionsInvalid()
445        {
446            ConfigurationUtils.enableRuntimeExceptions((Configuration) new Mock(
447                    Configuration.class).proxy());
448        }
449    
450        /**
451         * Tries to enable runtime exceptions for a null configuration. This should
452         * cause an exception.
453         */
454        @Test(expected = IllegalArgumentException.class)
455        public void testEnableRuntimeExceptionsNull()
456        {
457            ConfigurationUtils.enableRuntimeExceptions(null);
458        }
459    }