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.net.URL;
21  import java.util.Properties;
22  import java.io.File;
23  import java.io.FileInputStream;
24  import java.io.FileOutputStream;
25  import java.io.FileWriter;
26  import java.io.IOException;
27  import java.io.PrintWriter;
28  
29  import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
30  
31  import junit.framework.TestCase;
32  
33  /***
34   * @author Emmanuel Bourg
35   * @version $Revision: 439648 $, $Date: 2006-09-02 22:42:10 +0200 (Sa, 02 Sep 2006) $
36   */
37  public class TestFileConfiguration extends TestCase
38  {
39      private static final File TARGET_DIR = new File("target");
40  
41      private static final String RESOURCE_NAME = "config/deep/deeptest.properties";
42  
43      public void testSetURL() throws Exception
44      {
45          // http URL
46          FileConfiguration config = new PropertiesConfiguration();
47          config.setURL(new URL("http://jakarta.apache.org/commons/configuration/index.html"));
48  
49          assertEquals("base path", "http://jakarta.apache.org/commons/configuration/", config
50                  .getBasePath());
51          assertEquals("file name", "index.html", config.getFileName());
52  
53          // file URL
54          config.setURL(new URL("file:/temp/test.properties"));
55          assertEquals("base path", "file:/temp/", config.getBasePath());
56          assertEquals("file name", "test.properties", config.getFileName());
57      }
58  
59      public void testSetURLWithParams() throws Exception
60      {
61          FileConfiguration config = new PropertiesConfiguration();
62          URL url = new URL(
63                  "http://issues.apache.org/bugzilla/show_bug.cgi?id=37886");
64          config.setURL(url);
65          assertEquals("Base path incorrect",
66                  "http://issues.apache.org/bugzilla/", config.getBasePath());
67          assertEquals("File name incorrect", "show_bug.cgi", config
68                  .getFileName());
69          assertEquals("URL was not correctly stored", url, config.getURL());
70      }
71  
72      public void testLocations() throws Exception
73      {
74          PropertiesConfiguration config = new PropertiesConfiguration();
75  
76          File directory = new File("conf");
77          File file = new File(directory, "test.properties");
78          config.setFile(file);
79          assertEquals(directory.getAbsolutePath(), config.getBasePath());
80          assertEquals("test.properties", config.getFileName());
81          assertEquals(file.getAbsolutePath(), config.getPath());
82  
83          config.setPath("conf" + File.separator + "test.properties");
84          assertEquals("test.properties", config.getFileName());
85          assertEquals(directory.getAbsolutePath(), config.getBasePath());
86          assertEquals(file.getAbsolutePath(), config.getPath());
87          assertEquals(file.toURL(), config.getURL());
88  
89          config.setBasePath(null);
90          config.setFileName("test.properties");
91          assertNull(config.getBasePath());
92          assertEquals("test.properties", config.getFileName());
93      }
94  
95      public void testCreateFile1() throws Exception
96      {
97          File file = new File("target/test-resources/foo/bar/test.properties");
98          if (file.exists())
99          {
100             file.delete();
101             file.getParentFile().delete();
102         }
103 
104         assertFalse("The file should not exist", file.exists());
105 
106         FileConfiguration config = new PropertiesConfiguration(file);
107         config.save();
108 
109         assertTrue("The file doesn't exist", file.exists());
110     }
111 
112     public void testCreateFile2() throws Exception
113     {
114         File file = new File("target/test-resources/foo/bar/test.properties");
115         if (file.exists())
116         {
117             file.delete();
118             file.getParentFile().delete();
119         }
120 
121         assertFalse("The file should not exist", file.exists());
122 
123         FileConfiguration config = new PropertiesConfiguration();
124         config.setFile(file);
125         config.save();
126 
127         assertTrue("The file doesn't exist", file.exists());
128     }
129 
130     public void testCreateFile3() throws Exception
131     {
132         File file = new File("target/test-resources/foo/bar/test.properties");
133         if (file.exists())
134         {
135             file.delete();
136             file.getParentFile().delete();
137         }
138 
139         assertFalse("The file should not exist", file.exists());
140 
141         FileConfiguration config = new PropertiesConfiguration();
142         config.save(file);
143 
144         assertTrue("The file doesn't exist", file.exists());
145     }
146 
147     /***
148      * Tests collaboration with ConfigurationFactory: Is the base path set on
149      * loading is valid in file based configurations?
150      *
151      * @throws Exception if an error occurs
152      */
153     public void testWithConfigurationFactory() throws Exception
154     {
155         File dir = new File("conf");
156         File file = new File(dir, "testFileConfiguration.properties");
157 
158         if (file.exists())
159         {
160             assertTrue("File cannot be deleted", file.delete());
161         }
162 
163         try
164         {
165             ConfigurationFactory factory = new ConfigurationFactory();
166             factory.setConfigurationURL(new File(dir, "testDigesterConfiguration2.xml").toURL());
167             CompositeConfiguration cc = (CompositeConfiguration) factory.getConfiguration();
168             PropertiesConfiguration config = null;
169             for (int i = 0; config == null; i++)
170             {
171                 if (cc.getConfiguration(i) instanceof PropertiesConfiguration)
172                 {
173                     config = (PropertiesConfiguration) cc.getConfiguration(i);
174                 }
175             }
176 
177             config.setProperty("test", "yes");
178             config.save(file.getName());
179             assertTrue(file.exists());
180             config = new PropertiesConfiguration();
181             config.setFile(file);
182             config.load();
183 
184             assertEquals("yes", config.getProperty("test"));
185             assertEquals("masterOfPost", config.getProperty("mail.account.user"));
186         }
187         finally
188         {
189             if (file.exists())
190             {
191                 assertTrue("File could not be deleted", file.delete());
192             }
193         }
194     }
195 
196     /***
197      * Tests if invalid URLs cause an exception.
198      */
199     public void testSaveInvalidURL() throws Exception
200     {
201         FileConfiguration config = new PropertiesConfiguration();
202         try
203         {
204             config.save(new URL("http://jakarta.apache.org"));
205             fail("Should throw a ConfigurationException!");
206         }
207         catch (ConfigurationException cex)
208         {
209             //fine
210         }
211 
212         try
213         {
214             config.save("http://www.apache.org");
215             fail("Should throw a ConfigurationException!");
216         }
217         catch (ConfigurationException cex)
218         {
219             //fine
220         }
221     }
222 
223     /***
224      * Tests if the URL used by the load() method is also used by save().
225      */
226     public void testFileOverwrite() throws Exception
227     {
228         FileOutputStream out = null;
229         FileInputStream in = null;
230         File tempFile = null;
231         try
232         {
233             String path = System.getProperties().getProperty("user.home");
234             File homeDir = new File(path);
235             tempFile = File.createTempFile("CONF", null, homeDir);
236             String fileName = tempFile.getName();
237             Properties props = new Properties();
238             props.setProperty("1", "one");
239             out = new FileOutputStream(tempFile);
240             props.store(out, "TestFileOverwrite");
241             out.close();
242             out = null;
243             FileConfiguration config = new PropertiesConfiguration(fileName);
244             config.load();
245             String value = config.getString("1");
246             assertTrue("one".equals(value));
247             config.setProperty("1", "two");
248             config.save();
249             props = new Properties();
250             in = new FileInputStream(tempFile);
251             props.load(in);
252             String value2 = props.getProperty("1");
253             assertTrue("two".equals(value2));
254         }
255         finally
256         {
257             if (out != null)
258             {
259                 try
260                 {
261                     out.close();
262                 }
263                 catch (IOException ioex)
264                 {
265                     ioex.printStackTrace();
266                 }
267             }
268             if (in != null)
269             {
270                 try
271                 {
272                     in.close();
273                 }
274                 catch (IOException ioex)
275                 {
276                     ioex.printStackTrace();
277                 }
278             }
279             if (tempFile.exists())
280             {
281                 assertTrue(tempFile.delete());
282             }
283         }
284     }
285 
286     /***
287      * Tests setting a file changed reloading strategy together with the auto
288      * save feature.
289      */
290     public void testReloadingWithAutoSave() throws Exception
291     {
292         File configFile = new File(TARGET_DIR, "test.properties");
293         PrintWriter out = null;
294 
295         try
296         {
297             out = new PrintWriter(new FileWriter(configFile));
298             out.println("a = one");
299             out.close();
300             out = null;
301 
302             PropertiesConfiguration config = new PropertiesConfiguration(
303                     configFile);
304             config.setReloadingStrategy(new FileChangedReloadingStrategy());
305             config.setAutoSave(true);
306 
307             assertEquals("one", config.getProperty("a"));
308             config.setProperty("b", "two");
309             assertEquals("one", config.getProperty("a"));
310         }
311         finally
312         {
313             if (out != null)
314             {
315                 out.close();
316             }
317             if (configFile.exists())
318             {
319                 assertTrue(configFile.delete());
320             }
321         }
322     }
323 
324     /***
325      * Tests loading and saving a configuration file with a complicated path
326      * name including spaces. (related to issue 35210)
327      */
328     public void testPathWithSpaces() throws Exception
329     {
330         File path = new File(TARGET_DIR, "path with spaces");
331         File confFile = new File(path, "config-test.properties");
332         PrintWriter out = null;
333 
334         try
335         {
336             if (!path.exists())
337             {
338                 assertTrue(path.mkdir());
339             }
340             out = new PrintWriter(new FileWriter(confFile));
341             out.println("saved = false");
342             out.close();
343             out = null;
344 
345             URL url = new URL(TARGET_DIR.toURL()
346                     + "path%20with%20spaces/config-test.properties");
347             PropertiesConfiguration config = new PropertiesConfiguration(url);
348             config.load();
349             assertFalse(config.getBoolean("saved"));
350 
351             config.setProperty("saved", Boolean.TRUE);
352             config.save();
353             config = new PropertiesConfiguration();
354             config.setFile(confFile);
355             config.load();
356             assertTrue(config.getBoolean("saved"));
357         }
358         finally
359         {
360             if (out != null)
361             {
362                 out.close();
363             }
364             if (confFile.exists())
365             {
366                 assertTrue(confFile.delete());
367             }
368             if (path.exists())
369             {
370                 assertTrue(path.delete());
371             }
372         }
373     }
374 
375     /***
376      * Tests the getFile() method.
377      */
378     public void testGetFile() throws ConfigurationException
379     {
380         FileConfiguration config = new PropertiesConfiguration();
381         assertNull(config.getFile());
382         File file = new File("conf/test.properties").getAbsoluteFile();
383         config.setFile(file);
384         assertEquals(file, config.getFile());
385         config.load();
386         assertEquals(file, config.getFile());
387     }
388 
389     /***
390      * Tests to invoke save() without explicitely setting a file name. This
391      * will cause an exception.
392      */
393     public void testSaveWithoutFileName() throws Exception
394     {
395         FileConfiguration config = new PropertiesConfiguration();
396         File file = new File("conf/test.properties");
397         config.load(file);
398         try
399         {
400             config.save();
401             fail("Could save config without setting a file name!");
402         }
403         catch(ConfigurationException cex)
404         {
405             //ok
406         }
407 
408         config = new PropertiesConfiguration();
409         config.load("conf/test.properties");
410         try
411         {
412             config.save();
413             fail("Could save config without setting a file name!");
414         }
415         catch(ConfigurationException cex)
416         {
417             //ok
418         }
419 
420         config = new PropertiesConfiguration();
421         config.load(file.toURL());
422         try
423         {
424             config.save();
425             fail("Could save config without setting a file name!");
426         }
427         catch(ConfigurationException cex)
428         {
429             //ok
430         }
431     }
432 
433     /***
434      * Checks that loading a directory instead of a file throws an exception.
435      */
436     public void testLoadDirectory()
437     {
438         PropertiesConfiguration config = new PropertiesConfiguration();
439 
440         try
441         {
442             config.load("target");
443             fail("Could load config from a directory!");
444         }
445         catch (ConfigurationException e)
446         {
447             // ok
448         }
449 
450         try
451         {
452             config.load(new File("target"));
453             fail("Could load config from a directory!");
454         }
455         catch (ConfigurationException e)
456         {
457             // ok
458         }
459 
460         try
461         {
462             new PropertiesConfiguration("target");
463             fail("Could load config from a directory!");
464         }
465         catch (ConfigurationException e)
466         {
467             // ok
468         }
469 
470         try
471         {
472             new PropertiesConfiguration(new File("target"));
473             fail("Could load config from a directory!");
474         }
475         catch (ConfigurationException e)
476         {
477             // ok
478         }
479     }
480 
481     /***
482      * Tests whether the constructor behaves the same as setFileName() when the
483      * configuration source is in the classpath.
484      */
485     public void testInitFromClassPath() throws ConfigurationException
486     {
487         PropertiesConfiguration config1 = new PropertiesConfiguration();
488         config1.setFileName(RESOURCE_NAME);
489         config1.load();
490         PropertiesConfiguration config2 = new PropertiesConfiguration(
491                 RESOURCE_NAME);
492         compare(config1, config2);
493     }
494 
495     /***
496      * Tests the loading of configuration file in a Combined configuration 
497      * when the configuration source is in the classpath.
498      */
499     public void testLoadFromClassPath() throws ConfigurationException
500     {
501         DefaultConfigurationBuilder cf = 
502             new DefaultConfigurationBuilder("conf/config/deep/testFileFromClasspath.xml");
503         CombinedConfiguration config = cf.getConfiguration(true);
504         Configuration config1 = config.getConfiguration("propConf");
505         Configuration config2 = config.getConfiguration("propConfDeep");
506         compare(config1, config2);
507     }
508 
509     /***
510      * Tests cloning a file based configuration.
511      */
512     public void testClone() throws ConfigurationException
513     {
514         PropertiesConfiguration config = new PropertiesConfiguration(
515                 RESOURCE_NAME);
516         PropertiesConfiguration copy = (PropertiesConfiguration) config.clone();
517         compare(config, copy);
518         assertNull("URL was not reset", copy.getURL());
519         assertNull("Base path was not reset", copy.getBasePath());
520         assertNull("File name was not reset", copy.getFileName());
521         assertNotSame("Reloading strategy was not reset", config
522                 .getReloadingStrategy(), copy.getReloadingStrategy());
523     }
524 
525     /***
526      * Helper method for comparing the content of two configuration objects.
527      *
528      * @param config1 the first configuration
529      * @param config2 the second configuration
530      */
531     private void compare(Configuration config1, Configuration config2)
532     {
533         StrictConfigurationComparator cc = new StrictConfigurationComparator();
534         assertTrue("Configurations are different", cc.compare(config1, config2));
535     }
536 }