001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.configuration.reloading;
019    
020    import static org.junit.Assert.assertEquals;
021    import static org.junit.Assert.assertFalse;
022    import static org.junit.Assert.assertNotNull;
023    import static org.junit.Assert.assertNull;
024    import static org.junit.Assert.assertTrue;
025    
026    import java.io.ByteArrayOutputStream;
027    import java.io.File;
028    import java.io.FileWriter;
029    import java.net.URL;
030    
031    import org.apache.commons.configuration.ConfigurationException;
032    import org.apache.commons.configuration.PropertiesConfiguration;
033    import org.apache.commons.configuration.XMLConfiguration;
034    import org.apache.log4j.Appender;
035    import org.apache.log4j.Layout;
036    import org.apache.log4j.Level;
037    import org.apache.log4j.Logger;
038    import org.apache.log4j.PatternLayout;
039    import org.apache.log4j.WriterAppender;
040    import org.junit.Test;
041    
042    /**
043     * Test case for the ReloadableConfiguration class.
044     *
045     * @author Emmanuel Bourg
046     * @version $Id: TestFileChangedReloadingStrategy.java 1225906 2011-12-30 20:01:37Z oheger $
047     */
048    public class TestFileChangedReloadingStrategy
049    {
050        /** Constant for the name of a test properties file.*/
051        private static final String TEST_FILE = "test.properties";
052    
053        @Test
054        public void testAutomaticReloading() throws Exception
055        {
056            // create a new configuration
057            File file = new File("target/testReload.properties");
058    
059            if (file.exists())
060            {
061                file.delete();
062            }
063    
064            // create the configuration file
065            FileWriter out = new FileWriter(file);
066            out.write("string=value1");
067            out.flush();
068            out.close();
069    
070            // load the configuration
071            PropertiesConfiguration config = new PropertiesConfiguration("target/testReload.properties");
072            FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();
073            strategy.setRefreshDelay(500);
074            config.setReloadingStrategy(strategy);
075            assertEquals("Initial value", "value1", config.getString("string"));
076    
077            Thread.sleep(2000);
078    
079            // change the file
080            out = new FileWriter(file);
081            out.write("string=value2");
082            out.flush();
083            out.close();
084    
085            // test the automatic reloading
086            assertEquals("Modified value with enabled reloading", "value2", config.getString("string"));
087        }
088    
089        @Test
090        public void testNewFileReloading() throws Exception
091        {
092            // create a new configuration
093            File file = new File("target/testReload.properties");
094    
095            if (file.exists())
096            {
097                file.delete();
098            }
099    
100            PropertiesConfiguration config = new PropertiesConfiguration();
101            config.setFile(file);
102            FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();
103            strategy.setRefreshDelay(500);
104            config.setReloadingStrategy(strategy);
105    
106            assertNull("Initial value", config.getString("string"));
107    
108            // change the file
109            FileWriter out = new FileWriter(file);
110            out.write("string=value1");
111            out.flush();
112            out.close();
113    
114            Thread.sleep(2000);
115    
116            // test the automatic reloading
117            assertEquals("Modified value with enabled reloading", "value1", config.getString("string"));
118        }
119    
120        @Test
121        public void testGetRefreshDelay()
122        {
123            FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();
124            strategy.setRefreshDelay(500);
125            assertEquals("refresh delay", 500, strategy.getRefreshDelay());
126        }
127    
128        /**
129         * Tests if a file from the classpath can be monitored.
130         */
131        @Test
132        public void testFromClassPath() throws Exception
133        {
134            PropertiesConfiguration config = new PropertiesConfiguration();
135            config.setFileName(TEST_FILE);
136            config.load();
137            assertTrue(config.getBoolean("configuration.loaded"));
138            FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();
139            config.setReloadingStrategy(strategy);
140            assertEquals(config.getURL().toExternalForm(), strategy.getFile().toURI().toURL().toExternalForm());
141        }
142    
143        /**
144         * Tests to watch a configuration file in a jar. In this case the jar file
145         * itself should be monitored.
146         */
147        @Test
148        public void testFromJar() throws Exception
149        {
150            XMLConfiguration config = new XMLConfiguration();
151            // use some jar: URL
152            config.setURL(new URL("jar:" + new File("conf/resources.jar").getAbsoluteFile().toURI().toURL() + "!/test-jar.xml"));
153            FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();
154            config.setReloadingStrategy(strategy);
155            File file = strategy.getFile();
156            assertNotNull("Strategy's file is null", file);
157            assertEquals("Strategy does not monitor the jar file", "resources.jar", file.getName());
158        }
159    
160        /**
161         * Tests calling reloadingRequired() multiple times before a reload actually
162         * happens. This test is related to CONFIGURATION-302.
163         */
164        @Test
165        public void testReloadingRequiredMultipleTimes()
166                throws ConfigurationException
167        {
168            FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy()
169            {
170                @Override
171                protected boolean hasChanged()
172                {
173                    // signal always a change
174                    return true;
175                }
176            };
177            strategy.setRefreshDelay(100000);
178            PropertiesConfiguration config = new PropertiesConfiguration(TEST_FILE);
179            config.setReloadingStrategy(strategy);
180            assertTrue("Reloading not required", strategy.reloadingRequired());
181            assertTrue("Reloading no more required", strategy.reloadingRequired());
182            strategy.reloadingPerformed();
183            assertFalse("Reloading still required", strategy.reloadingRequired());
184        }
185    
186        @Test
187        public void testFileDeletion() throws Exception
188        {
189            Logger logger = Logger.getLogger(FileChangedReloadingStrategy.class.getName());
190            Layout layout = new PatternLayout("%p - %m%n");
191            ByteArrayOutputStream os = new ByteArrayOutputStream();
192            Appender appender = new WriterAppender(layout, os);
193            logger.addAppender(appender);
194            logger.setLevel(Level.WARN);
195            logger.setAdditivity(false);
196            // create a new configuration
197            File file = new File("target/testReload.properties");
198    
199            if (file.exists())
200            {
201                file.delete();
202            }
203    
204            // create the configuration file
205            FileWriter out = new FileWriter(file);
206            out.write("string=value1");
207            out.flush();
208            out.close();
209    
210            // load the configuration
211            PropertiesConfiguration config = new PropertiesConfiguration("target/testReload.properties");
212            FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();
213            strategy.setRefreshDelay(500);
214            config.setReloadingStrategy(strategy);
215            assertEquals("Initial value", "value1", config.getString("string"));
216    
217            Thread.sleep(2000);
218    
219            // Delete the file.
220            file.delete();
221            //Old value should still be returned.
222            assertEquals("Initial value", "value1", config.getString("string"));
223            logger.removeAppender(appender);
224            String str = os.toString();
225            //System.out.println(str);
226            assertTrue("No error was logged", str != null && str.length() > 0);
227        }
228    }