001    package org.apache.commons.configuration;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one or more
005     * contributor license agreements.  See the NOTICE file distributed with
006     * this work for additional information regarding copyright ownership.
007     * The ASF licenses this file to You under the Apache License, Version 2.0
008     * (the "License"); you may not use this file except in compliance with
009     * the License.  You may obtain a copy of the License at
010     *
011     *     http://www.apache.org/licenses/LICENSE-2.0
012     *
013     * Unless required by applicable law or agreed to in writing, software
014     * distributed under the License is distributed on an "AS IS" BASIS,
015     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016     * See the License for the specific language governing permissions and
017     * limitations under the License.
018     */
019    
020    import static org.junit.Assert.assertEquals;
021    import static org.junit.Assert.assertFalse;
022    import static org.junit.Assert.assertTrue;
023    
024    import java.io.File;
025    import java.util.Collection;
026    import java.util.Iterator;
027    
028    import org.junit.Before;
029    import org.junit.Rule;
030    import org.junit.Test;
031    import org.junit.rules.TemporaryFolder;
032    
033    /**
034     * Test class for XMLConfiguration. In addition to TestXMLConfiguration this
035     * class especially tests the hierarchical nature of this class and structured
036     * data access.
037     *
038     * @author Emmanuel Bourg
039     * @author Mark Woodman
040     * @version $Id: TestHierarchicalXMLConfiguration.java 1224764 2011-12-26 17:14:49Z oheger $
041     */
042    public class TestHierarchicalXMLConfiguration
043    {
044        /** Test resources directory. */
045        private static final String TEST_DIR = "conf";
046    
047        /** Test file #1 **/
048        private static final String TEST_FILENAME = "testHierarchicalXMLConfiguration.xml";
049    
050        /** Test file #2 **/
051        private static final String TEST_FILENAME2 = "testHierarchicalXMLConfiguration2.xml";
052    
053        /** Test file path #1 **/
054        private static final String TEST_FILE = ConfigurationAssert.getTestFile(TEST_FILENAME).getAbsolutePath();
055    
056        /** Test file path #2 **/
057        private static final String TEST_FILE2 = ConfigurationAssert.getTestFile(TEST_FILENAME2).getAbsolutePath();
058    
059        /** Test file path #3.*/
060        private static final String TEST_FILE3 = ConfigurationAssert.getTestFile("test.xml").getAbsolutePath();
061    
062        /** File name for saving.*/
063        private static final String TEST_SAVENAME = "testhierarchicalsave.xml";
064    
065        /** Helper object for creating temporary files. */
066        @Rule
067        public TemporaryFolder folder = new TemporaryFolder();
068    
069        /** Instance config used for tests. */
070        private XMLConfiguration config;
071    
072        /** Fixture setup. */
073        @Before
074        public void setUp() throws Exception
075        {
076            config = new XMLConfiguration();
077        }
078    
079        private void configTest(XMLConfiguration config)
080        {
081            assertEquals(1, config.getMaxIndex("tables.table"));
082            assertEquals("system", config.getProperty("tables.table(0)[@tableType]"));
083            assertEquals("application", config.getProperty("tables.table(1)[@tableType]"));
084    
085            assertEquals("users", config.getProperty("tables.table(0).name"));
086            assertEquals("documents", config.getProperty("tables.table(1).name"));
087    
088            Object prop = config.getProperty("tables.table.fields.field.name");
089            assertTrue(prop instanceof Collection);
090            assertEquals(10, ((Collection<?>) prop).size());
091    
092            prop = config.getProperty("tables.table(0).fields.field.type");
093            assertTrue(prop instanceof Collection);
094            assertEquals(5, ((Collection<?>) prop).size());
095    
096            prop = config.getProperty("tables.table(1).fields.field.type");
097            assertTrue(prop instanceof Collection);
098            assertEquals(5, ((Collection<?>) prop).size());
099        }
100    
101        @Test
102        public void testGetProperty() throws Exception
103        {
104            config.setFileName(TEST_FILE);
105            config.load();
106    
107            configTest(config);
108        }
109    
110        @Test
111        public void testLoadURL() throws Exception
112        {
113            config.load(new File(TEST_FILE).getAbsoluteFile().toURI().toURL());
114            configTest(config);
115        }
116    
117        @Test
118        public void testLoadBasePath1() throws Exception
119        {
120            config.setBasePath(TEST_DIR);
121            config.setFileName(TEST_FILENAME);
122            config.load();
123            configTest(config);
124        }
125    
126        @Test
127        public void testLoadBasePath2() throws Exception
128        {
129            config.setBasePath(new File(TEST_FILE).getAbsoluteFile().toURI().toURL().toString());
130            config.setFileName(TEST_FILENAME);
131            config.load();
132            configTest(config);
133        }
134    
135        /**
136         * Ensure various node types are correctly processed in config.
137         * @throws Exception
138         */
139        @Test
140        public void testXmlNodeTypes() throws Exception
141        {
142            // Number of keys expected from test configuration file
143            final int KEY_COUNT = 5;
144    
145            // Load the configuration file
146            config.load(new File(TEST_FILE2).getAbsoluteFile().toURI().toURL());
147    
148            // Validate comment in element ignored
149            assertEquals("Comment in element must not change element value.", "Case1Text", config
150                    .getString("case1"));
151    
152            // Validate sibling comment ignored
153            assertEquals("Comment as sibling must not change element value.", "Case2Text", config
154                    .getString("case2.child"));
155    
156            // Validate comment ignored, CDATA processed
157            assertEquals("Comment and use of CDATA must not change element value.", "Case3Text", config
158                    .getString("case3"));
159    
160            // Validate comment and processing instruction ignored
161            assertEquals("Comment and use of PI must not change element value.", "Case4Text", config
162                    .getString("case4"));
163    
164            // Validate comment ignored in parent attribute
165            assertEquals("Comment must not change attribute node value.", "Case5Text", config
166                    .getString("case5[@attr]"));
167    
168            // Validate non-text nodes haven't snuck in as keys
169            Iterator<String> iter = config.getKeys();
170            int count = 0;
171            while (iter.hasNext())
172            {
173                iter.next();
174                count++;
175            }
176            assertEquals("Config must contain only " + KEY_COUNT + " keys.", KEY_COUNT, count);
177        }
178    
179        @Test
180        public void testSave() throws Exception
181        {
182            config.setFileName(TEST_FILE3);
183            config.load();
184            File saveFile = folder.newFile(TEST_SAVENAME);
185            config.save(saveFile);
186    
187            config = new XMLConfiguration();
188            config.load(saveFile.toURI().toURL());
189            assertEquals("value", config.getProperty("element"));
190            assertEquals("I'm complex!", config.getProperty("element2.subelement.subsubelement"));
191            assertEquals(8, config.getInt("test.short"));
192            assertEquals("one", config.getString("list(0).item(0)[@name]"));
193            assertEquals("two", config.getString("list(0).item(1)"));
194            assertEquals("six", config.getString("list(1).sublist.item(1)"));
195        }
196    
197        /**
198         * Tests to save a newly created configuration.
199         */
200        @Test
201        public void testSaveNew() throws Exception
202        {
203            config.addProperty("connection.url", "jdbc://mydb:1234");
204            config.addProperty("connection.user", "scott");
205            config.addProperty("connection.passwd", "tiger");
206            config.addProperty("connection[@type]", "system");
207            config.addProperty("tables.table.name", "tests");
208            config.addProperty("tables.table(0).fields.field.name", "test_id");
209            config.addProperty("tables.table(0).fields.field(-1).name", "test_name");
210            config.addProperty("tables.table(-1).name", "results");
211            config.addProperty("tables.table(1).fields.field.name", "res_id");
212            config.addProperty("tables.table(1).fields.field(0).type", "int");
213            config.addProperty("tables.table(1).fields.field(-1).name", "value");
214            config.addProperty("tables.table(1).fields.field(1).type", "string");
215            config.addProperty("tables.table(1).fields.field(1)[@null]", "true");
216    
217            File saveFile = folder.newFile(TEST_SAVENAME);
218            config.setFile(saveFile);
219            config.setRootElementName("myconfig");
220            config.save();
221    
222            config = new XMLConfiguration();
223            config.load(saveFile);
224            assertEquals(1, config.getMaxIndex("tables.table.name"));
225            assertEquals("tests", config.getString("tables.table(0).name"));
226            assertEquals("test_name", config.getString("tables.table(0).fields.field(1).name"));
227            assertEquals("int", config.getString("tables.table(1).fields.field(0).type"));
228            assertTrue(config.getBoolean("tables.table(1).fields.field(1)[@null]"));
229            assertEquals("tiger", config.getString("connection.passwd"));
230            assertEquals("system", config.getProperty("connection[@type]"));
231            assertEquals("myconfig", config.getRootElementName());
232        }
233    
234        /**
235         * Tests to save a modified configuration.
236         */
237        @Test
238        public void testSaveModified() throws Exception
239        {
240            config.setFile(new File(TEST_FILE3));
241            config.load();
242    
243            assertTrue(config.getString("mean").startsWith("This is\n A long story..."));
244            assertTrue(config.getString("mean").indexOf("And even longer") > 0);
245            config.clearProperty("test.entity[@name]");
246            config.setProperty("element", "new value");
247            config.setProperty("test(0)", "A <new> value");
248            config.addProperty("test(1).int", new Integer(9));
249            config.addProperty("list(1).sublist.item", "seven");
250            config.setProperty("clear", "yes");
251            config.setProperty("mean", "now it's simple");
252            config.addProperty("[@topattr]", "available");
253            config.addProperty("[@topattr]", "successfull");
254    
255            File saveFile = folder.newFile(TEST_SAVENAME);
256            config.save(saveFile);
257            config = new XMLConfiguration();
258            config.load(saveFile.getAbsolutePath());
259            assertFalse(config.containsKey("test.entity[@name]"));
260            assertEquals("1<2", config.getProperty("test.entity"));
261            assertEquals("new value", config.getString("element"));
262            assertEquals("A <new> value", config.getProperty("test(0)"));
263            assertEquals((short) 8, config.getShort("test(1).short"));
264            assertEquals(9, config.getInt("test(1).int"));
265            assertEquals("six", config.getProperty("list(1).sublist.item(1)"));
266            assertEquals("seven", config.getProperty("list(1).sublist.item(2)"));
267            assertEquals("yes", config.getProperty("clear"));
268            assertEquals("now it's simple", config.getString("mean"));
269            assertEquals("available", config.getString("[@topattr](0)"));
270            assertEquals("successfull", config.getString("[@topattr](1)"));
271        }
272    
273        /**
274         * Tests manipulation of the root element's name.
275         */
276        @Test
277        public void testRootElement() throws Exception
278        {
279            assertEquals("configuration", config.getRootElementName());
280            config.setRootElementName("newRootName");
281            assertEquals("newRootName", config.getRootElementName());
282        }
283    
284        /**
285         * Tests that it is not allowed to change the root element name when the
286         * configuration was loaded from a file.
287         */
288        @Test(expected = UnsupportedOperationException.class)
289        public void testSetRootElementNameWhenLoadedFromFile() throws Exception
290        {
291            config.setFile(new File(TEST_FILE3));
292            config.load();
293            assertEquals("testconfig", config.getRootElementName());
294            config.setRootElementName("anotherRootElement");
295        }
296    }