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.
33 import java.io.InputStream;
34 import java.util.HashMap;
36 import java.util.Stack;
38 import javax.xml.parsers.ParserConfigurationException;
39 import javax.xml.parsers.SAXParser;
40 import javax.xml.parsers.SAXParserFactory;
43 import multex.Failure;
45 import org.xml.sax.Attributes;
46 import org.xml.sax.InputSource;
47 import org.xml.sax.Locator;
48 import org.xml.sax.SAXException;
49 import org.xml.sax.SAXParseException;
50 import org.xml.sax.helpers.DefaultHandler;
52 public class XMLReader {
53 private Locator locator;
54 private String filename;
55 private boolean namespaceAware;
61 public XMLReader(boolean aNameSpaceAware) {
62 namespaceAware = aNameSpaceAware;
66 public void parseString(String aString, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
68 parseInputSource(new InputSource(new StringReader(aString)), aRootHandler);
71 throw new XMLReaderFailure(t);
75 public void parseFile(String aFileName, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
78 parseInputStream(new FileInputStream(aFileName), aRootHandler);
81 throw new XMLReaderFailure(t);
85 public void parseInputStream(InputStream anInputStream, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
86 parseInputSource(new InputSource(anInputStream), aRootHandler);
89 public void parseInputSource(InputSource anInputSource, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {
91 SAXParserFactory parserFactory = SAXParserFactory.newInstance();
93 parserFactory.setNamespaceAware(true);
94 parserFactory.setValidating(true);
96 XMLReaderHandler handler = new XMLReaderHandler(parserFactory, aRootHandler);
98 handler.processInputSource(anInputSource);
100 catch (Throwable e) {
101 Throwable t = ExceptionFunctions.traceCauseException(e);
103 if (t instanceof XMLReaderExc) {
104 throw (XMLReaderExc) t;
107 if (t instanceof XMLReaderFailure) {
108 throw (XMLReaderFailure) t;
111 throw new XMLReaderFailure(t);
114 private class XMLReaderHandler extends DefaultHandler {
115 private SAXParserFactory parserFactory;
116 private SectionsManager manager;
118 public XMLReaderHandler(SAXParserFactory aParserFactory, SectionHandler aRootHandler) {
121 parserFactory=aParserFactory;
122 manager = new SectionsManager();
123 manager.pushHandler(aRootHandler);
126 public void setDocumentLocator(Locator aLocator) {
130 private void processInputSource(InputSource anInputSource) throws XMLReaderExc, XMLReaderFailure {
132 SAXParser parser=parserFactory.newSAXParser();
134 parser.parse(anInputSource, this);
136 catch (Throwable e) {
137 Throwable t = ExceptionFunctions.traceCauseException(e);
139 if (t instanceof XMLReaderExc) {
140 if (locator!=null && filename!=null)
141 ((XMLReaderExc) t).setLocation(filename, locator.getLineNumber(), locator.getColumnNumber());
142 throw (XMLReaderExc) t;
145 if (t instanceof SAXParseException) {
146 XMLReaderExc r = new XMLReaderExc(t.getMessage());
148 if (locator!=null && filename!=null)
149 r.setLocation(filename, locator.getLineNumber(), locator.getColumnNumber());
154 if (t instanceof XMLReaderFailure) {
155 throw (XMLReaderFailure) t;
158 if (t instanceof ParserConfigurationException) {
159 throw new XMLReaderFailure("Internal exception: "+t.toString(), t);
162 throw new XMLReaderFailure(t);
166 public void startElement(String aUri, String aLocalName, String aQualifiedName, Attributes anAttributes) throws SAXException {
171 attributesMap = new HashMap();
173 // if (namespaceAware)
174 for (i=0; i<anAttributes.getLength(); i++)
175 attributesMap.put(new XMLName(anAttributes.getURI(i), XMLReaderTool.getNameSpaceFromQualifiedName(anAttributes.getQName(i)), anAttributes.getLocalName(i)), anAttributes.getValue(i));
177 for (i=0; i<anAttributes.getLength(); i++)
178 attributesMap.put(anAttributes.getLocalName(i), anAttributes.getValue(i));
181 SectionHandler handler = manager.currentHandler().startElement(new XMLName(aUri, XMLReaderTool.getNameSpaceFromQualifiedName(aQualifiedName), aLocalName), attributesMap);
183 manager.pushHandler( handler );
185 catch (XMLReaderExc e) {
186 throw new SAXParseException(e.getMessage(), null, e);
188 catch (Exception e) {
189 throw new SAXException(e);
193 public void endElement(String aUri, String aLocalName, String aQualifiedName) throws SAXException {
196 if (!aQualifiedName.equals("include")) {
197 SectionHandler handler = manager.popHandler();
199 handler.finishSection();
201 if (!manager.isEmpty()) {
202 manager.currentHandler().endElement(handler);
206 catch (XMLReaderExc e) {
207 throw new SAXParseException(e.getMessage(), null, e);
209 catch (Exception e) {
210 throw new SAXException(e);
214 public void characters(char[] aBuffer, int aStart, int anEnd) throws SAXException {
216 String text = new String(aBuffer, aStart, anEnd);
218 manager.currentHandler().characters(text);
220 catch (XMLReaderExc e) {
221 throw new SAXParseException(e.getMessage(), null, e);
223 catch (Exception e) {
224 throw new SAXException(e);
229 private class SectionsManager {
232 public SectionsManager() {
233 handlerStack = new Stack();
236 public void pushHandler(SectionHandler aSectionHandler) {
237 handlerStack.push(aSectionHandler);
240 public SectionHandler popHandler() {
241 return (SectionHandler) handlerStack.pop();
244 public SectionHandler currentHandler() {
245 return (SectionHandler) handlerStack.peek();
248 public boolean isEmpty() {
249 return handlerStack.isEmpty();
253 public static interface SectionHandler {
254 public abstract SectionHandler startElement(XMLName aTag, Map anAttributes) throws XMLReaderExc;
256 public abstract void endElement(SectionHandler aHandler) throws XMLReaderExc;
258 public void characters(String aCharacters) throws XMLReaderExc;
260 public void finishSection() throws XMLReaderExc;
263 public static abstract class AbstractSectionHandler implements SectionHandler {
264 public SectionHandler startElement(XMLName aTag, Map anAttributes) throws XMLReaderExc {
265 return startElement(aTag.getLocalName(), anAttributes);
268 public SectionHandler startElement(String aLocalName, Map anAttributes) throws XMLReaderExc {
272 public void endElement(SectionHandler aHandler) throws XMLReaderExc {
275 public void finishSection() throws XMLReaderExc {
278 public void characters(String aCharacters) throws XMLReaderExc {
279 if ( aCharacters.trim().length() > 0) {
280 throw new XMLReaderExc("Text not allowed");
285 public static class XMLReaderExc extends Exc {
286 private boolean hasLocation;
287 private String filename;
289 private int columnNr;
291 public XMLReaderExc(String aMessage) {
296 protected void setLocation(String aFilename, int aLineNr, int aColumnNr) {
297 filename = aFilename;
299 columnNr = aColumnNr;
303 public boolean getHasLocation() {
307 public int getLineNr() {
311 public int getColumnNr() {
315 public String getFilename() {
320 public static class XMLReaderFailure extends Failure {
321 public XMLReaderFailure(String aMessage, Throwable aCause) {
322 super(aMessage, aCause);
325 public XMLReaderFailure(Throwable aCause) {
326 super(aCause.getMessage(), aCause);
330 public static class XMLName {
331 private String namespaceURI;
332 private String localName;
333 private String prefix;
335 public XMLName(String aLocalName) {
336 this(null, null, aLocalName);
339 public XMLName(String aNamespaceURI, String aPrefix, String aLocalName) {
344 if (aLocalName!=null)
345 localName = aLocalName;
348 if (aNamespaceURI!=null)
349 namespaceURI = aNamespaceURI;
352 public XMLName(String aNamespaceURI, String aLocalName) {
353 this (aNamespaceURI, null, aLocalName);
356 public String getNamespaceURI() {
360 public String getLocalName() {
364 public String getPrefix() {
368 public int hashCode() {
369 if (namespaceURI == null)
370 return localName.hashCode() + 3*prefix.hashCode();
372 return localName.hashCode() + 3*namespaceURI.hashCode();
375 public String toString() {
376 return ((namespaceURI.length()>0)? "["+namespaceURI+"]":"")+((prefix.length()>0)?prefix+":":"")+localName;
379 public boolean equals(Object anObject) {
380 if (anObject instanceof XMLName) {
381 if (namespaceURI==null)
382 return (((XMLName) anObject).namespaceURI == null) &&
383 prefix.equals(((XMLName) anObject).prefix) &&
384 localName.equals(((XMLName) anObject).localName);
386 return namespaceURI.equals(((XMLName) anObject).namespaceURI) &&
387 localName.equals(((XMLName) anObject).localName);