KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > definition > XmlParser


1 /**************************************************************************************
2  * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
3  * http://aspectwerkz.codehaus.org *
4  * ---------------------------------------------------------------------------------- *
5  * The software in this package is published under the terms of the LGPL license *
6  * a copy of which has been included with this distribution in the license.txt file. *
7  **************************************************************************************/

8 package org.codehaus.aspectwerkz.definition;
9
10 import org.codehaus.aspectwerkz.exception.DefinitionException;
11 import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
12 import org.dom4j.Document;
13 import org.dom4j.DocumentException;
14 import org.dom4j.Element;
15 import org.dom4j.DocumentHelper;
16 import org.dom4j.io.SAXReader;
17 import org.xml.sax.EntityResolver JavaDoc;
18 import org.xml.sax.InputSource JavaDoc;
19
20 import java.io.File JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.io.InputStream JavaDoc;
23 import java.io.FileInputStream JavaDoc;
24 import java.io.BufferedInputStream JavaDoc;
25 import java.net.MalformedURLException JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Set JavaDoc;
30
31 /**
32  * Parses the XML definition file using <tt>dom4j</tt>.
33  *
34  * @author <a HREF="mailto:jboner@codehaus.org">Jonas Bonér </a>
35  */

36 public class XmlParser {
37     /**
38      * The current DTD public id. The matching dtd will be searched as a resource.
39      */

40     private final static String JavaDoc DTD_PUBLIC_ID = "-//AspectWerkz//DTD 2.0//EN";
41
42     /**
43      * The DTD alias, for better user experience.
44      */

45     private final static String JavaDoc DTD_PUBLIC_ID_ALIAS = "-//AspectWerkz//DTD//EN";
46
47     /**
48      * A handler to the DTD stream so that we are only using one file descriptor
49      */

50     private final static InputStream JavaDoc DTD_STREAM = XmlParser.class.getResourceAsStream("/aspectwerkz2.dtd");
51
52     /**
53      * The timestamp, holding the last time that the definition was parsed.
54      */

55     private static File JavaDoc s_timestamp = new File JavaDoc(".timestamp");
56
57     /**
58      * The AspectWerkz definitions.
59      */

60     private static Set JavaDoc s_definitions = null;
61
62 // /**
63
// * Returns the aspect class names defined in the XML file.
64
// *
65
// * @param definitionFile the definition file
66
// * @return the definitions
67
// */
68
// public static List getAspectClassNames(final File definitionFile) {
69
// if (definitionFile == null) {
70
// throw new IllegalArgumentException("definition file can not be null");
71
// }
72
// if (!definitionFile.exists()) {
73
// throw new DefinitionException("definition file " + definitionFile.toString() + " does not exist");
74
// }
75
// try {
76
// return getAspectClassNames(definitionFile.toURL());
77
// } catch (MalformedURLException e) {
78
// throw new DefinitionException(definitionFile + " does not exist");
79
// }
80
// }
81

82 // /**
83
// * Returns the aspect class names defined in the XML file.
84
// *
85
// * @param definitionURL the definition URL
86
// * @return the definitions
87
// */
88
// public static List getAspectClassNames(final URL definitionURL) {
89
// if (definitionURL == null) {
90
// throw new IllegalArgumentException("definition file can not be null");
91
// }
92
// try {
93
// Document document = createDocument(definitionURL);
94
// return DocumentParser.parseAspectClassNames(document);
95
// } catch (DocumentException e) {
96
// throw new DefinitionException("XML definition file <" + definitionURL + "> has errors: " + e.toString());
97
// }
98
// }
99

100 // /**
101
// * Returns the aspect class names defined in the XML file.
102
// *
103
// * @param stream the input stream containing the document
104
// * @return the definitions
105
// */
106
// public static List getAspectClassNames(final InputStream stream) {
107
// try {
108
// Document document = createDocument(stream);
109
// return DocumentParser.parseAspectClassNames(document);
110
// } catch (DocumentException e) {
111
// throw new DefinitionException("XML definition file on classpath has errors: " + e.toString());
112
// }
113
// }
114

115 // /**
116
// * Parses the XML definition file, only if it has been updated. Uses a timestamp to check for modifications.
117
// *
118
// * @param loader the current class loader
119
// * @param definitionFile the definition file
120
// * @param isDirty flag to mark the the definition as updated or not
121
// * @return the definitions
122
// */
123
// public static Set parse(final ClassLoader loader, final File definitionFile, boolean isDirty) {
124
// if (definitionFile == null) {
125
// throw new IllegalArgumentException("definition file can not be null");
126
// }
127
// if (!definitionFile.exists()) {
128
// throw new DefinitionException("definition file " + definitionFile.toString() + " does not exist");
129
// }
130
//
131
// // if definition is not updated; don't parse but return it right away
132
// if (isNotUpdated(definitionFile)) {
133
// isDirty = false;
134
// return s_definitions;
135
// }
136
//
137
// // updated definition, ready to be parsed
138
// try {
139
// Document document = createDocument(definitionFile.toURL());
140
// s_definitions = DocumentParser.parse(loader, document);
141
// setParsingTimestamp();
142
// isDirty = true;
143
// return s_definitions;
144
// } catch (MalformedURLException e) {
145
// throw new DefinitionException(definitionFile + " does not exist");
146
// } catch (DocumentException e) {
147
// throw new DefinitionException("XML definition file <" + definitionFile + "> has errors: " + e.toString());
148
// }
149
// }
150

151 // /**
152
// * Parses the XML definition file retrieved from an input stream.
153
// *
154
// * @param loader the current class loader
155
// * @param stream the input stream containing the document
156
// * @return the definitions
157
// */
158
// public static Set parse(final ClassLoader loader, final InputStream stream) {
159
// try {
160
// Document document = createDocument(stream);
161
// s_definitions = DocumentParser.parse(loader, document);
162
// return s_definitions;
163
// } catch (DocumentException e) {
164
// throw new DefinitionException("XML definition file on classpath has errors: " + e.getMessage());
165
// }
166
// }
167

168     /**
169      * Parses the XML definition file not using the cache.
170      *
171      * @param loader the current class loader
172      * @param url the URL to the definition file
173      * @return the definition object
174      */

175     public static Set JavaDoc parseNoCache(final ClassLoader JavaDoc loader, final URL JavaDoc url) {
176         try {
177             Document document = createDocument(url);
178             s_definitions = DocumentParser.parse(loader, document);
179             return s_definitions;
180         } catch (Exception JavaDoc e) {
181             throw new WrappedRuntimeException(e);
182         }
183     }
184
185     /**
186      * Merges two DOM documents.
187      *
188      * @param document1 the first document
189      * @param document2 the second document
190      * @return the definition merged document
191      */

192     public static Document mergeDocuments(final Document document1, final Document document2) {
193         if ((document2 == null) && (document1 != null)) {
194             return document1;
195         }
196         if ((document1 == null) && (document2 != null)) {
197             return document2;
198         }
199         if ((document1 == null) && (document2 == null)) {
200             return null;
201         }
202         try {
203             Element root1 = document1.getRootElement();
204             Element root2 = document2.getRootElement();
205             for (Iterator JavaDoc it1 = root2.elementIterator(); it1.hasNext();) {
206                 Element element = (Element) it1.next();
207                 element.setParent(null);
208                 root1.add(element);
209             }
210         } catch (Exception JavaDoc e) {
211             throw new WrappedRuntimeException(e);
212         }
213         return document1;
214     }
215
216     /**
217      * Creates a DOM document.
218      *
219      * @param url the URL to the file containing the XML
220      * @return the DOM document
221      * @throws DocumentException
222      */

223     public static Document createDocument(final URL JavaDoc url) throws DocumentException {
224         SAXReader reader = new SAXReader();
225         setEntityResolver(reader);
226         InputStream JavaDoc in = null;
227         try {
228             in = url.openStream();
229             return reader.read(in);
230         } catch (IOException JavaDoc e) {
231             throw new DocumentException(e);
232         } finally {
233             try {in.close();} catch (Throwable JavaDoc t) {;}
234         }
235     }
236
237 // /**
238
// * Creates a DOM document.
239
// *
240
// * @param stream the stream containing the XML
241
// * @return the DOM document
242
// * @throws DocumentException
243
// */
244
// public static Document createDocument(final InputStream stream) throws DocumentException {
245
// SAXReader reader = new SAXReader();
246
// setEntityResolver(reader);
247
// return reader.read(stream);
248
// }
249

250     /**
251      * Creates a DOM document.
252      *
253      * @param string the string containing the XML
254      * @return the DOM document
255      * @throws DocumentException
256      */

257     public static Document createDocument(final String JavaDoc string) throws DocumentException {
258         return DocumentHelper.parseText(string);
259     }
260
261     /**
262      * Sets the entity resolver which is created based on the DTD from in the root dir of the AspectWerkz distribution.
263      *
264      * @param reader the reader to set the resolver in
265      */

266     private static void setEntityResolver(final SAXReader reader) {
267         EntityResolver JavaDoc resolver = new EntityResolver JavaDoc() {
268             public InputSource JavaDoc resolveEntity(String JavaDoc publicId, String JavaDoc systemId) {
269                 if (publicId.equals(DTD_PUBLIC_ID) || publicId.equals(DTD_PUBLIC_ID_ALIAS)) {
270                     InputStream JavaDoc in = DTD_STREAM;
271                     if (in == null) {
272                         System.err.println("AspectWerkz - WARN - could not open DTD");
273                         return new InputSource JavaDoc();
274                     } else {
275                         return new InputSource JavaDoc(in);
276                     }
277                 } else {
278                     System.err.println(
279                             "AspectWerkz - WARN - deprecated DTD "
280                             + publicId
281                             + " - consider upgrading to "
282                             + DTD_PUBLIC_ID
283                     );
284                     return new InputSource JavaDoc(); // avoid null pointer exception
285
}
286             }
287         };
288         reader.setEntityResolver(resolver);
289     }
290
291     /**
292      * Checks if the definition file has been updated since the last parsing.
293      *
294      * @param definitionFile the definition file
295      * @return boolean
296      */

297     private static boolean isNotUpdated(final File JavaDoc definitionFile) {
298         return (definitionFile.lastModified() < getParsingTimestamp()) && (s_definitions != null);
299     }
300
301     /**
302      * Sets the timestamp for the latest parsing of the definition file.
303      */

304     private static void setParsingTimestamp() {
305         final long newModifiedTime = System.currentTimeMillis();
306         s_timestamp.setLastModified(newModifiedTime);
307     }
308
309     /**
310      * Returns the timestamp for the last parsing of the definition file.
311      *
312      * @return the timestamp
313      */

314     private static long getParsingTimestamp() {
315         final long modifiedTime = s_timestamp.lastModified();
316         if (modifiedTime == 0L) {
317             // no timestamp, create a new one
318
try {
319                 s_timestamp.createNewFile();
320             } catch (IOException JavaDoc e) {
321                 throw new RuntimeException JavaDoc("could not create timestamp file: " + s_timestamp.getAbsolutePath());
322             }
323         }
324         return modifiedTime;
325     }
326 }
Popular Tags