1   package org.apache.commons.configuration;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements.  See the NOTICE file distributed with
6    * this work for additional information regarding copyright ownership.
7    * The ASF licenses this file to You under the Apache License, Version 2.0
8    * (the "License"); you may not use this file except in compliance with
9    * the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  import junit.framework.TestCase;
21  
22  import java.io.File;
23  import java.util.Collection;
24  import java.util.Iterator;
25  
26  /***
27   * Test class for XMLConfiguration. In addition to TestXMLConfiguration this
28   * class especially tests the hierarchical nature of this class and structured
29   * data access.
30   *
31   * @author Emmanuel Bourg
32   * @author Mark Woodman
33   * @author Oliver Heger
34   * @version $Id: TestHierarchicalXMLConfiguration.java 439648 2006-09-02 20:42:10Z oheger $
35   */
36  public class TestHierarchicalXMLConfiguration extends TestCase
37  {
38      /*** Test resources directory. */
39      private static final String TEST_DIR = "conf";
40  
41      /*** Test file #1 **/
42      private static final String TEST_FILENAME = "testHierarchicalXMLConfiguration.xml";
43  
44      /*** Test file #2 **/
45      private static final String TEST_FILENAME2 = "testHierarchicalXMLConfiguration2.xml";
46  
47      /*** Test file path #1 **/
48      private static final String TEST_FILE = TEST_DIR + File.separator + TEST_FILENAME;
49  
50      /*** Test file path #2 **/
51      private static final String TEST_FILE2 = TEST_DIR + File.separator + TEST_FILENAME2;
52  
53      /*** Test file path #3.*/
54      private static final String TEST_FILE3 = TEST_DIR + File.separator + "test.xml";
55  
56      /*** File name for saving.*/
57      private static final String TEST_SAVENAME = "testhierarchicalsave.xml";
58  
59      /*** File path for saving.*/
60      private static final String TEST_SAVE = "target" + File.separator + TEST_SAVENAME;
61  
62      /*** Instance config used for tests. */
63      private XMLConfiguration config;
64  
65      /*** Fixture setup. */
66      protected void setUp() throws Exception
67      {
68          config = new XMLConfiguration();
69      }
70  
71      private void configTest(XMLConfiguration config)
72      {
73          assertEquals(1, config.getMaxIndex("tables.table"));
74          assertEquals("system", config.getProperty("tables.table(0)[@tableType]"));
75          assertEquals("application", config.getProperty("tables.table(1)[@tableType]"));
76  
77          assertEquals("users", config.getProperty("tables.table(0).name"));
78          assertEquals("documents", config.getProperty("tables.table(1).name"));
79  
80          Object prop = config.getProperty("tables.table.fields.field.name");
81          assertTrue(prop instanceof Collection);
82          assertEquals(10, ((Collection) prop).size());
83  
84          prop = config.getProperty("tables.table(0).fields.field.type");
85          assertTrue(prop instanceof Collection);
86          assertEquals(5, ((Collection) prop).size());
87  
88          prop = config.getProperty("tables.table(1).fields.field.type");
89          assertTrue(prop instanceof Collection);
90          assertEquals(5, ((Collection) prop).size());
91      }
92  
93      public void testGetProperty() throws Exception
94      {
95          config.setFileName(TEST_FILE);
96          config.load();
97  
98          configTest(config);
99      }
100 
101     public void testLoadURL() throws Exception
102     {
103         config.load(new File(TEST_FILE).getAbsoluteFile().toURL());
104         configTest(config);
105     }
106 
107     public void testLoadBasePath1() throws Exception
108     {
109         config.setBasePath(TEST_DIR);
110         config.setFileName(TEST_FILENAME);
111         config.load();
112         configTest(config);
113     }
114 
115     public void testLoadBasePath2() throws Exception
116     {
117         config.setBasePath(new File(TEST_FILE).getAbsoluteFile().toURL().toString());
118         config.setFileName(TEST_FILENAME);
119         config.load();
120         configTest(config);
121     }
122 
123     /***
124      * Ensure various node types are correctly processed in config.
125      * @throws Exception
126      */
127     public void testXmlNodeTypes() throws Exception
128     {
129         // Number of keys expected from test configuration file
130         final int KEY_COUNT = 5;
131 
132         // Load the configuration file
133         config.load(new File(TEST_FILE2).getAbsoluteFile().toURL());
134 
135         // Validate comment in element ignored
136         assertEquals("Comment in element must not change element value.", "Case1Text", config
137                 .getString("case1"));
138 
139         // Validate sibling comment ignored
140         assertEquals("Comment as sibling must not change element value.", "Case2Text", config
141                 .getString("case2.child"));
142 
143         // Validate comment ignored, CDATA processed
144         assertEquals("Comment and use of CDATA must not change element value.", "Case3Text", config
145                 .getString("case3"));
146 
147         // Validate comment and processing instruction ignored
148         assertEquals("Comment and use of PI must not change element value.", "Case4Text", config
149                 .getString("case4"));
150 
151         // Validate comment ignored in parent attribute
152         assertEquals("Comment must not change attribute node value.", "Case5Text", config
153                 .getString("case5[@attr]"));
154 
155         // Validate non-text nodes haven't snuck in as keys
156         Iterator iter = config.getKeys();
157         int count = 0;
158         while (iter.hasNext())
159         {
160             iter.next();
161             count++;
162         }
163         assertEquals("Config must contain only " + KEY_COUNT + " keys.", KEY_COUNT, count);
164     }
165 
166     public void testSave() throws Exception
167     {
168         removeTestSaveFile();
169         try
170         {
171             config.setFileName(TEST_FILE3);
172             config.load();
173             File saveFile = new File(TEST_SAVE);
174             config.save(saveFile);
175 
176             config = new XMLConfiguration();
177             config.load(saveFile.toURL());
178             assertEquals("value", config.getProperty("element"));
179             assertEquals("I'm complex!", config.getProperty("element2.subelement.subsubelement"));
180             assertEquals(8, config.getInt("test.short"));
181             assertEquals("one", config.getString("list(0).item(0)[@name]"));
182             assertEquals("two", config.getString("list(0).item(1)"));
183             assertEquals("six", config.getString("list(1).sublist.item(1)"));
184 
185         }
186         finally
187         {
188             removeTestSaveFile();
189         }
190     }
191 
192     /***
193      * Tests to save a newly created configuration.
194      *
195      */
196     public void testSaveNew() throws Exception
197     {
198         config.addProperty("connection.url", "jdbc://mydb:1234");
199         config.addProperty("connection.user", "scott");
200         config.addProperty("connection.passwd", "tiger");
201         config.addProperty("connection[@type]", "system");
202         config.addProperty("tables.table.name", "tests");
203         config.addProperty("tables.table(0).fields.field.name", "test_id");
204         config.addProperty("tables.table(0).fields.field(-1).name", "test_name");
205         config.addProperty("tables.table(-1).name", "results");
206         config.addProperty("tables.table(1).fields.field.name", "res_id");
207         config.addProperty("tables.table(1).fields.field(0).type", "int");
208         config.addProperty("tables.table(1).fields.field(-1).name", "value");
209         config.addProperty("tables.table(1).fields.field(1).type", "string");
210         config.addProperty("tables.table(1).fields.field(1)[@null]", "true");
211 
212         removeTestSaveFile();
213         try
214         {
215             File saveFile = new File(TEST_SAVE);
216             config.setFile(saveFile);
217             config.setRootElementName("myconfig");
218             config.save();
219 
220             config = new XMLConfiguration();
221             config.load(saveFile);
222             assertEquals(1, config.getMaxIndex("tables.table.name"));
223             assertEquals("tests", config.getString("tables.table(0).name"));
224             assertEquals("test_name", config.getString("tables.table(0).fields.field(1).name"));
225             assertEquals("int", config.getString("tables.table(1).fields.field(0).type"));
226             assertTrue(config.getBoolean("tables.table(1).fields.field(1)[@null]"));
227             assertEquals("tiger", config.getString("connection.passwd"));
228             assertEquals("system", config.getProperty("connection[@type]"));
229             assertEquals("myconfig", config.getRootElementName());
230         }
231         finally
232         {
233             removeTestSaveFile();
234         }
235     }
236 
237     /***
238      * Tests to save a modified configuration.
239      *
240      */
241     public void testSaveModified() throws Exception
242     {
243         config.setFile(new File(TEST_FILE3));
244         config.load();
245 
246         assertTrue(config.getString("mean").startsWith("This is\n A long story..."));
247         assertTrue(config.getString("mean").indexOf("And even longer") > 0);
248         config.clearProperty("test.entity[@name]");
249         config.setProperty("element", "new value");
250         config.setProperty("test(0)", "A <new> value");
251         config.addProperty("test(1).int", new Integer(9));
252         config.addProperty("list(1).sublist.item", "seven");
253         config.setProperty("clear", "yes");
254         config.setProperty("mean", "now it's simple");
255         config.addProperty("[@topattr]", "available");
256         config.addProperty("[@topattr]", "successfull");
257 
258         removeTestSaveFile();
259         try
260         {
261             config.save(new File(TEST_SAVE));
262             config = new XMLConfiguration();
263             config.load(TEST_SAVE);
264             assertFalse(config.containsKey("test.entity[@name]"));
265             assertEquals("1<2", config.getProperty("test.entity"));
266             assertEquals("new value", config.getString("element"));
267             assertEquals("A <new> value", config.getProperty("test(0)"));
268             assertEquals((short) 8, config.getShort("test(1).short"));
269             assertEquals(9, config.getInt("test(1).int"));
270             assertEquals("six", config.getProperty("list(1).sublist.item(1)"));
271             assertEquals("seven", config.getProperty("list(1).sublist.item(2)"));
272             assertEquals("yes", config.getProperty("clear"));
273             assertEquals("now it's simple", config.getString("mean"));
274             assertEquals("available", config.getString("[@topattr](0)"));
275             assertEquals("successfull", config.getString("[@topattr](1)"));
276         }
277         finally
278         {
279             removeTestSaveFile();
280         }
281     }
282     
283     /***
284      * Tests manipulation of the root element's name.
285      *
286      */
287     public void testRootElement() throws Exception
288     {
289         assertEquals("configuration", config.getRootElementName());
290         config.setRootElementName("newRootName");
291         assertEquals("newRootName", config.getRootElementName());
292         
293         config.setFile(new File(TEST_FILE3));
294         config.load();
295         assertEquals("testconfig", config.getRootElementName());
296         try
297         {
298             config.setRootElementName("anotherRootElement");
299             fail("Setting root element name when loaded from file!");
300         }
301         catch(UnsupportedOperationException uex)
302         {
303             //fine
304         }
305     }
306 
307     /***
308      * Helper method that ensures that the test save file has been removed. 
309      *
310      */
311     private void removeTestSaveFile()
312     {
313         File saveFile = new File(TEST_SAVE);
314         if (saveFile.exists())
315         {
316             assertTrue(saveFile.delete());
317         }
318     }
319 }