KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jdon > util > jdom > XMLProperties


1 package com.jdon.util.jdom;
2
3 /**
4  * $RCSfile: XMLProperties.java,v $
5  * $Revision: 1.1.1.1 $
6  * $Date: 2004/12/26 09:10:27 $
7  *
8  * Copyright (C) 1999-2001 CoolServlets, Inc. All rights reserved.
9  *
10  * This software is the proprietary information of CoolServlets, Inc.
11  * Use is subject to license terms.
12  */

13
14
15 import java.io.BufferedOutputStream JavaDoc;
16 import java.io.File JavaDoc;
17 import java.io.FileOutputStream JavaDoc;
18 import java.io.InputStream JavaDoc;
19 import java.io.OutputStream JavaDoc;
20 import java.io.Writer JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.StringTokenizer JavaDoc;
25
26 import org.jdom.Document;
27 import org.jdom.Element;
28 import org.jdom.input.SAXBuilder;
29 import org.jdom.output.XMLOutputter;
30
31 /**
32  * Provides the the ability to use simple XML property files. Each property is
33  * in the form X.Y.Z, which would map to an XML snippet of:
34  * <pre>
35  * &lt;X&gt;
36  * &lt;Y&gt;
37  * &lt;Z&gt;someValue&lt;/Z&gt;
38  * &lt;/Y&gt;
39  * &lt;/X&gt;
40  * </pre>
41  *
42  * The XML file is passed in to the constructor and must be readable and
43  * writtable. Setting property values will automatically persist those value
44  * to disk or outputStream.
45  */

