1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License")
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.commons.configuration;
18  
19  import java.io.File;
20  import java.util.ArrayList;
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.NoSuchElementException;
24  
25  import junit.framework.TestCase;
26  
27  /***
28   * Test loading multiple configurations.
29   *
30   * @version $Id: TestCompositeConfiguration.java 155408 2005-02-26 12:56:39Z dirkv $
31   */
32  public class TestCompositeConfiguration extends TestCase
33  {
34      protected PropertiesConfiguration conf1;
35      protected PropertiesConfiguration conf2;
36      protected XMLConfiguration xmlConf;
37      protected CompositeConfiguration cc;
38  
39      /***
40       * The File that we test with
41       */
42      private String testProperties = new File("conf/test.properties").getAbsolutePath();
43      private String testProperties2 = new File("conf/test2.properties").getAbsolutePath();
44      private String testPropertiesXML = new File("conf/test.xml").getAbsolutePath();
45  
46      protected void setUp() throws Exception
47      {
48          cc = new CompositeConfiguration();
49          conf1 = new PropertiesConfiguration(testProperties);
50          conf2 = new PropertiesConfiguration(testProperties2);
51          xmlConf = new XMLConfiguration(new File(testPropertiesXML));
52  
53          cc.setThrowExceptionOnMissing(true);
54      }
55  
56      public void testThrowExceptionOnMissing()
57      {
58          assertTrue("Throw Exception Property is not set!", cc.isThrowExceptionOnMissing());
59      }
60  
61      public void testAddRemoveConfigurations() throws Exception
62      {
63          cc.addConfiguration(conf1);
64          assertEquals(2, cc.getNumberOfConfigurations());
65          cc.addConfiguration(conf1);
66          assertEquals(2, cc.getNumberOfConfigurations());
67          cc.addConfiguration(conf2);
68          assertEquals(3, cc.getNumberOfConfigurations());
69          cc.removeConfiguration(conf1);
70          assertEquals(2, cc.getNumberOfConfigurations());
71          cc.clear();
72          assertEquals(1, cc.getNumberOfConfigurations());
73      }
74  
75      public void testGetPropertyWIncludes() throws Exception
76      {
77          cc.addConfiguration(conf1);
78          cc.addConfiguration(conf2);
79          List l = cc.getList("packages");
80          assertTrue(l.contains("packagea"));       
81      }
82  
83      public void testGetProperty() throws Exception
84      {
85          cc.addConfiguration(conf1);
86          cc.addConfiguration(conf2);
87          assertEquals("Make sure we get the property from conf1 first", "test.properties", cc.getString("propertyInOrder"));
88          cc.clear();
89  
90          cc.addConfiguration(conf2);
91          cc.addConfiguration(conf1);
92          assertEquals("Make sure we get the property from conf2 first", "test2.properties", cc.getString("propertyInOrder"));
93      }
94  
95      public void testCantRemoveMemoryConfig() throws Exception
96      {
97          cc.clear();
98          assertEquals(1, cc.getNumberOfConfigurations());
99  
100         Configuration internal = cc.getConfiguration(0);
101         cc.removeConfiguration(internal);
102 
103         assertEquals(1, cc.getNumberOfConfigurations());
104     }
105 
106     public void testGetPropertyMissing() throws Exception
107     {
108         cc.addConfiguration(conf1);
109         cc.addConfiguration(conf2);
110         try
111         {
112             assertNull(cc.getString("bogus.property"));
113             fail("Should have thrown a NoSuchElementException");
114         }
115         catch (NoSuchElementException nsee)
116         {
117             assertTrue(nsee.getMessage().indexOf("bogus.property") > -1);
118         }
119 
120         assertTrue("Should be false", !cc.getBoolean("test.missing.boolean", false));
121         assertTrue("Should be true", cc.getBoolean("test.missing.boolean.true", true));
122     }
123 
124     /***
125      * Tests <code>List</code> parsing.
126      */
127     public void testMultipleTypesOfConfigs() throws Exception
128     {
129         cc.addConfiguration(conf1);
130         cc.addConfiguration(xmlConf);
131         assertEquals("Make sure we get the property from conf1 first", 1, cc.getInt("test.short"));
132         cc.clear();
133 
134         cc.addConfiguration(xmlConf);
135         cc.addConfiguration(conf1);
136         assertEquals("Make sure we get the property from xml", 8, cc.getInt("test.short"));
137     }
138 
139     /***
140      * Tests <code>List</code> parsing.
141      */
142     public void testPropertyExistsInOnlyOneConfig() throws Exception
143     {
144         cc.addConfiguration(conf1);
145         cc.addConfiguration(xmlConf);
146         assertEquals("value", cc.getString("element"));
147     }
148 
149     /***
150      * Tests getting a default when the key doesn't exist
151      */
152     public void testDefaultValueWhenKeyMissing() throws Exception
153     {
154         cc.addConfiguration(conf1);
155         cc.addConfiguration(xmlConf);
156         assertEquals("default", cc.getString("bogus", "default"));
157         assertTrue(1.4 == cc.getDouble("bogus", 1.4));
158         assertTrue(1.4 == cc.getDouble("bogus", 1.4));
159     }
160 
161     /***
162      * Tests <code>List</code> parsing.
163      */
164     public void testGettingConfiguration() throws Exception
165     {
166         cc.addConfiguration(conf1);
167         cc.addConfiguration(xmlConf);
168         assertEquals(PropertiesConfiguration.class, cc.getConfiguration(0).getClass());
169         assertEquals(XMLConfiguration.class, cc.getConfiguration(1).getClass());
170     }
171 
172     /***
173      * Tests setting values.  These are set in memory mode only!
174      */
175     public void testClearingProperty() throws Exception
176     {
177         cc.addConfiguration(conf1);
178         cc.addConfiguration(xmlConf);
179         cc.clearProperty("test.short");
180         assertTrue("Make sure test.short is gone!", !cc.containsKey("test.short"));
181     }
182 
183     /***
184      * Tests adding values.  Make sure they _DON'T_ override any other properties but add to the
185      * existing properties  and keep sequence
186      */
187     public void testAddingProperty() throws Exception
188     {
189         cc.addConfiguration(conf1);
190         cc.addConfiguration(xmlConf);
191 
192         String[] values = cc.getStringArray("test.short");
193 
194         assertEquals("Number of values before add is wrong!", 1, values.length);
195         assertEquals("First Value before add is wrong", "1", values[0]);
196 
197         cc.addProperty("test.short", "88");
198 
199         values = cc.getStringArray("test.short");
200 
201         assertEquals("Number of values is wrong!", 2, values.length);
202         assertEquals("First Value is wrong", "1", values[0]);
203         assertEquals("Third Value is wrong", "88", values[1]);
204     }
205 
206     /***
207      * Tests setting values.  These are set in memory mode only!
208      */
209     public void testSettingMissingProperty() throws Exception
210     {
211         cc.addConfiguration(conf1);
212         cc.addConfiguration(xmlConf);
213         cc.setProperty("my.new.property", "supernew");
214         assertEquals("supernew", cc.getString("my.new.property"));
215     }
216 
217     /***
218      * Tests retrieving subsets of configurations
219      */
220     public void testGettingSubset() throws Exception
221     {
222         cc.addConfiguration(conf1);
223         cc.addConfiguration(xmlConf);
224 
225         Configuration subset = null;
226         subset = cc.subset("test");
227         assertNotNull(subset);
228         assertFalse("Shouldn't be empty", subset.isEmpty());
229         assertEquals("Make sure the initial loaded configs subset overrides any later add configs subset", "1", subset.getString("short"));
230 
231         cc.setProperty("test.short", "43");
232         subset = cc.subset("test");
233         assertEquals("Make sure the initial loaded configs subset overrides any later add configs subset", "43", subset.getString("short"));
234     }
235 
236     /***
237      * Tests subsets and still can resolve elements
238      */
239     public void testSubsetCanResolve() throws Exception
240     {
241         cc = new CompositeConfiguration();
242         final BaseConfiguration config = new BaseConfiguration();
243         config.addProperty("subset.tempfile", "${java.io.tmpdir}/file.tmp");
244         cc.addConfiguration(config);
245         cc.addConfiguration(ConfigurationConverter.getConfiguration(System.getProperties()));
246 
247         Configuration subset = cc.subset("subset");
248         assertEquals(System.getProperty("java.io.tmpdir") + "/file.tmp", subset.getString("tempfile"));
249     }
250 
251     /***
252      * Tests <code>List</code> parsing.
253      */
254     public void testList() throws Exception
255     {
256         cc.addConfiguration(conf1);
257         cc.addConfiguration(xmlConf);
258 
259         List packages = cc.getList("packages");
260         // we should get 3 packages here
261         assertEquals(3, packages.size());
262 
263         List defaultList = new ArrayList();
264         defaultList.add("1");
265         defaultList.add("2");
266 
267         packages = cc.getList("packages.which.dont.exist", defaultList);
268         // we should get 2 packages here
269         assertEquals(2, packages.size());
270 
271     }
272 
273     /***
274      * Tests <code>String</code> array parsing.
275      */
276     public void testStringArray() throws Exception
277     {
278         cc.addConfiguration(conf1);
279         cc.addConfiguration(xmlConf);
280 
281         String[] packages = cc.getStringArray("packages");
282         // we should get 3 packages here
283         assertEquals(3, packages.length);
284 
285         packages = cc.getStringArray("packages.which.dont.exist");
286         // we should get 0 packages here
287         assertEquals(0, packages.length);
288     }
289 
290     public void testGetList()
291     {
292         Configuration conf1 = new BaseConfiguration();
293         conf1.addProperty("array", "value1");
294         conf1.addProperty("array", "value2");
295 
296         Configuration conf2 = new BaseConfiguration();
297         conf2.addProperty("array", "value3");
298         conf2.addProperty("array", "value4");
299 
300         cc.addConfiguration(conf1);
301         cc.addConfiguration(conf2);
302 
303         // check the composite 'array' property
304         List list = cc.getList("array");
305         assertNotNull("null list", list);
306         assertEquals("list size", 2, list.size());
307         assertTrue("'value1' not found in the list", list.contains("value1"));
308         assertTrue("'value2' not found in the list", list.contains("value2"));
309 
310         // add an element to the list in the composite configuration
311         cc.addProperty("array", "value5");
312 
313         // test the new list
314         list = cc.getList("array");
315         assertNotNull("null list", list);
316         assertEquals("list size", 3, list.size());
317         assertTrue("'value1' not found in the list", list.contains("value1"));
318         assertTrue("'value2' not found in the list", list.contains("value2"));
319         assertTrue("'value5' not found in the list", list.contains("value5"));
320     }
321 
322     /***
323      * Tests <code>getKeys</code> preserves the order
324      */
325     public void testGetKeysPreservesOrder() throws Exception
326     {
327         cc.addConfiguration(conf1);
328         List orderedList = new ArrayList();
329         for (Iterator keys = conf1.getKeys(); keys.hasNext();)
330         {
331             orderedList.add(keys.next());
332         }
333         List iteratedList = new ArrayList();
334         for (Iterator keys = cc.getKeys(); keys.hasNext();)
335         {
336             iteratedList.add(keys.next());
337         }
338         assertEquals(orderedList.size(), iteratedList.size());
339         for (int i = 0; i < orderedList.size(); i++)
340         {
341             assertEquals(orderedList.get(i), iteratedList.get(i));
342         }
343     }
344 
345     /***
346      * Tests <code>getKeys(String key)</code> preserves the order
347      */
348     public void testGetKeys2PreservesOrder() throws Exception
349     {
350         cc.addConfiguration(conf1);
351         List orderedList = new ArrayList();
352         for (Iterator keys = conf1.getKeys("test"); keys.hasNext();)
353         {
354             orderedList.add(keys.next());
355         }
356         List iteratedList = new ArrayList();
357         for (Iterator keys = cc.getKeys("test"); keys.hasNext();)
358         {
359             iteratedList.add(keys.next());
360         }
361         assertEquals(orderedList.size(), iteratedList.size());
362         for (int i = 0; i < orderedList.size(); i++)
363         {
364             assertEquals(orderedList.get(i), iteratedList.get(i));
365         }
366     }
367 
368     public void testGetStringWithDefaults()
369     {
370         BaseConfiguration defaults = new BaseConfiguration();
371         defaults.addProperty("default", "default string");
372 
373         CompositeConfiguration c = new CompositeConfiguration(defaults);
374         c.setThrowExceptionOnMissing(cc.isThrowExceptionOnMissing());
375         c.addProperty("string", "test string");
376 
377         assertEquals("test string", c.getString("string"));
378         try
379         {
380             c.getString("XXX");
381             fail("Should throw NoSuchElementException exception");
382         }
383         catch (NoSuchElementException e)
384         {
385             //ok
386         }
387         catch (Exception e)
388         {
389             fail("Should throw NoSuchElementException exception, not " + e);
390         }
391 
392         //test defaults
393         assertEquals("test string", c.getString("string", "some default value"));
394         assertEquals("default string", c.getString("default"));
395         assertEquals("default string", c.getString("default", "some default value"));
396         assertEquals("some default value", c.getString("XXX", "some default value"));
397     }
398 
399     public void testCheckingInMemoryConfiguration() throws Exception
400     {
401         String TEST_KEY = "testKey";
402         Configuration defaults = new PropertiesConfiguration();
403         defaults.setProperty(TEST_KEY, "testValue");
404         Configuration testConfiguration = new CompositeConfiguration(defaults);
405         assertTrue(testConfiguration.containsKey(TEST_KEY));
406         assertFalse(testConfiguration.isEmpty());
407         boolean foundTestKey = false;
408         Iterator i = testConfiguration.getKeys();
409         //assertTrue(i instanceof IteratorChain);
410         //IteratorChain ic = (IteratorChain)i;
411         //assertEquals(2,i.size());
412         for (; i.hasNext();)
413         {
414             String key = (String) i.next();
415             if (key.equals(TEST_KEY))
416             {
417                 foundTestKey = true;
418             }
419         }
420         assertTrue(foundTestKey);
421         testConfiguration.clearProperty(TEST_KEY);
422         assertFalse(testConfiguration.containsKey(TEST_KEY));
423     }
424 
425     public void testStringArrayInterpolation()
426     {
427         CompositeConfiguration config = new CompositeConfiguration();
428         config.addProperty("base", "foo");
429         config.addProperty("list", "${base}.bar1");
430         config.addProperty("list", "${base}.bar2");
431         config.addProperty("list", "${base}.bar3");
432 
433         String[] array = config.getStringArray("list");
434         assertEquals("size", 3, array.length);
435         assertEquals("1st element", "foo.bar1", array[0]);
436         assertEquals("2nd element", "foo.bar2", array[1]);
437         assertEquals("3rd element", "foo.bar3", array[2]);
438     }
439 }