2 * Copyright (C) 2001, 2002 The Mir-coders group
4 * This file is part of Mir.
6 * Mir is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Mir is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Mir; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * In addition, as a special exception, The Mir-coders gives permission to link
21 * the code of this program with any library licensed under the Apache Software License,
22 * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23 * (or with modified versions of the above that use the same license as the above),
24 * and distribute linked combinations including the two. You must obey the
25 * GNU General Public License in all respects for all of the code used other than
26 * the above mentioned libraries. If you modify this file, you may extend this
27 * exception to your version of the file, but you are not obligated to do so.
28 * If you do not wish to do so, delete this exception statement from your version.
32 import java.io.BufferedInputStream;
33 import java.io.FileInputStream;
34 import java.io.InputStream;
35 import java.io.StringReader;
36 import java.util.HashMap;
38 import java.util.Stack;
39 import javax.xml.parsers.ParserConfigurationException;
40 import javax.xml.parsers.SAXParser;
41 import javax.xml.parsers.SAXParserFactory;
43 import org.ccil.cowan.tagsoup.Parser;
44 import org.xml.sax.Attributes;
45 import org.xml.sax.InputSource;
46 import org.xml.sax.Locator;
47 import org.xml.sax.SAXException;
48 import org.xml.sax.SAXParseException;
49 import org.xml.sax.helpers.DefaultHandler;
51 import multex.Failure;
53 public class XMLReader {
54 private Locator locator;
55 private String filename;
56 private boolean namespaceAware;
62 public XMLReader(boolean aNameSpaceAware) {
63 namespaceAware = aNameSpaceAware;
67 public void parseString(String aString, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
69 parseInputSource(new InputSource(new StringReader(aString)), aRootHandler);
72 throw new XMLReaderFailure(t);
76 public void parseString(boolean aTagSoup, String aString, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
78 parseInputSource(aTagSoup, new InputSource(new StringReader(aString)), aRootHandler);
81 throw new XMLReaderFailure(t);
85 public void parseFile(String aFileName, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
88 parseInputStream(new BufferedInputStream(new FileInputStream(aFileName),8192), aRootHandler);
91 throw new XMLReaderFailure(t);
95 public void parseInputStream(InputStream anInputStream, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
96 parseInputSource(new InputSource(anInputStream), aRootHandler);
99 public void parseInputStream(boolean aTagSoup, InputStream anInputStream, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
100 parseInputSource(aTagSoup, new InputSource(anInputStream), aRootHandler);
103 public void parseInputSource(InputSource anInputSource, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
105 parseInputSource(false, anInputSource, aRootHandler);
107 catch (Throwable e) {
108 Throwable t = ExceptionFunctions.traceCauseException(e);
110 if (t instanceof XMLReaderExc) {
111 throw (XMLReaderExc) t;
114 if (t instanceof XMLReaderFailure) {
115 throw (XMLReaderFailure) t;
118 throw new XMLReaderFailure(t);
122 public void parseInputSource(boolean aTagSoup, InputSource anInputSource, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
124 XMLReaderHandler handler = new XMLReaderHandler(aRootHandler);
127 org.ccil.cowan.tagsoup.Parser parser = new Parser();
128 parser.setContentHandler(handler);
129 parser.setDTDHandler(handler);
130 parser.parse(anInputSource);
133 SAXParserFactory parserFactory = SAXParserFactory.newInstance();
135 parserFactory.setNamespaceAware(true);
136 parserFactory.setValidating(true);
137 SAXParser parser = parserFactory.newSAXParser();
139 parser.parse(anInputSource, handler);
142 catch (Throwable e) {
143 Throwable t = ExceptionFunctions.traceCauseException(e);
145 if (t instanceof XMLReaderExc) {
146 throw (XMLReaderExc) t;
149 if (t instanceof XMLReaderFailure) {
150 throw (XMLReaderFailure) t;
153 if (t instanceof XMLReaderExc) {
154 if (locator!=null && filename!=null)
155 ((XMLReaderExc) t).setLocation(filename, locator.getLineNumber(), locator.getColumnNumber());
156 throw (XMLReaderExc) t;
159 if (t instanceof SAXParseException) {
160 XMLReaderExc r = new XMLReaderExc(t.getMessage());
162 if (locator!=null && filename!=null)
163 r.setLocation(filename, locator.getLineNumber(), locator.getColumnNumber());
168 if (t instanceof XMLReaderFailure) {
169 throw (XMLReaderFailure) t;
172 if (t instanceof ParserConfigurationException) {
173 throw new XMLReaderFailure("Internal exception: "+t.toString(), t);
176 throw new XMLReaderFailure(t);
179 private class XMLReaderHandler extends DefaultHandler {
180 private SectionsManager manager;
182 public XMLReaderHandler(SectionHandler aRootHandler) {
185 manager = new SectionsManager();
186 manager.pushHandler(aRootHandler);
189 public void setDocumentLocator(Locator aLocator) {
193 public void startElement(String aUri, String aLocalName, String aQualifiedName, Attributes anAttributes) throws SAXException {
198 attributesMap = new HashMap();
201 for (i=0; i<anAttributes.getLength(); i++)
202 attributesMap.put(new XMLName(anAttributes.getURI(i), XMLReaderTool.getNameSpaceFromQualifiedName(anAttributes.getQName(i)), anAttributes.getLocalName(i)), anAttributes.getValue(i));
204 for (i=0; i<anAttributes.getLength(); i++)
205 attributesMap.put(anAttributes.getLocalName(i), anAttributes.getValue(i));
207 SectionHandler handler = manager.currentHandler().startElement(new XMLName(aUri, XMLReaderTool.getNameSpaceFromQualifiedName(aQualifiedName), aLocalName), attributesMap);
209 manager.pushHandler( handler );
211 catch (XMLReaderExc e) {
212 throw new SAXParseException(e.getMessage(), null, e);
214 catch (Exception e) {
215 throw new SAXException(e);
219 public void endElement(String aUri, String aLocalName, String aQualifiedName) throws SAXException {
222 SectionHandler handler = manager.popHandler();
224 handler.finishSection();
226 if (!manager.isEmpty()) {
227 manager.currentHandler().endElement(handler);
230 catch (XMLReaderExc e) {
231 throw new SAXParseException(e.getMessage(), null, e);
233 catch (Exception e) {
234 throw new SAXException(e);
238 public void endDocument() throws SAXException {
241 SectionHandler handler = manager.popHandler();
243 handler.finishSection();
245 catch (XMLReaderExc e) {
246 throw new SAXParseException(e.getMessage(), null, e);
248 catch (Exception e) {
249 throw new SAXException(e);
253 public void characters(char[] aBuffer, int aStart, int anEnd) throws SAXException {
255 String text = new String(aBuffer, aStart, anEnd);
257 manager.currentHandler().characters(text);
259 catch (XMLReaderExc e) {
260 throw new SAXParseException(e.getMessage(), null, e);
262 catch (Exception e) {
263 throw new SAXException(e);
268 private class SectionsManager {
271 public SectionsManager() {
272 handlerStack = new Stack();
275 public void pushHandler(SectionHandler aSectionHandler) {
276 handlerStack.push(aSectionHandler);
279 public SectionHandler popHandler() {
280 return (SectionHandler) handlerStack.pop();
283 public SectionHandler currentHandler() {
284 return (SectionHandler) handlerStack.peek();
287 public boolean isEmpty() {
288 return handlerStack.isEmpty();
292 public static interface SectionHandler {
293 public abstract SectionHandler startElement(XMLName aTag, Map anAttributes) throws XMLReaderExc;
295 public abstract void endElement(SectionHandler aHandler) throws XMLReaderExc;
297 public void characters(String aCharacters) throws XMLReaderExc;
299 public void finishSection() throws XMLReaderExc;
302 public static abstract class AbstractSectionHandler implements SectionHandler {
303 public SectionHandler startElement(XMLName aTag, Map anAttributes) throws XMLReaderExc {
304 return startElement(aTag.getLocalName(), anAttributes);
307 public SectionHandler startElement(String aLocalName, Map anAttributes) throws XMLReaderExc {
311 public void endElement(SectionHandler aHandler) throws XMLReaderExc {
314 public void finishSection() throws XMLReaderExc {
317 public void characters(String aCharacters) throws XMLReaderExc {
318 if ( aCharacters.trim().length() > 0) {
319 throw new XMLReaderExc("Text not allowed");
324 public static class XMLReaderExc extends Exc {
325 private boolean hasLocation;
326 private String filename;
328 private int columnNr;
330 public XMLReaderExc(String aMessage) {
335 protected void setLocation(String aFilename, int aLineNr, int aColumnNr) {
336 filename = aFilename;
338 columnNr = aColumnNr;
342 public boolean getHasLocation() {
346 public int getLineNr() {
350 public int getColumnNr() {
354 public String getFilename() {
359 public static class XMLReaderFailure extends Failure {
360 public XMLReaderFailure(String aMessage, Throwable aCause) {
361 super(aMessage, aCause);
364 public XMLReaderFailure(Throwable aCause) {
365 super(aCause.getMessage(), aCause);
369 public static class XMLName {
370 private String namespaceURI;
371 private String localName;
372 private String prefix;
374 public XMLName(String aLocalName) {
375 this(null, null, aLocalName);
378 public XMLName(String aNamespaceURI, String aPrefix, String aLocalName) {
383 if (aLocalName!=null)
384 localName = aLocalName;
387 if (aNamespaceURI!=null)
388 namespaceURI = aNamespaceURI;
391 public XMLName(String aNamespaceURI, String aLocalName) {
392 this (aNamespaceURI, null, aLocalName);
395 public String getNamespaceURI() {
399 public String getLocalName() {
403 public String getPrefix() {
407 public int hashCode() {
408 if (namespaceURI == null)
409 return localName.hashCode() + 3*prefix.hashCode();
411 return localName.hashCode() + 3*namespaceURI.hashCode();
414 public String toString() {
415 return ((namespaceURI.length()>0)? "["+namespaceURI+"]":"")+((prefix.length()>0)?prefix+":":"")+localName;
418 public boolean equals(Object anObject) {
419 if (anObject instanceof XMLName) {
420 if (namespaceURI==null)
421 return (((XMLName) anObject).namespaceURI == null) &&
422 prefix.equals(((XMLName) anObject).prefix) &&
423 localName.equals(((XMLName) anObject).localName);
425 return namespaceURI.equals(((XMLName) anObject).namespaceURI) &&
426 localName.equals(((XMLName) anObject).localName);