View Javadoc
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.configuration2;
19  
20  import static org.apache.commons.configuration2.TempDirUtils.newFile;
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  
27  import java.io.File;
28  import java.util.Collection;
29  import java.util.Iterator;
30  
31  import org.apache.commons.configuration2.io.FileHandler;
32  import org.junit.jupiter.api.BeforeEach;
33  import org.junit.jupiter.api.Test;
34  import org.junit.jupiter.api.io.TempDir;
35  
36  /**
37   * Test class for XMLConfiguration. In addition to TestXMLConfiguration this class especially tests the hierarchical
38   * nature of this class and structured data access.
39   */
40  public class TestHierarchicalXMLConfiguration {
41      /** Test resources directory. */
42      private static final String TEST_DIR = "conf";
43  
44      /** Test file #1 **/
45      private static final String TEST_FILENAME = "testHierarchicalXMLConfiguration.xml";
46  
47      /** Test file #2 **/
48      private static final String TEST_FILENAME2 = "testHierarchicalXMLConfiguration2.xml";
49  
50      /** Test file path #1 **/
51      private static final String TEST_FILE = ConfigurationAssert.getTestFile(TEST_FILENAME).getAbsolutePath();
52  
53      /** Test file path #2 **/
54      private static final String TEST_FILE2 = ConfigurationAssert.getTestFile(TEST_FILENAME2).getAbsolutePath();
55  
56      /** Test file path #3. */
57      private static final String TEST_FILE3 = ConfigurationAssert.getTestFile("test.xml").getAbsolutePath();
58  
59      /** File name for saving. */
60      private static final String TEST_SAVENAME = "testhierarchicalsave.xml";
61  
62      /** A folder for temporary files. */
63      @TempDir
64      public File tempFolder;
65  
66      /** Instance config used for tests. */
67      private XMLConfiguration config;
68  
69      private void configTest(final XMLConfiguration config) {
70          assertEquals(1, config.getMaxIndex("tables.table"));
71          assertEquals("system", config.getProperty("tables.table(0)[@tableType]"));
72          assertEquals("application", config.getProperty("tables.table(1)[@tableType]"));
73  
74          assertEquals("users", config.getProperty("tables.table(0).name"));
75          assertEquals("documents", config.getProperty("tables.table(1).name"));
76  
77          Object prop = config.getProperty("tables.table.fields.field.name");
78          Collection<?> collection = assertInstanceOf(Collection.class, prop);
79          assertEquals(10, collection.size());
80  
81          prop = config.getProperty("tables.table(0).fields.field.type");
82          collection = assertInstanceOf(Collection.class, prop);
83          assertEquals(5, collection.size());
84  
85          prop = config.getProperty("tables.table(1).fields.field.type");
86          collection = assertInstanceOf(Collection.class, prop);
87          assertEquals(5, collection.size());
88      }
89  
90      /** Fixture setup. */
91      @BeforeEach
92      public void setUp() throws Exception {
93          config = new XMLConfiguration();
94      }
95  
96      @Test
97      public void testGetProperty() throws Exception {
98          final FileHandler handler = new FileHandler(config);
99          handler.setFileName(TEST_FILE);
100         handler.load();
101 
102         configTest(config);
103     }
104 
105     @Test
106     public void testLoadBasePath1() throws Exception {
107         final FileHandler handler = new FileHandler(config);
108         handler.setBasePath(TEST_DIR);
109         handler.setFileName(TEST_FILENAME);
110         handler.load();
111         configTest(config);
112     }
113 
114     @Test
115     public void testLoadBasePath2() throws Exception {
116         final FileHandler handler = new FileHandler(config);
117         handler.setBasePath(new File(TEST_FILE).getAbsoluteFile().toURI().toURL().toString());
118         handler.setFileName(TEST_FILENAME);
119         handler.load();
120         configTest(config);
121     }
122 
123     @Test
124     public void testLoadURL() throws Exception {
125         final FileHandler handler = new FileHandler(config);
126         handler.load(new File(TEST_FILE).getAbsoluteFile().toURI().toURL());
127         configTest(config);
128     }
129 
130     /**
131      * Tests manipulation of the root element's name.
132      */
133     @Test
134     public void testRootElement() throws Exception {
135         assertEquals("configuration", config.getRootElementName());
136         config.setRootElementName("newRootName");
137         assertEquals("newRootName", config.getRootElementName());
138     }
139 
140     @Test
141     public void testSave() throws Exception {
142         final FileHandler handler = new FileHandler(config);
143         handler.setFileName(TEST_FILE3);
144         handler.load();
145         final File saveFile = newFile(TEST_SAVENAME, tempFolder);
146         handler.save(saveFile);
147 
148         config = new XMLConfiguration();
149         final FileHandler handler2 = new FileHandler(config);
150         handler2.load(saveFile.toURI().toURL());
151         assertEquals("value", config.getProperty("element"));
152         assertEquals("I'm complex!", config.getProperty("element2.subelement.subsubelement"));
153         assertEquals(8, config.getInt("test.short"));
154         assertEquals("one", config.getString("list(0).item(0)[@name]"));
155         assertEquals("two", config.getString("list(0).item(1)"));
156         assertEquals("six", config.getString("list(1).sublist.item(1)"));
157     }
158 
159     /**
160      * Tests to save a modified configuration.
161      */
162     @Test
163     public void testSaveModified() throws Exception {
164         FileHandler handler = new FileHandler(config);
165         handler.setFile(new File(TEST_FILE3));
166         handler.load();
167 
168         assertTrue(config.getString("mean").startsWith("This is\n A long story..."));
169         assertTrue(config.getString("mean").indexOf("And even longer") > 0);
170         config.clearProperty("test.entity[@name]");
171         config.setProperty("element", "new value");
172         config.setProperty("test(0)", "A <new> value");
173         config.addProperty("test(1).int", Integer.valueOf(9));
174         config.addProperty("list(1).sublist.item", "seven");
175         config.setProperty("clear", "yes");
176         config.setProperty("mean", "now it's simple");
177         config.addProperty("[@topattr]", "available");
178         config.addProperty("[@topattr_other]", "successfull");
179 
180         final File saveFile = newFile(TEST_SAVENAME, tempFolder);
181         handler.save(saveFile);
182         config = new XMLConfiguration();
183         handler = new FileHandler(config);
184         handler.load(saveFile.getAbsolutePath());
185         assertFalse(config.containsKey("test.entity[@name]"));
186         assertEquals("1<2", config.getProperty("test.entity"));
187         assertEquals("new value", config.getString("element"));
188         assertEquals("A <new> value", config.getProperty("test(0)"));
189         assertEquals((short) 8, config.getShort("test(1).short"));
190         assertEquals(9, config.getInt("test(1).int"));
191         assertEquals("six", config.getProperty("list(1).sublist.item(1)"));
192         assertEquals("seven", config.getProperty("list(1).sublist.item(2)"));
193         assertEquals("yes", config.getProperty("clear"));
194         assertEquals("now it's simple", config.getString("mean"));
195         assertEquals("available", config.getString("[@topattr](0)"));
196         assertEquals("successfull", config.getString("[@topattr_other]"));
197     }
198 
199     /**
200      * Tests to save a newly created configuration.
201      */
202     @Test
203     public void testSaveNew() throws Exception {
204         config.addProperty("connection.url", "jdbc://mydb:1234");
205         config.addProperty("connection.user", "scott");
206         config.addProperty("connection.passwd", "tiger");
207         config.addProperty("connection[@type]", "system");
208         config.addProperty("tables.table.name", "tests");
209         config.addProperty("tables.table(0).fields.field.name", "test_id");
210         config.addProperty("tables.table(0).fields.field(-1).name", "test_name");
211         config.addProperty("tables.table(-1).name", "results");
212         config.addProperty("tables.table(1).fields.field.name", "res_id");
213         config.addProperty("tables.table(1).fields.field(0).type", "int");
214         config.addProperty("tables.table(1).fields.field(-1).name", "value");
215         config.addProperty("tables.table(1).fields.field(1).type", "string");
216         config.addProperty("tables.table(1).fields.field(1)[@null]", "true");
217 
218         config.setRootElementName("myconfig");
219         final File saveFile = newFile(TEST_SAVENAME, tempFolder);
220         FileHandler handler = new FileHandler(config);
221         handler.setFile(saveFile);
222         handler.save();
223 
224         config = new XMLConfiguration();
225         handler = new FileHandler(config);
226         handler.load(saveFile);
227         assertEquals(1, config.getMaxIndex("tables.table.name"));
228         assertEquals("tests", config.getString("tables.table(0).name"));
229         assertEquals("test_name", config.getString("tables.table(0).fields.field(1).name"));
230         assertEquals("int", config.getString("tables.table(1).fields.field(0).type"));
231         assertTrue(config.getBoolean("tables.table(1).fields.field(1)[@null]"));
232         assertEquals("tiger", config.getString("connection.passwd"));
233         assertEquals("system", config.getProperty("connection[@type]"));
234         assertEquals("myconfig", config.getRootElementName());
235     }
236 
237     /**
238      * Tests that it is not allowed to change the root element name when the configuration was loaded from a file.
239      */
240     @Test
241     public void testSetRootElementNameWhenLoadedFromFile() throws Exception {
242         final FileHandler handler = new FileHandler(config);
243         handler.setFile(new File(TEST_FILE3));
244         handler.load();
245         assertEquals("testconfig", config.getRootElementName());
246         assertThrows(UnsupportedOperationException.class, () -> config.setRootElementName("anotherRootElement"));
247     }
248 
249     /**
250      * Ensure various node types are correctly processed in config.
251      */
252     @Test
253     public void testXmlNodeTypes() throws Exception {
254         // Number of keys expected from test configuration file
255         final int KEY_COUNT = 5;
256 
257         // Load the configuration file
258         final FileHandler handler = new FileHandler(config);
259         handler.load(new File(TEST_FILE2).getAbsoluteFile().toURI().toURL());
260 
261         // Validate comment in element ignored
262         assertEquals("Case1Text", config.getString("case1"));
263 
264         // Validate sibling comment ignored
265         assertEquals("Case2Text", config.getString("case2.child"));
266 
267         // Validate comment ignored, CDATA processed
268         assertEquals("Case3Text", config.getString("case3"));
269 
270         // Validate comment and processing instruction ignored
271         assertEquals("Case4Text", config.getString("case4"));
272 
273         // Validate comment ignored in parent attribute
274         assertEquals("Case5Text", config.getString("case5[@attr]"));
275 
276         // Validate non-text nodes haven't snuck in as keys
277         final Iterator<String> iter = config.getKeys();
278         int count = 0;
279         while (iter.hasNext()) {
280             iter.next();
281             count++;
282         }
283         assertEquals(KEY_COUNT, count);
284     }
285 }