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;
019    
020    import static org.junit.Assert.assertNotNull;
021    import static org.junit.Assert.assertNull;
022    import static org.junit.Assert.assertTrue;
023    import static org.junit.Assert.fail;
024    
025    import java.io.File;
026    import java.io.FileReader;
027    import java.io.FileWriter;
028    import java.io.IOException;
029    import java.io.Reader;
030    import java.io.Writer;
031    
032    import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
033    import org.junit.Test;
034    import org.xml.sax.SAXParseException;
035    
036    /**
037     * Unit test for simple MultiConfigurationTest.
038     *
039     * @version $Id: TestMultiFileHierarchicalConfiguration.java 1224811 2011-12-26 21:04:25Z oheger $
040     */
041    public class TestMultiFileHierarchicalConfiguration
042    {
043        private static String PATTERN1 = "target/test-classes/testMultiConfiguration_${sys:Id}.xml";
044    
045        private static final File MULTI_TENENT_FILE = new File(
046                "conf/testMultiTenentConfigurationBuilder2.xml");
047    
048        private static final File MULTI_TENENT_FILE2 = new File(
049                "target/test-classes/testMultiTenentConfigurationBuilder2.xml");
050    
051        private static final File MULTI_RELOAD_FILE = new File(
052                "conf/testMultiTenentConfigurationBuilder3.xml");
053    
054        /**
055         * Rigourous Test :-)
056         */
057        @Test
058        public void testMultiConfiguration()
059        {
060            //set up a reloading strategy
061            FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();
062            strategy.setRefreshDelay(10000);
063    
064            MultiFileHierarchicalConfiguration config = new MultiFileHierarchicalConfiguration(PATTERN1);
065            config.setReloadingStrategy(strategy);
066    
067            System.setProperty("Id", "1001");
068            assertTrue(config.getInt("rowsPerPage") == 15);
069    
070            System.setProperty("Id", "1002");
071            assertTrue(config.getInt("rowsPerPage") == 25);
072    
073            System.setProperty("Id", "1003");
074            assertTrue(config.getInt("rowsPerPage") == 35);
075        }
076    
077        @Test
078        public void testSchemaValidationError() throws Exception
079        {
080            System.getProperties().remove("Id");
081            DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
082            factory.setFile(MULTI_TENENT_FILE);
083            CombinedConfiguration config = factory.getConfiguration(true);
084            try
085            {
086                System.setProperty("Id", "2001");
087                config.getInt("rowsPerPage");
088                fail("No exception thrown");
089            }
090            catch (Exception ex)
091            {
092                Throwable cause = ex.getCause();
093                while (cause != null && !(cause instanceof SAXParseException))
094                {
095                    cause = cause.getCause();
096                }
097                assertTrue("SAXParseException was not thrown", cause instanceof SAXParseException);
098            }
099        }
100    
101        @Test
102        public void testSchemaValidation() throws Exception
103        {
104            System.getProperties().remove("Id");
105            DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
106            factory.setFile(MULTI_TENENT_FILE);
107            CombinedConfiguration config = factory.getConfiguration(true);
108            System.setProperty("Id", "2002");
109            int rows = config.getInt("rowsPerPage");
110            assertTrue("expected: " + rows + " actual: " + "25", 25 == rows);
111        }
112    
113        @Test
114        public void testMissingFile() throws Exception
115        {
116            System.getProperties().remove("Id");
117            DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
118            factory.setFile(MULTI_TENENT_FILE);
119            CombinedConfiguration config = factory.getConfiguration(true);
120            System.setProperty("Id", "3099");
121            int rows = config.getInt("rowsPerPage");
122            assertTrue("expected: " + rows + " actual: " + "50", 50 == rows);
123    
124        }
125    
126        @Test
127        public void testFileReload1() throws Exception
128        {
129            System.getProperties().remove("Id");
130            DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
131            factory.setFile(MULTI_RELOAD_FILE);
132            CombinedConfiguration config = factory.getConfiguration(true);
133    
134            // create a new configuration
135            File input = new File("target/test-classes/testMultiConfiguration_3001.xml");
136            File output = new File("target/test-classes/testwrite/testMultiConfiguration_3001.xml");
137            output.delete();
138            output.getParentFile().mkdir();
139            copyFile(input, output);
140    
141            assertNotNull(config);
142            verify("3001", config, 15);
143            Thread.sleep(1100);
144            XMLConfiguration x = new XMLConfiguration();
145            x.setFile(output);
146            x.setAttributeSplittingDisabled(true);
147            x.setDelimiterParsingDisabled(true);
148            x.load();
149            x.setProperty("rowsPerPage", "35");
150            //Insure orginal timestamp and new timestamp aren't the same second.
151            Thread.sleep(1100);
152            x.save();
153            verify("3001", config, 35);
154            output.delete();
155        }
156    
157        @Test
158        public void testFileReload2() throws Exception
159        {
160            // create a new configuration
161            File input = new File("target/test-classes/testMultiConfiguration_3002.xml");
162            File output = new File("target/test-classes/testwrite/testMultiConfiguration_3002.xml");
163            output.delete();
164    
165            System.getProperties().remove("Id");
166            DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
167            factory.setFile(MULTI_RELOAD_FILE);
168            CombinedConfiguration config = factory.getConfiguration(true);
169            assertNotNull(config);
170            // The file should not exist yet.
171            verify("3002", config, 50);
172    
173            output.getParentFile().mkdir();
174            copyFile(input, output);
175            Thread.sleep(600);
176            verify("3002", config, 25);
177            output.delete();
178        }
179    
180        @Test
181        public void testFileReload3() throws Exception
182        {
183            // create a new configuration
184            File input = new File("target/test-classes/testMultiConfiguration_3001.xml");
185            File output = new File("target/test-classes/testwrite/testMultiConfiguration_3001.xml");
186            output.delete();
187            output.getParentFile().mkdir();
188    
189            System.getProperties().remove("Id");
190            DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
191            factory.setFile(MULTI_RELOAD_FILE);
192            CombinedConfiguration config = factory.getConfiguration(true);
193            assertNotNull(config);
194            //The file does not exist yet.
195            verify("3001", config, 50);
196            copyFile(input, output);
197            //Sleep so refreshDelay elapses
198            Thread.sleep(600);
199            verify("3001", config, 15);
200            Thread.sleep(500);
201            XMLConfiguration x = new XMLConfiguration();
202            x.setFile(output);
203            x.setAttributeSplittingDisabled(true);
204            x.setDelimiterParsingDisabled(true);
205            x.load();
206            x.setProperty("rowsPerPage", "35");
207            // Insure original timestamp and new timestamp are not the same second.
208            Thread.sleep(1100);
209            x.save();
210            verify("3001", config, 35);
211            output.delete();
212        }
213    
214        @Test
215        public void testReloadDefault() throws Exception
216        {
217            // create a new configuration
218            String defaultName = "target/test-classes/testMultiConfiguration_default.xml";
219            File input = new File(defaultName);
220    
221            System.getProperties().remove("Id");
222            DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
223            factory.setFile(MULTI_TENENT_FILE2);
224            CombinedConfiguration config = factory.getConfiguration(true);
225            assertNotNull(config);
226            verify("3001", config, 15);
227            verify("3002", config, 25);
228            System.setProperty("Id", "3002");
229            config.addProperty("/ TestProp", "Test");
230            assertTrue("Property not added", "Test".equals(config.getString("TestProp")));
231            System.getProperties().remove("Id");
232            //Sleep so refreshDelay elapses
233            Thread.sleep(600);
234            long time = System.currentTimeMillis();
235            long original = input.lastModified();
236            input.setLastModified(time);
237            File defaultFile = new File(defaultName);
238            long newTime = defaultFile.lastModified();
239            assertTrue("time mismatch", original != newTime);
240            Thread.sleep(600);
241            verify("3001", config, 15);
242            verify("3002", config, 25);
243            System.setProperty("Id", "3002");
244            String test = config.getString("TestProp");
245            assertNull("Property was not cleared by reload", test);
246        }
247    
248        @Test
249        public void testFileReloadSchemaValidationError() throws Exception
250        {
251            System.getProperties().remove("Id");
252            DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
253            factory.setFile(MULTI_RELOAD_FILE);
254            CombinedConfiguration config = factory.getConfiguration(true);
255    
256            // create a new configuration
257            File input = new File("target/test-classes/testMultiConfiguration_3001.xml");
258            File output = new File("target/test-classes/testwrite/testMultiConfiguration_3001.xml");
259            output.delete();
260            output.getParentFile().mkdir();
261            copyFile(input, output);
262    
263            assertNotNull(config);
264            verify("3001", config, 15);
265            Thread.sleep(1100);
266            XMLConfiguration x = new XMLConfiguration();
267            x.setFile(output);
268            x.setAttributeSplittingDisabled(true);
269            x.setDelimiterParsingDisabled(true);
270            x.load();
271            x.setProperty("rowsPerPage", "test");
272            //Insure orginal timestamp and new timestamp aren't the same second.
273            Thread.sleep(1100);
274            x.save();
275            System.setProperty("Id", "3001");
276            try
277            {
278                config.getInt("rowsPerPage");
279                fail("No exception was thrown");
280            }
281            catch (Exception ex)
282            {
283    
284            }
285    
286            output.delete();
287        }
288    
289        private void copyFile(File input, File output) throws IOException
290        {
291            Reader reader = new FileReader(input);
292            Writer writer = new FileWriter(output);
293            char[] buffer = new char[4096];
294            int n = 0;
295            while (-1 != (n = reader.read(buffer)))
296            {
297                writer.write(buffer, 0, n);
298            }
299            reader.close();
300            writer.close();
301        }
302    
303        private void verify(String key, CombinedConfiguration config, int rows)
304        {
305            if (key == null)
306            {
307                System.getProperties().remove("Id");
308            }
309            else
310            {
311                System.setProperty("Id", key);
312            }
313            int actual = config.getInt("rowsPerPage");
314            assertTrue("expected: " + rows + " actual: " + actual, actual == rows);
315        }
316    }