2 * Copyright (C) 2001, 2002 The Mir-coders group
\r
4 * This file is part of Mir.
\r
6 * Mir is free software; you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation; either version 2 of the License, or
\r
9 * (at your option) any later version.
\r
11 * Mir is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with Mir; if not, write to the Free Software
\r
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 * In addition, as a special exception, The Mir-coders gives permission to link
\r
21 * the code of this program with any library licensed under the Apache Software License,
\r
22 * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
\r
23 * (or with modified versions of the above that use the same license as the above),
\r
24 * and distribute linked combinations including the two. You must obey the
\r
25 * GNU General Public License in all respects for all of the code used other than
\r
26 * the above mentioned libraries. If you modify this file, you may extend this
\r
27 * exception to your version of the file, but you are not obligated to do so.
\r
28 * If you do not wish to do so, delete this exception statement from your version.
\r
32 import java.io.FileInputStream;
\r
33 import java.io.InputStream;
\r
34 import java.io.StringReader;
\r
35 import java.util.HashMap;
\r
36 import java.util.Map;
\r
37 import java.util.Stack;
\r
38 import javax.xml.parsers.ParserConfigurationException;
\r
39 import javax.xml.parsers.SAXParser;
\r
40 import javax.xml.parsers.SAXParserFactory;
\r
42 import org.ccil.cowan.tagsoup.Parser;
\r
43 import org.xml.sax.Attributes;
\r
44 import org.xml.sax.InputSource;
\r
45 import org.xml.sax.Locator;
\r
46 import org.xml.sax.SAXException;
\r
47 import org.xml.sax.SAXParseException;
\r
48 import org.xml.sax.helpers.DefaultHandler;
\r
50 import multex.Failure;
\r
52 public class XMLReader {
\r
53 private Locator locator;
\r
54 private String filename;
\r
55 private boolean namespaceAware;
\r
57 public XMLReader() {
\r
61 public XMLReader(boolean aNameSpaceAware) {
\r
62 namespaceAware = aNameSpaceAware;
\r
66 public void parseString(String aString, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
\r
68 parseInputSource(new InputSource(new StringReader(aString)), aRootHandler);
\r
70 catch (Throwable t) {
\r
71 throw new XMLReaderFailure(t);
\r
75 public void parseString(boolean aTagSoup, String aString, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
\r
77 parseInputSource(aTagSoup, new InputSource(new StringReader(aString)), aRootHandler);
\r
79 catch (Throwable t) {
\r
80 throw new XMLReaderFailure(t);
\r
84 public void parseFile(String aFileName, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
\r
85 filename= aFileName;
\r
87 parseInputStream(new FileInputStream(aFileName), aRootHandler);
\r
89 catch (Throwable t) {
\r
90 throw new XMLReaderFailure(t);
\r
94 public void parseInputStream(InputStream anInputStream, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
\r
95 parseInputSource(new InputSource(anInputStream), aRootHandler);
\r
98 public void parseInputStream(boolean aTagSoup, InputStream anInputStream, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
\r
99 parseInputSource(aTagSoup, new InputSource(anInputStream), aRootHandler);
\r
102 public void parseInputSource(InputSource anInputSource, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
\r
104 parseInputSource(false, anInputSource, aRootHandler);
\r
106 catch (Throwable e) {
\r
107 Throwable t = ExceptionFunctions.traceCauseException(e);
\r
109 if (t instanceof XMLReaderExc) {
\r
110 throw (XMLReaderExc) t;
\r
113 if (t instanceof XMLReaderFailure) {
\r
114 throw (XMLReaderFailure) t;
\r
117 throw new XMLReaderFailure(t);
\r
121 public void parseInputSource(boolean aTagSoup, InputSource anInputSource, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
\r
123 XMLReaderHandler handler = new XMLReaderHandler(aRootHandler);
\r
126 org.ccil.cowan.tagsoup.Parser parser = new Parser();
\r
127 parser.setContentHandler(handler);
\r
128 parser.setDTDHandler(handler);
\r
129 parser.parse(anInputSource);
\r
132 SAXParserFactory parserFactory = SAXParserFactory.newInstance();
\r
134 parserFactory.setNamespaceAware(true);
\r
135 parserFactory.setValidating(true);
\r
136 SAXParser parser = parserFactory.newSAXParser();
\r
138 parser.parse(anInputSource, handler);
\r
141 catch (Throwable e) {
\r
142 Throwable t = ExceptionFunctions.traceCauseException(e);
\r
144 if (t instanceof XMLReaderExc) {
\r
145 throw (XMLReaderExc) t;
\r
148 if (t instanceof XMLReaderFailure) {
\r
149 throw (XMLReaderFailure) t;
\r
152 if (t instanceof XMLReaderExc) {
\r
153 if (locator!=null && filename!=null)
\r
154 ((XMLReaderExc) t).setLocation(filename, locator.getLineNumber(), locator.getColumnNumber());
\r
155 throw (XMLReaderExc) t;
\r
158 if (t instanceof SAXParseException) {
\r
159 XMLReaderExc r = new XMLReaderExc(t.getMessage());
\r
161 if (locator!=null && filename!=null)
\r
162 r.setLocation(filename, locator.getLineNumber(), locator.getColumnNumber());
\r
167 if (t instanceof XMLReaderFailure) {
\r
168 throw (XMLReaderFailure) t;
\r
171 if (t instanceof ParserConfigurationException) {
\r
172 throw new XMLReaderFailure("Internal exception: "+t.toString(), t);
\r
175 throw new XMLReaderFailure(t);
\r
178 private class XMLReaderHandler extends DefaultHandler {
\r
179 private SectionsManager manager;
\r
181 public XMLReaderHandler(SectionHandler aRootHandler) {
\r
184 manager = new SectionsManager();
\r
185 manager.pushHandler(aRootHandler);
\r
188 public void setDocumentLocator(Locator aLocator) {
\r
192 public void startElement(String aUri, String aLocalName, String aQualifiedName, Attributes anAttributes) throws SAXException {
\r
197 attributesMap = new HashMap();
\r
199 if (namespaceAware)
\r
200 for (i=0; i<anAttributes.getLength(); i++)
\r
201 attributesMap.put(new XMLName(anAttributes.getURI(i), XMLReaderTool.getNameSpaceFromQualifiedName(anAttributes.getQName(i)), anAttributes.getLocalName(i)), anAttributes.getValue(i));
\r
203 for (i=0; i<anAttributes.getLength(); i++)
\r
204 attributesMap.put(anAttributes.getLocalName(i), anAttributes.getValue(i));
\r
206 SectionHandler handler = manager.currentHandler().startElement(new XMLName(aUri, XMLReaderTool.getNameSpaceFromQualifiedName(aQualifiedName), aLocalName), attributesMap);
\r
208 manager.pushHandler( handler );
\r
210 catch (XMLReaderExc e) {
\r
211 throw new SAXParseException(e.getMessage(), null, e);
\r
213 catch (Exception e) {
\r
214 throw new SAXException(e);
\r
218 public void endElement(String aUri, String aLocalName, String aQualifiedName) throws SAXException {
\r
221 SectionHandler handler = manager.popHandler();
\r
223 handler.finishSection();
\r
225 if (!manager.isEmpty()) {
\r
226 manager.currentHandler().endElement(handler);
\r
229 catch (XMLReaderExc e) {
\r
230 throw new SAXParseException(e.getMessage(), null, e);
\r
232 catch (Exception e) {
\r
233 throw new SAXException(e);
\r
237 public void endDocument() throws SAXException {
\r
240 SectionHandler handler = manager.popHandler();
\r
242 handler.finishSection();
\r
244 catch (XMLReaderExc e) {
\r
245 throw new SAXParseException(e.getMessage(), null, e);
\r
247 catch (Exception e) {
\r
248 throw new SAXException(e);
\r
252 public void characters(char[] aBuffer, int aStart, int anEnd) throws SAXException {
\r
254 String text = new String(aBuffer, aStart, anEnd);
\r
256 manager.currentHandler().characters(text);
\r
258 catch (XMLReaderExc e) {
\r
259 throw new SAXParseException(e.getMessage(), null, e);
\r
261 catch (Exception e) {
\r
262 throw new SAXException(e);
\r
267 private class SectionsManager {
\r
268 Stack handlerStack;
\r
270 public SectionsManager() {
\r
271 handlerStack = new Stack();
\r
274 public void pushHandler(SectionHandler aSectionHandler) {
\r
275 handlerStack.push(aSectionHandler);
\r
278 public SectionHandler popHandler() {
\r
279 return (SectionHandler) handlerStack.pop();
\r
282 public SectionHandler currentHandler() {
\r
283 return (SectionHandler) handlerStack.peek();
\r
286 public boolean isEmpty() {
\r
287 return handlerStack.isEmpty();
\r
291 public static interface SectionHandler {
\r
292 public abstract SectionHandler startElement(XMLName aTag, Map anAttributes) throws XMLReaderExc;
\r
294 public abstract void endElement(SectionHandler aHandler) throws XMLReaderExc;
\r
296 public void characters(String aCharacters) throws XMLReaderExc;
\r
298 public void finishSection() throws XMLReaderExc;
\r
301 public static abstract class AbstractSectionHandler implements SectionHandler {
\r
302 public SectionHandler startElement(XMLName aTag, Map anAttributes) throws XMLReaderExc {
\r
303 return startElement(aTag.getLocalName(), anAttributes);
\r
306 public SectionHandler startElement(String aLocalName, Map anAttributes) throws XMLReaderExc {
\r
310 public void endElement(SectionHandler aHandler) throws XMLReaderExc {
\r
313 public void finishSection() throws XMLReaderExc {
\r
316 public void characters(String aCharacters) throws XMLReaderExc {
\r
317 if ( aCharacters.trim().length() > 0) {
\r
318 throw new XMLReaderExc("Text not allowed");
\r
323 public static class XMLReaderExc extends Exc {
\r
324 private boolean hasLocation;
\r
325 private String filename;
\r
326 private int lineNr;
\r
327 private int columnNr;
\r
329 public XMLReaderExc(String aMessage) {
\r
331 hasLocation = false;
\r
334 protected void setLocation(String aFilename, int aLineNr, int aColumnNr) {
\r
335 filename = aFilename;
\r
337 columnNr = aColumnNr;
\r
338 hasLocation = true;
\r
341 public boolean getHasLocation() {
\r
342 return hasLocation;
\r
345 public int getLineNr() {
\r
349 public int getColumnNr() {
\r
353 public String getFilename() {
\r
358 public static class XMLReaderFailure extends Failure {
\r
359 public XMLReaderFailure(String aMessage, Throwable aCause) {
\r
360 super(aMessage, aCause);
\r
363 public XMLReaderFailure(Throwable aCause) {
\r
364 super(aCause.getMessage(), aCause);
\r
368 public static class XMLName {
\r
369 private String namespaceURI;
\r
370 private String localName;
\r
371 private String prefix;
\r
373 public XMLName(String aLocalName) {
\r
374 this(null, null, aLocalName);
\r
377 public XMLName(String aNamespaceURI, String aPrefix, String aLocalName) {
\r
382 if (aLocalName!=null)
\r
383 localName = aLocalName;
\r
386 if (aNamespaceURI!=null)
\r
387 namespaceURI = aNamespaceURI;
\r
390 public XMLName(String aNamespaceURI, String aLocalName) {
\r
391 this (aNamespaceURI, null, aLocalName);
\r
394 public String getNamespaceURI() {
\r
395 return namespaceURI;
\r
398 public String getLocalName() {
\r
402 public String getPrefix() {
\r
406 public int hashCode() {
\r
407 if (namespaceURI == null)
\r
408 return localName.hashCode() + 3*prefix.hashCode();
\r
410 return localName.hashCode() + 3*namespaceURI.hashCode();
\r
413 public String toString() {
\r
414 return ((namespaceURI.length()>0)? "["+namespaceURI+"]":"")+((prefix.length()>0)?prefix+":":"")+localName;
\r
417 public boolean equals(Object anObject) {
\r
418 if (anObject instanceof XMLName) {
\r
419 if (namespaceURI==null)
\r
420 return (((XMLName) anObject).namespaceURI == null) &&
\r
421 prefix.equals(((XMLName) anObject).prefix) &&
\r
422 localName.equals(((XMLName) anObject).localName);
\r
424 return namespaceURI.equals(((XMLName) anObject).namespaceURI) &&
\r
425 localName.equals(((XMLName) anObject).localName);
\r