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