KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > myvietnam > mvncore > configuration > DOM4JConfiguration


1 package net.myvietnam.mvncore.configuration;
2
3 /* ====================================================================
4  * The Apache Software License, Version 1.1
5  *
6  * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
7  * reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if
22  * any, must include the following acknowledgement:
23  * "This product includes software developed by the
24  * Apache Software Foundation (http://www.apache.org/)."
25  * Alternately, this acknowledgement may appear in the software itself,
26  * if and wherever such third-party acknowledgements normally appear.
27  *
28  * 4. The names "The Jakarta Project", "Commons", and "Apache Software
29  * Foundation" must not be used to endorse or promote products derived
30  * from this software without prior written permission. For written
31  * permission, please contact apache@apache.org.
32  *
33  * 5. Products derived from this software may not be called "Apache"
34  * nor may "Apache" appear in their names without prior written
35  * permission of the Apache Software Foundation.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals on behalf of the Apache Software Foundation. For more
53  * information on the Apache Software Foundation, please see
54  * <http://www.apache.org/>.
55  */

56
57 import java.io.BufferedOutputStream JavaDoc;
58 import java.io.File JavaDoc;
59 import java.io.FileOutputStream JavaDoc;
60 import java.io.IOException JavaDoc;
61 import java.io.OutputStream JavaDoc;
62 import java.net.URL JavaDoc;
63 import java.util.Iterator JavaDoc;
64 import java.util.List JavaDoc;
65
66 import org.dom4j.Attribute;
67 import org.dom4j.Document;
68 import org.dom4j.Element;
69 import org.dom4j.io.OutputFormat;
70 import org.dom4j.io.SAXReader;
71 import org.dom4j.io.XMLWriter;
72
73 import org.apache.commons.lang.StringUtils;
74 import org.apache.commons.lang.exception.NestableRuntimeException;
75
76 /**
77  * Reads a XML configuration file.
78  *
79  * To retrieve the value of an attribute of an element, use
80  * <code>X.Y.Z[@attribute]</code>. The '@' symbol was chosen for
81  * consistency with XPath.
82  *
83  * Setting property values will <b>NOT</b> automatically persist
84  * changes to disk, unless <code>autoSave=true</code>.
85  *
86  * @author <a HREF="mailto:kelvint@apache.org">Kelvin Tan</a>
87  * @author <a HREF="mailto:dlr@apache.org">Daniel Rall</a>
88  * @since 0.8.1
89  */

