    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 }