46 public class XMLProperties {
47
48     private Document doc;
49     /**
50      * Parsing the XML file every time we need a property is slow. Therefore,
51      * we use a Map to cache property values that are accessed more than once.
52      */

53     private Map JavaDoc propertyCache = new HashMap JavaDoc();
54
55     /**
56      * Creates a new XMLProperties object.
57      *
58      * @parm file the full path the file that properties should be read from
59      * and written to.
60      */

61     public XMLProperties(String JavaDoc fileName) {
62         try {
63             SAXBuilder builder = new SAXBuilder();
64             // Strip formatting
65
DataUnformatFilter format = new DataUnformatFilter();
66             builder.setXMLFilter(format);
67             doc = builder.build(new File JavaDoc(fileName));
68         }
69         catch (Exception JavaDoc e) {
70             System.err.println("Error creating XML parser in "
71                 + "PropertyManager.java");
72             e.printStackTrace();
73         }
74     }
75
76     /**
77      * Creates a new XMLProperties object.
78      *
79      * @parm file the full path the file that properties should be read from
80      * and written to.
81      */

82     public XMLProperties(InputStream JavaDoc inputStream) {
83         try {
84             SAXBuilder builder = new SAXBuilder();
85             // Strip formatting
86
DataUnformatFilter format = new DataUnformatFilter();
87             builder.setXMLFilter(format);
88             doc = builder.build(inputStream);
89         }
90         catch (Exception JavaDoc e) {
91             System.err.println("Error creating XML parser in "
92                 + "PropertyManager.java");
93             e.printStackTrace();
94         }
95     }
96
97
98
99     /**
100      * Returns the value of the specified property.
101      *
102      * @param name the name of the property to get.
103      * @return the value of the specified property.
104      */

105     public String JavaDoc getProperty(String JavaDoc name) {
106         if (propertyCache.containsKey(name)) {
107             return (String JavaDoc)propertyCache.get(name);
108         }
109
110         String JavaDoc[] propName = parsePropertyName(name);
111         // Search for this property by traversing down the XML heirarchy.
112
Element element = doc.getRootElement();
113         for (int i = 0; i < propName.length; i++) {
114             element = element.getChild(propName[i]);
115             if (element == null) {
116                 // This node doesn't match this part of the property name which
117
// indicates this property doesn't exist so return null.
118
return null;
119             }
120         }
121         // At this point, we found a matching property, so return its value.
122
// Empty strings are returned as null.
123
String JavaDoc value = element.getText();
124         if ("".equals(value)) {
125             return null;
126         }
127         else {
128             // Add to cache so that getting property next time is fast.
129
value = value.trim();
130             propertyCache.put(name, value);
131             return value;
132         }
133     }
134
135     /**
136      * Return all children property names of a parent property as a String array,
137      * or an empty array if the if there are no children. For example, given
138      * the properties <tt>X.Y.A</tt>, <tt>X.Y.B</tt>, and <tt>X.Y.C</tt>, then
139      * the child properties of <tt>X.Y</tt> are <tt>A</tt>, <tt>B</tt>, and
140      * <tt>C</tt>.
141      *
142      * @param parent the name of the parent property.
143      * @return all child property values for the given parent.
144      */

145     public String JavaDoc [] getChildrenProperties(String JavaDoc parent) {
146         String JavaDoc[] propName = parsePropertyName(parent);
147         // Search for this property by traversing down the XML heirarchy.
148
Element element = doc.getRootElement();
149         for (int i = 0; i < propName.length; i++) {
150             element = element.getChild(propName[i]);
151             if (element == null) {
152                 // This node doesn't match this part of the property name which
153
// indicates this property doesn't exist so return empty array.
154
return new String JavaDoc [] { };
155             }
156         }
157         // We found matching property, return names of children.
158
List JavaDoc children = element.getChildren();
159         int childCount = children.size();
160         String JavaDoc [] childrenNames = new String JavaDoc[childCount];
161         for (int i=0; i<childCount; i++) {
162             childrenNames[i] = ((Element)children.get(i)).getName();
163         }
164         return childrenNames;
165     }
166
167     /**
168      * Sets the value of the specified property. If the property doesn't
169      * currently exist, it will be automatically created.
170      *
171      * @param name the name of the property to set.
172      * @param value the new value for the property.
173      */

174     public void setProperty(String JavaDoc name, String JavaDoc value) {
175         // Set cache correctly with prop name and value.
176
propertyCache.put(name, value);
177
178         String JavaDoc[] propName = parsePropertyName(name);
179         // Search for this property by traversing down the XML heirarchy.
180
Element element = doc.getRootElement();
181         for (int i=0; i<propName.length; i++) {
182             // If we don't find this part of the property in the XML heirarchy
183
// we add it as a new node
184
if (element.getChild(propName[i]) == null) {
185                 element.addContent(new Element(propName[i]));
186             }
187             element = element.getChild(propName[i]);
188         }
189         // Set the value of the property in this node.
190
element.setText(value);
191      
192     }
193
194     /**
195      * Deletes the specified property.
196      *
197      * @param name the property to delete.
198      */

199     public void deleteProperty(String JavaDoc name) {
200         String JavaDoc[] propName = parsePropertyName(name);
201         // Search for this property by traversing down the XML heirarchy.
202
Element element = doc.getRootElement();
203         for (int i=0; i<propName.length-1; i++) {
204             element = element.getChild(propName[i]);
205             // Can't find the property so return.
206
if (element == null) {
207                 return;
208             }
209         }
210         // Found the correct element to remove, so remove it...
211
element.removeChild(propName[propName.length-1]);
212       
213     }
214
215     /**
216      * Saves the properties to disk as an XML document. A temporary file is
217      * used during the writing process for maximum safety.
218      */

219     public synchronized void saveProperties(String JavaDoc fileName) {
220         OutputStream JavaDoc out = null;
221         boolean error = false;
222         File JavaDoc file = new File JavaDoc(fileName);
223         // Write data out to a temporary file first.
224
File JavaDoc tempFile = null;
225         try {
226             tempFile = new File JavaDoc(file.getParentFile(), file.getName() + ".tmp");
227             // Use JDOM's XMLOutputter to do the writing and formatting. The
228
// file should always come out pretty-printed.
229
XMLOutputter outputter = new XMLOutputter(" ", true);
230             out = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(tempFile));
231             outputter.output(doc, out);
232         }
233         catch (Exception JavaDoc e) {
234             e.printStackTrace();
235             // There were errors so abort replacing the old property file.
236
error = true;
237         }
238         finally {
239             try { out.close(); }
240             catch (Exception JavaDoc e) {
241                 e.printStackTrace();
242                 error = true;
243             }
244         }
245         // No errors occured, so we should be safe in replacing the old
246
if (!error) {
247             // Delete the old file so we can replace it.
248
file.delete();
249             // Rename the temp file. The delete and rename won't be an
250
// automic operation, but we should be pretty safe in general.
251
// At the very least, the temp file should remain in some form.
252
tempFile.renameTo(file);
253         }
254     }
255     
256     public synchronized void savePropertiesToStream(OutputStream JavaDoc out) {
257         boolean error = false;
258         try {
259             // Use JDOM's XMLOutputter to do the writing and formatting. The
260
// file should always come out pretty-printed.
261
XMLOutputter outputter = new XMLOutputter(" ", true);
262             outputter.output(doc, out);
263         }
264         catch (Exception JavaDoc e) {
265             e.printStackTrace();
266         }
267         finally {
268             try { out.close(); }
269             catch (Exception JavaDoc e) {
270                 e.printStackTrace();
271             }
272         }
273     }
274     
275     
276     public synchronized void savePropertiesToStream(Writer JavaDoc writer) {
277         boolean error = false;
278         try {
279             // Use JDOM's XMLOutputter to do the writing and formatting. The
280
// file should always come out pretty-printed.
281
XMLOutputter outputter = new XMLOutputter(" ", true);
282             outputter.output(doc, writer);
283         }
284         catch (Exception JavaDoc e) {
285             e.printStackTrace();
286         }
287         finally {
288             try { writer.close(); }
289             catch (Exception JavaDoc e) {
290                 e.printStackTrace();
291             }
292         }
293     }
294     
295
296     /**
297      * Returns an array representation of the given Jive property. Jive
298      * properties are always in the format "prop.name.is.this" which would be
299      * represented as an array of four Strings.
300      *
301      * @param name the name of the Jive property.
302      * @return an array representation of the given Jive property.
303      */

304     private String JavaDoc[] parsePropertyName(String JavaDoc name) {
305         // Figure out the number of parts of the name (this becomes the size
306
// of the resulting array).
307
int size = 1;
308         for (int i=0; i<name.length(); i++) {
309             if (name.charAt(i) == '.') {
310                 size++;
311             }
312         }
313         String JavaDoc[] propName = new String JavaDoc[size];
314         // Use a StringTokenizer to tokenize the property name.
315
StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(name, ".");
316         int i = 0;
317         while (tokenizer.hasMoreTokens()) {
318             propName[i] = tokenizer.nextToken();
319             i++;
320         }
321         return propName;
322     }
323 }
324
Popular Tags