1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.configuration;
19  
20  import java.io.File;
21  import java.io.FileWriter;
22  import java.util.Collection;
23  import java.util.List;
24  
25  import junit.framework.TestCase;
26  
27  import org.xml.sax.SAXException;
28  
29  /***
30   * Test the ConfigurationFactory.
31   *
32   * @version $Id: TestConfigurationFactory.java 570916 2007-08-29 20:05:46Z oheger $
33   */
34  public class TestConfigurationFactory extends TestCase
35  {
36      /*** The Files that we test with */
37      private File digesterRules = new File("conf/digesterRules.xml");
38      private File testDigesterFile =
39              new File("conf/testDigesterConfiguration.xml");
40      private File testDigesterFileReverseOrder =
41              new File("conf/testDigesterConfigurationReverseOrder.xml");
42      private File testDigesterFileNamespaceAware =
43              new File("conf/testDigesterConfigurationNamespaceAware.xml");
44      private File testDigesterFileBasePath =
45              new File("conf/testDigesterConfigurationBasePath.xml");
46      private File testDigesterFileEnhanced =
47              new File("conf/testDigesterConfiguration2.xml");
48      private File testDigesterFileComplete =
49              new File("conf/testDigesterConfiguration3.xml");
50      private File testDigesterFileOptional =
51              new File("conf/testDigesterOptionalConfiguration.xml");
52      private File testDigesterFileOptionalEx =
53              new File("conf/testDigesterOptionalConfigurationEx.xml");
54      private File testDigesterFileSysProps =
55              new File("conf/testDigesterConfigurationSysProps.xml");
56      private File testDigesterFileInitProps =
57              new File("conf/testDigesterConfigurationWithProps.xml");
58  
59      private File testDigesterBadXML = new File("conf/testDigesterBadXML.xml");
60  
61      private String testBasePath = new File("conf").getAbsolutePath();
62  
63      private File testProperties = new File("conf/test.properties");
64      private File testAbsConfig = new File("target/testAbsConfig.xml");
65  
66      private Configuration configuration;
67      private CompositeConfiguration compositeConfiguration;
68      private ConfigurationFactory factory;
69  
70      public void setUp() throws Exception
71      {
72          System.setProperty("java.naming.factory.initial", "org.apache.commons.configuration.MockInitialContextFactory");
73          factory = new ConfigurationFactory();
74      }
75  
76      public void testJNDI() throws Exception
77      {
78          JNDIConfiguration jndiConfiguration = new JNDIConfiguration();
79          Object o = jndiConfiguration.getProperty("test.boolean");
80          assertNotNull(o);
81          assertEquals("true", o.toString());
82      }
83  
84      public void testLoadingConfiguration() throws Exception
85      {
86          factory.setConfigurationFileName(testDigesterFile.toString());
87  
88          compositeConfiguration = (CompositeConfiguration) factory.getConfiguration();
89  
90          assertEquals("Number of configurations", 4, compositeConfiguration.getNumberOfConfigurations());
91          assertEquals(PropertiesConfiguration.class, compositeConfiguration.getConfiguration(0).getClass());
92          assertEquals(XMLPropertiesConfiguration.class, compositeConfiguration.getConfiguration(1).getClass());
93          assertEquals(XMLConfiguration.class, compositeConfiguration.getConfiguration(2).getClass());
94  
95          // check the first configuration
96          PropertiesConfiguration pc = (PropertiesConfiguration) compositeConfiguration.getConfiguration(0);
97          assertNotNull("Make sure we have a fileName: " + pc.getFileName(), pc.getFileName());
98  
99          // check some properties
100         assertTrue("Make sure we have loaded our key", compositeConfiguration.getBoolean("test.boolean"));
101         assertEquals("I'm complex!", compositeConfiguration.getProperty("element2.subelement.subsubelement"));
102         assertEquals("property in the XMLPropertiesConfiguration", "value1", compositeConfiguration.getProperty("key1"));
103     }
104 
105     public void testLoadingConfigurationWithRulesXML() throws Exception
106     {
107         factory.setConfigurationFileName(testDigesterFile.toString());
108         factory.setDigesterRules(digesterRules.toURL());
109 
110         compositeConfiguration = (CompositeConfiguration) factory.getConfiguration();
111 
112         assertEquals("Number of configurations", 4, compositeConfiguration.getNumberOfConfigurations());
113         assertEquals(PropertiesConfiguration.class, compositeConfiguration.getConfiguration(0).getClass());
114         //assertEquals(XMLPropertiesConfiguration.class, compositeConfiguration.getConfiguration(1).getClass()); // doesn't work
115         assertEquals(XMLConfiguration.class, compositeConfiguration.getConfiguration(2).getClass());
116 
117         // check the first configuration
118         PropertiesConfiguration pc = (PropertiesConfiguration) compositeConfiguration.getConfiguration(0);
119         assertNotNull("Make sure we have a fileName: " + pc.getFileName(), pc.getFileName());
120 
121         // check some properties
122         assertTrue("Make sure we have loaded our key", pc.getBoolean("test.boolean"));
123         assertTrue("Make sure we have loaded our key", compositeConfiguration.getBoolean("test.boolean"));
124 
125         assertEquals("I'm complex!", compositeConfiguration.getProperty("element2.subelement.subsubelement"));
126     }
127 
128     public void testLoadingConfigurationReverseOrder() throws Exception
129     {
130         factory.setConfigurationFileName(testDigesterFileReverseOrder.toString());
131 
132         configuration = factory.getConfiguration();
133 
134         assertEquals("8", configuration.getProperty("test.short"));
135 
136         factory.setConfigurationFileName(testDigesterFile.toString());
137 
138         configuration = factory.getConfiguration();
139         assertEquals("1", configuration.getProperty("test.short"));
140     }
141 
142     public void testLoadingConfigurationNamespaceAware() throws Exception
143     {
144         factory.setConfigurationFileName(testDigesterFileNamespaceAware.toString());
145         //factory.setDigesterRules(digesterRules.toURL());
146         factory.setDigesterRuleNamespaceURI("namespace-one");
147 
148         checkCompositeConfiguration();
149     }
150 
151     public void testLoadingConfigurationBasePath() throws Exception
152     {
153         factory.setConfigurationFileName(testDigesterFileBasePath.toString());
154 
155         factory.setBasePath(testBasePath);
156 
157         //factory.setDigesterRules(digesterRules.toURL());
158         //factory.setDigesterRuleNamespaceURI("namespace-one");
159 
160         checkCompositeConfiguration();
161     }
162 
163     public void testLoadingAdditional() throws Exception
164     {
165         factory.setConfigurationFileName(testDigesterFileEnhanced.toString());
166         factory.setBasePath(null);
167         checkUnionConfig();
168     }
169 
170     public void testLoadingURL() throws Exception
171     {
172         factory.setConfigurationURL(testDigesterFileEnhanced.toURL());
173         checkUnionConfig();
174 
175         factory = new ConfigurationFactory();
176         File nonExistingFile = new File("conf/nonexisting.xml");
177         factory.setConfigurationURL(nonExistingFile.toURL());
178         try
179         {
180             factory.getConfiguration();
181             fail("Could load non existing file!");
182         }
183         catch(ConfigurationException cex)
184         {
185             //ok
186         }
187     }
188 
189     public void testThrowingConfigurationInitializationException() throws Exception
190     {
191         factory.setConfigurationFileName(testDigesterBadXML.toString());
192         try
193         {
194             factory.getConfiguration();
195             fail("Should have throw an Exception");
196         }
197         catch (ConfigurationException cle)
198         {
199             assertTrue("Unexpected cause: " + cle.getCause(),
200                     cle.getCause() instanceof SAXException);
201         }
202     }
203 
204     // Tests if properties from all sources can be loaded
205     public void testAllConfiguration() throws Exception
206     {
207         factory.setConfigurationURL(testDigesterFileComplete.toURL());
208         Configuration config = factory.getConfiguration();
209         assertFalse(config.isEmpty());
210         assertTrue(config instanceof CompositeConfiguration);
211         CompositeConfiguration cc = (CompositeConfiguration) config;
212         assertTrue(cc.getNumberOfConfigurations() > 1);
213         // Currently fails, should be 4?  Only 2?
214         //assertEquals(4, cc.getNumberOfConfigurations());
215 
216         assertNotNull(config.getProperty("tables.table(0).fields.field(2).name"));
217         assertNotNull(config.getProperty("element2.subelement.subsubelement"));
218         assertEquals("value", config.getProperty("element3"));
219         assertEquals("foo", config.getProperty("element3[@name]"));
220         assertNotNull(config.getProperty("mail.account.user"));
221 
222         // test JNDIConfiguration
223         assertNotNull(config.getProperty("test.onlyinjndi"));
224         assertTrue(config.getBoolean("test.onlyinjndi"));
225 
226         Configuration subset = config.subset("test");
227         assertNotNull(subset.getProperty("onlyinjndi"));
228         assertTrue(subset.getBoolean("onlyinjndi"));
229 
230         // test SystemConfiguration
231         assertNotNull(config.getProperty("java.version"));
232         assertEquals(System.getProperty("java.version"), config.getString("java.version"));
233     }
234 
235     // Checks if optional configurations work
236     public void testOptionalConfigurations() throws Exception
237     {
238         factory.setConfigurationURL(testDigesterFileOptional.toURL());
239         Configuration config = factory.getConfiguration();
240         assertTrue(config.getBoolean("test.boolean"));
241         assertEquals("value", config.getProperty("element"));
242 
243         factory.setConfigurationURL(testDigesterFileOptionalEx.toURL());
244         try
245         {
246             config = factory.getConfiguration();
247             fail("Unexisting properties loaded!");
248         }
249         catch(ConfigurationException cex)
250         {
251             // fine
252         }
253     }
254 
255     // Checks if a file with an absolute path can be loaded
256     public void testLoadAbsolutePath() throws Exception
257     {
258         try
259         {
260             FileWriter out = null;
261             try
262             {
263                 out = new FileWriter(testAbsConfig);
264                 out.write("<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>");
265                 out.write("<configuration>");
266                 out.write("<properties fileName=\"");
267                 out.write(testProperties.getAbsolutePath());
268                 out.write("\"/>");
269                 out.write("</configuration>");
270             }
271             finally
272             {
273                 if (out != null)
274                 {
275                     out.close();
276                 }
277             }
278 
279             factory.setConfigurationFileName(testAbsConfig.toString());
280             Configuration config = factory.getConfiguration();
281             assertTrue(config.getBoolean("configuration.loaded"));
282         }
283         finally
284         {
285             if (testAbsConfig.exists())
286             {
287                 testAbsConfig.delete();
288             }
289         }
290     }
291 
292     public void testBasePath() throws Exception
293     {
294         assertEquals(".", factory.getBasePath());
295         factory.setConfigurationFileName(testDigesterFile.getAbsolutePath());
296         // if no specific base path has been set, the base is determined
297         // from the file name
298         assertEquals(testDigesterFile.getParentFile().getAbsolutePath(),
299                 factory.getBasePath());
300 
301         String homeDir = System.getProperty("user.home");
302         factory = new ConfigurationFactory();
303         factory.setBasePath(homeDir);
304         factory.setConfigurationFileName(testDigesterFile.getAbsolutePath());
305         // if a base path was set, the file name does not play a role
306         assertEquals(homeDir, factory.getBasePath());
307 
308         factory = new ConfigurationFactory(testDigesterFile.getAbsolutePath());
309         assertEquals(testDigesterFile.getParentFile().getAbsolutePath(),
310                 factory.getBasePath());
311         factory.setBasePath(homeDir);
312         assertEquals(homeDir, factory.getBasePath());
313 
314         factory = new ConfigurationFactory();
315         factory.setConfigurationURL(testDigesterFile.toURL());
316         assertEquals(testDigesterFile.toURL().toString(), factory.getBasePath());
317     }
318 
319     // Tests if system properties can be resolved in the configuration
320     // definition
321     public void testLoadingWithSystemProperties() throws ConfigurationException
322     {
323         System.setProperty("config.file", "test.properties");
324         factory.setConfigurationFileName(testDigesterFileSysProps
325                 .getAbsolutePath());
326         Configuration config = factory.getConfiguration();
327         assertTrue("Configuration not loaded", config
328                 .getBoolean("configuration.loaded"));
329     }
330 
331     // Tests if the properties of a configuration object are correctly set
332     // before it is loaded.
333     public void testLoadInitProperties() throws ConfigurationException
334     {
335         factory.setConfigurationFileName(testDigesterFileInitProps
336                 .getAbsolutePath());
337         Configuration config = factory.getConfiguration();
338         PropertiesConfiguration c = (PropertiesConfiguration) ((CompositeConfiguration) config)
339                 .getConfiguration(0);
340         assertEquals("List delimiter was not set", ';', c.getListDelimiter());
341         List l = c.getList("test.mixed.array");
342         assertEquals("Wrong number of list elements", 2, l.size());
343         assertEquals("List delimiter was not applied", "b, c, d", l.get(1));
344     }
345 
346     private void checkUnionConfig() throws Exception
347     {
348         compositeConfiguration = (CompositeConfiguration) factory.getConfiguration();
349         assertEquals("Verify how many configs", 3, compositeConfiguration.getNumberOfConfigurations());
350 
351         // Test if union was constructed correctly
352         Object prop = compositeConfiguration.getProperty("tables.table.name");
353         assertTrue(prop instanceof Collection);
354         assertEquals(3, ((Collection) prop).size());
355         assertEquals("users", compositeConfiguration.getProperty("tables.table(0).name"));
356         assertEquals("documents", compositeConfiguration.getProperty("tables.table(1).name"));
357         assertEquals("tasks", compositeConfiguration.getProperty("tables.table(2).name"));
358 
359         prop = compositeConfiguration.getProperty("tables.table.fields.field.name");
360         assertTrue(prop instanceof Collection);
361         assertEquals(17, ((Collection) prop).size());
362 
363         assertEquals("smtp.mydomain.org", compositeConfiguration.getString("mail.host.smtp"));
364         assertEquals("pop3.mydomain.org", compositeConfiguration.getString("mail.host.pop"));
365 
366         // This was overriden
367         assertEquals("masterOfPost", compositeConfiguration.getString("mail.account.user"));
368         assertEquals("topsecret", compositeConfiguration.getString("mail.account.psswd"));
369 
370         // This was overriden, too, but not in additional section
371         assertEquals("enhanced factory", compositeConfiguration.getString("test.configuration"));
372     }
373 
374     private void checkCompositeConfiguration() throws Exception
375     {
376         compositeConfiguration = (CompositeConfiguration) factory.getConfiguration();
377 
378         assertEquals("Verify how many configs", 2, compositeConfiguration.getNumberOfConfigurations());
379         assertEquals(PropertiesConfiguration.class, compositeConfiguration.getConfiguration(0).getClass());
380 
381         PropertiesConfiguration pc = (PropertiesConfiguration) compositeConfiguration.getConfiguration(0);
382         assertNotNull("Make sure we have a fileName:" + pc.getFileName(), pc.getFileName());
383         assertTrue("Make sure we have loaded our key", pc.getBoolean("test.boolean"));
384         assertTrue("Make sure we have loaded our key", compositeConfiguration.getBoolean("test.boolean"));
385 
386         Object property = compositeConfiguration.getProperty("element2.subelement.subsubelement");
387         assertNull("Should have returned a null", property);
388     }
389 }