KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > XmlParserImpl


1 /*
2  * XmlParserImpl.java
3  *
4  * Copyright (C) 2000-2003 Peter Graves
5  * $Id: XmlParserImpl.java,v 1.7 2003/06/25 18:30:58 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j;
23
24 import java.io.FileInputStream JavaDoc;
25 import java.io.FileNotFoundException JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.io.Reader JavaDoc;
29 import java.util.Stack JavaDoc;
30 import javax.swing.tree.DefaultMutableTreeNode JavaDoc;
31 import javax.swing.tree.DefaultTreeModel JavaDoc;
32 import javax.swing.tree.TreeModel JavaDoc;
33 import org.xml.sax.Attributes JavaDoc;
34 import org.xml.sax.ContentHandler JavaDoc;
35 import org.xml.sax.EntityResolver JavaDoc;
36 import org.xml.sax.InputSource JavaDoc;
37 import org.xml.sax.Locator JavaDoc;
38 import org.xml.sax.SAXException JavaDoc;
39 import org.xml.sax.SAXNotRecognizedException JavaDoc;
40 import org.xml.sax.SAXNotSupportedException JavaDoc;
41 import org.xml.sax.SAXParseException JavaDoc;
42 import org.xml.sax.XMLReader JavaDoc;
43 import org.xml.sax.helpers.DefaultHandler JavaDoc;
44 import org.xml.sax.helpers.XMLReaderFactory JavaDoc;
45
46 public final class XmlParserImpl extends DefaultHandler JavaDoc implements Runnable JavaDoc,
47     ContentHandler JavaDoc, EntityResolver JavaDoc
48 {
49     private static final String JavaDoc VALIDATION =
50         "http://xml.org/sax/features/validation";
51
52     private String JavaDoc parserClassName;
53     private boolean aelfred;
54     private final Buffer buffer;
55     private Reader JavaDoc reader;
56     private XMLReader JavaDoc xmlReader;
57     private TreeModel JavaDoc treeModel;
58     private Stack JavaDoc stack;
59     private Exception JavaDoc exception;
60     private DefaultMutableTreeNode JavaDoc current;
61     private Locator JavaDoc locator;
62     private FastStringBuffer output;
63
64     public XmlParserImpl(Buffer buffer)
65     {
66         Debug.assertTrue(buffer != null);
67         this.buffer = buffer;
68     }
69
70     public boolean initialize()
71     {
72         String JavaDoc className =
73             Editor.preferences().getStringProperty("org.xml.sax.driver");
74         if (className == null)
75             className = System.getProperty("org.xml.sax.driver");
76         if (className != null) {
77             try {
78                 xmlReader = XMLReaderFactory.createXMLReader(className);
79             }
80             catch (Exception JavaDoc e) {
81                 Log.debug(e);
82             }
83         }
84         if (xmlReader == null)
85             xmlReader = Utilities.getDefaultXMLReader();
86         if (xmlReader == null) {
87             parserClassName = null;
88             aelfred = false;
89             Log.error("no parser found");
90         } else {
91             parserClassName = xmlReader.getClass().getName();
92             if (parserClassName.equals("org.armedbear.j.aelfred.SAXDriver"))
93                 aelfred = true;
94             else
95                 aelfred = false;
96         }
97         return xmlReader != null;
98     }
99
100     public String JavaDoc getParserClassName()
101     {
102         return parserClassName;
103     }
104
105     public void setReader(Reader JavaDoc reader)
106     {
107         this.reader = reader;
108     }
109
110     public boolean enableValidation(boolean enable)
111     {
112         if (xmlReader == null) {
113             Debug.bug();
114             return false;
115         }
116         try {
117             xmlReader.setFeature(VALIDATION, enable);
118         }
119         catch (SAXNotRecognizedException JavaDoc e) {
120             Log.error(e);
121             return false;
122         }
123         catch (SAXNotSupportedException JavaDoc e) {
124             Log.error(e);
125             return false;
126         }
127         return true;
128     }
129
130     private boolean isValidating()
131     {
132         if (xmlReader == null) {
133             Debug.bug();
134             return false;
135         }
136         try {
137             return xmlReader.getFeature(VALIDATION);
138         }
139         catch (SAXNotRecognizedException JavaDoc e) {}
140         catch (SAXNotSupportedException JavaDoc e) {}
141         return false;
142     }
143
144     public Exception JavaDoc getException()
145     {
146         return exception;
147     }
148
149     public String JavaDoc getOutput()
150     {
151         return output != null ? output.toString() : "";
152     }
153
154     public void run()
155     {
156         if (xmlReader == null) {
157             Debug.bug();
158             initialize();
159         }
160
161         if (xmlReader == null) {
162             Log.error("no XML reader available");
163             return;
164         }
165
166         exception = null;
167         output = new FastStringBuffer();
168
169         final boolean validating = isValidating();
170
171         output.append("Using ");
172         output.append(xmlReader.getClass().getName());
173         output.append(" (");
174         if (!validating)
175             output.append("not ");
176         output.append("validating)\n");
177
178         // Parser must be associated with a buffer.
179
if (buffer == null) {
180             Debug.bug();
181             return;
182         }
183
184         InputSource JavaDoc inputSource = null;
185         final File file = buffer.getFile();
186         if (reader != null) {
187             inputSource = new InputSource JavaDoc(reader);
188         } else if (file != null) {
189             try {
190                 InputStream JavaDoc inputStream = file.getInputStream();
191                 if (inputStream != null) {
192                     inputSource = new InputSource JavaDoc(inputStream);
193                     String JavaDoc encoding = file.getEncoding();
194                     if (encoding != null) {
195                         inputSource.setEncoding(encoding);
196                         Log.debug("parser encoding is " + encoding);
197                     }
198                 }
199             }
200             catch (IOException JavaDoc e) {
201                 Log.error(e);
202             }
203         }
204         if (inputSource == null)
205             return;
206         if (file != null) {
207             if (file.isRemote())
208                 inputSource.setSystemId(file.netPath());
209             else
210                 inputSource.setSystemId("file://".concat(file.canonicalPath()));
211         }
212         treeModel = null;
213         stack = new Stack JavaDoc();
214
215         if (xmlReader != null) {
216             xmlReader.setContentHandler(this);
217             xmlReader.setErrorHandler(this);
218             xmlReader.setEntityResolver(this);
219             long start = System.currentTimeMillis();
220             try {
221                 xmlReader.parse(inputSource);
222             }
223             catch (Exception JavaDoc e) {
224                 exception = e;
225             }
226             long elapsed = System.currentTimeMillis() - start;
227             output.append('\n');
228             output.append(validating ? "Validation" : "Parsing");
229             output.append(" finished (");
230             output.append(elapsed);
231             output.append(" ms)");
232         }
233     }
234
235     public InputSource JavaDoc resolveEntity(String JavaDoc publicId, String JavaDoc systemId)
236     {
237         if (systemId == null)
238             return null;
239         if (Platform.isPlatformWindows() && systemId.startsWith("file://")) {
240             // Strip "file://" prefix.
241
String JavaDoc filename = systemId.substring(7);
242             // Make sure there's a colon after the drive letter.
243
if (filename.length() > 2 && filename.charAt(1) == '/')
244                 filename = filename.substring(0, 1) + ':' + filename.substring(1);
245             // Make sure the slashes are pointing the right way.
246
filename = File.normalize(filename);
247             try {
248                 return new InputSource JavaDoc(new FileInputStream JavaDoc(filename));
249             }
250             catch (FileNotFoundException JavaDoc e) {}
251             // FileNotFoundException was thrown.
252
if (filename.length() > 3 && filename.charAt(1) == ':'
253                 && filename.charAt(2) == '\\') {
254                 // Try relative to buffer's directory.
255
File file = File.getInstance(buffer.getFile().getParentFile(),
256                     filename.substring(3));
257                 try {
258                     return new InputSource JavaDoc(new FileInputStream JavaDoc(file.canonicalPath()));
259                 }
260                 catch (Exception JavaDoc e) {}
261             }
262         }
263         if (aelfred) {
264             // There's no way to tell aelfred about new system identifiers, so
265
// URLs relative to the new entity won't be resolved correctly if
266
// we return an input stream here. Don't use caching if we're
267
// using aelfred!
268
Log.debug("using aelfred - cache not supported");
269             return null;
270         }
271         if (!buffer.getBooleanProperty(Property.ENABLE_CACHE)) {
272             Log.debug("cache disabled");
273             return null;
274         }
275         if (systemId.startsWith("http://")) {
276             Cache cache = Cache.getCache();
277             if (cache != null) {
278                 Log.debug("checking cache for ".concat(systemId));
279                 File file = cache.get(systemId);
280                 if (file == null) {
281                     Log.debug("caching ".concat(systemId));
282                     file = cache.put(systemId);
283                 }
284                 if (file != null) {
285                     try {
286                         Log.debug("returning input stream from cache");
287                         InputSource JavaDoc inputSource =
288                             new InputSource JavaDoc(file.getInputStream());
289                         inputSource.setSystemId(systemId);
290                         return inputSource;
291                     }
292                     catch (Exception JavaDoc e) {
293                         Log.error(e);
294                     }
295                 }
296             }
297         }
298         return null;
299     }
300
301     public void setDocumentLocator(Locator JavaDoc locator)
302     {
303         this.locator = locator;
304     }
305
306     public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName,
307         Attributes JavaDoc attributes) throws SAXException JavaDoc
308     {
309         int lineNumber = 0;
310         int columnNumber = 0;
311         if (locator != null) {
312             lineNumber = locator.getLineNumber();
313             columnNumber = locator.getColumnNumber();
314         }
315         DefaultMutableTreeNode JavaDoc node =
316             new DefaultMutableTreeNode JavaDoc(new XmlTreeElement(localName,
317                 attributes, lineNumber, columnNumber));
318         if (treeModel == null) {
319             treeModel = new DefaultTreeModel JavaDoc(node);
320         } else {
321             Debug.assertTrue(current != null);
322             current.insert(node, current.getChildCount());
323             stack.push(current);
324         }
325         current = node;
326     }
327
328     public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName)
329     {
330         if (stack.empty())
331             current = null;
332         else
333             current = (DefaultMutableTreeNode JavaDoc) stack.pop();
334     }
335
336     public void warning(SAXParseException JavaDoc e)
337     throws SAXException JavaDoc
338     {
339         appendMessage("Warning", e);
340     }
341
342     public void error(SAXParseException JavaDoc e)
343     throws SAXException JavaDoc
344     {
345         appendMessage("Error", e);
346     }
347
348     public void fatalError(SAXParseException JavaDoc e)
349     throws SAXException JavaDoc
350     {
351         appendMessage("Fatal error", e);
352     }
353
354     private void appendMessage(String JavaDoc what, SAXParseException JavaDoc e)
355     {
356         FastStringBuffer sb = new FastStringBuffer();
357         final String JavaDoc systemId = e.getSystemId();
358         final int lineNumber = e.getLineNumber();
359         if (systemId.startsWith("file://")) {
360             sb.append(systemId.substring(7));
361             sb.append(':');
362             sb.append(lineNumber);
363         } else if (systemId.startsWith("file:")) {
364             sb.append(systemId.substring(5));
365             sb.append(':');
366             sb.append(lineNumber);
367         } else {
368             sb.append(systemId);
369             sb.append(" line ");
370             sb.append(lineNumber);
371         }
372         sb.append(": ");
373         sb.append(what);
374         sb.append(": ");
375         sb.append(e.getMessage());
376         sb.append('\n');
377         output.append(sb.toString());
378     }
379
380     public TreeModel JavaDoc getTreeModel()
381     {
382         return treeModel;
383     }
384 }
385
Popular Tags