90 public class DOM4JConfiguration extends XMLConfiguration
91 {
92     // For conformance with xpath
93
private static final char ATTRIB_MARKER = '@';
94     private static final String JavaDoc ATTRIB_START_MARKER = "[" + ATTRIB_MARKER;
95
96     /**
97      * For consistency with properties files. Access nodes via an
98      * "A.B.C" notation.
99      */

100     private static final String JavaDoc NODE_DELIMITER = ".";
101
102     /**
103      * A handle to our data source.
104      */

105     private String JavaDoc fileName;
106
107     /**
108      * The XML document from our data source.
109      */

110     private Document document;
111
112     /**
113      * If true, modifications are immediately persisted.
114      */

115     private boolean autoSave = false;
116
117     /**
118      * Empty construtor. You must provide a file/fileName
119      * and call the load method
120      *
121      */

122     public DOM4JConfiguration()
123     {
124     }
125
126     /**
127      * Attempts to load the XML file as a resource from the
128      * classpath. The XML file must be located somewhere in the
129      * classpath.
130      *
131      * @param resource Name of the resource
132      * @exception Exception If error reading data source.
133      * @see DOM4JConfiguration#DOM4JConfiguration(File)
134      */

135     public DOM4JConfiguration(String JavaDoc resource) throws Exception JavaDoc
136     {
137         setFile(resourceURLToFile(resource));
138         load();
139     }
140
141     /**
142      * Attempts to load the XML file.
143      *
144      * @param file File object representing the XML file.
145      * @exception Exception If error reading data source.
146      */

147     public DOM4JConfiguration(File JavaDoc file) throws Exception JavaDoc
148     {
149         setFile(file);
150         load();
151     }
152
153     public void load() throws Exception JavaDoc
154     {
155
156         document = new SAXReader().read(
157         ConfigurationUtils.getURL(getBasePath(), getFileName()));
158         initProperties(document.getRootElement(), new StringBuffer JavaDoc());
159
160     }
161
162     private static File JavaDoc resourceURLToFile(String JavaDoc resource)
163     {
164         URL JavaDoc confURL = DOM4JConfiguration.class.getClassLoader().getResource(resource);
165         if (confURL == null)
166         {
167             confURL = ClassLoader.getSystemResource(resource);
168         }
169         return new File JavaDoc(confURL.getFile());
170     }
171
172     /**
173      * Loads and initializes from the XML file.
174      *
175      * @param element The element to start processing from. Callers
176      * should supply the root element of the document.
177      * @param hierarchy
178      */

179     private void initProperties(Element element, StringBuffer JavaDoc hierarchy)
180     {
181         for (Iterator JavaDoc it = element.elementIterator(); it.hasNext();)
182         {
183             StringBuffer JavaDoc subhierarchy = new StringBuffer JavaDoc(hierarchy.toString());
184             Element child = (Element) it.next();
185             String JavaDoc nodeName = child.getName();
186             String JavaDoc nodeValue = child.getTextTrim();
187             subhierarchy.append(nodeName);
188             if (nodeValue.length() > 0)
189             {
190                 super.addProperty(subhierarchy.toString(), nodeValue);
191             }
192
193             // Add attributes as x.y{ATTRIB_START_MARKER}att{ATTRIB_END_MARKER}
194
List JavaDoc attributes = child.attributes();
195             for (int j = 0, k = attributes.size(); j < k; j++)
196             {
197                 Attribute a = (Attribute) attributes.get(j);
198                 String JavaDoc attName = subhierarchy.toString() + '[' + ATTRIB_MARKER + a.getName() + ']';
199                 String JavaDoc attValue = a.getValue();
200                 super.addProperty(attName, attValue);
201             }
202             StringBuffer JavaDoc buf = new StringBuffer JavaDoc(subhierarchy.toString());
203             initProperties(child, buf.append('.'));
204         }
205     }
206
207     /**
208      * Calls super method, and also ensures the underlying {@link
209      * Document} is modified so changes are persisted when saved.
210      *
211      * @param name
212      * @param value
213      */

214     public void addProperty(String JavaDoc name, Object JavaDoc value)
215     {
216         super.addProperty(name, value);
217         setXmlProperty(name, value);
218         possiblySave();
219     }
220
221     /**
222      * Calls super method, and also ensures the underlying {@link
223      * Document} is modified so changes are persisted when saved.
224      *
225      * @param name
226      * @param value
227      */

228     public void setProperty(String JavaDoc name, Object JavaDoc value)
229     {
230         super.setProperty(name, value);
231         setXmlProperty(name, value);
232         possiblySave();
233     }
234
235     /**
236      * Sets the property value in our document tree, auto-saving if
237      * appropriate.
238      *
239      * @param name The name of the element to set a value for.
240      * @param value The value to set.
241      */

242     private void setXmlProperty(String JavaDoc name, Object JavaDoc value)
243     {
244         String JavaDoc[] nodes = StringUtils.split(name, NODE_DELIMITER);
245         String JavaDoc attName = null;
246         Element element = document.getRootElement();
247         for (int i = 0; i < nodes.length; i++)
248         {
249             String JavaDoc eName = nodes[i];
250             int index = eName.indexOf(ATTRIB_START_MARKER);
251             if (index > -1)
252             {
253                 attName = eName.substring(index + ATTRIB_START_MARKER.length(), eName.length() - 1);
254                 eName = eName.substring(0, index);
255             }
256             // If we don't find this part of the property in the XML heirarchy
257
// we add it as a new node
258
if (element.element(eName) == null && attName == null)
259             {
260                 element.addElement(eName);
261             }
262             element = element.element(eName);
263         }
264
265         if (attName == null)
266         {
267             element.setText((String JavaDoc) value);
268         }
269         else
270         {
271             element.addAttribute(attName, (String JavaDoc) value);
272         }
273     }
274
275     /**
276      * Calls super method, and also ensures the underlying {@link
277      * Document} is modified so changes are persisted when saved.
278      *
279      * @param name The name of the property to clear.
280      */

281     public void clearProperty(String JavaDoc name)
282     {
283         super.clearProperty(name);
284         clearXmlProperty(name);
285         possiblySave();
286     }
287
288     private void clearXmlProperty(String JavaDoc name)
289     {
290         String JavaDoc[] nodes = StringUtils.split(name, NODE_DELIMITER);
291         String JavaDoc attName = null;
292         Element element = document.getRootElement();
293         for (int i = 0; i < nodes.length; i++)
294         {
295             String JavaDoc eName = nodes[i];
296             int index = eName.indexOf(ATTRIB_START_MARKER);
297             if (index > -1)
298             {
299                 attName = eName.substring(index + ATTRIB_START_MARKER.length(), eName.length() - 1);
300                 eName = eName.substring(0, index);
301             }
302             element = element.element(eName);
303             if (element == null)
304             {
305                 return;
306             }
307         }
308
309         if (attName == null)
310         {
311             element.remove(element.element(nodes[nodes.length - 1]));
312         }
313         else
314         {
315             element.remove(element.attribute(attName));
316         }
317     }
318
319     /**
320      */

321     private void possiblySave()
322     {
323         if (autoSave)
324         {
325             try
326             {
327                 save();
328             }
329             catch (IOException JavaDoc e)
330             {
331                 throw new NestableRuntimeException("Failed to auto-save", e);
332             }
333         }
334     }
335
336     /**
337      * If true, changes are automatically persisted.
338      * @param autoSave
339      */

340     public void setAutoSave(boolean autoSave)
341     {
342         this.autoSave = autoSave;
343     }
344
345     public synchronized void save() throws IOException JavaDoc
346     {
347         XMLWriter writer = null;
348         OutputStream JavaDoc out = null;
349         try
350         {
351             OutputFormat outputter = OutputFormat.createPrettyPrint();
352             out = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(getFile()));
353             writer = new XMLWriter(out, outputter);
354             writer.write(document);
355         }
356         finally
357         {
358             if (out != null)
359             {
360                 out.close();
361             }
362
363             if (writer != null)
364             {
365                 writer.close();
366             }
367         }
368     }
369     /**
370      * Returns the file.
371      * @return File
372      */

373     public File JavaDoc getFile()
374     {
375         return ConfigurationUtils.constructFile(getBasePath(), getFileName());
376     }
377
378     /**
379      * Sets the file.
380      * @param file The file to set
381      */

382     public void setFile(File JavaDoc file)
383     {
384         this.fileName = file.getAbsolutePath();
385     }
386
387     public void setFileName(String JavaDoc fileName)
388     {
389
390         this.fileName = fileName;
391
392     }
393
394     /**
395      * Returns the fileName.
396      * @return String
397      */

398     public String JavaDoc getFileName()
399     {
400         return fileName;
401     }
402 }
403
Popular Tags