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