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