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