o_store fixx
[mir.git] / source / mir / util / XMLReader.java
1 /*\r
2  * Copyright (C) 2001, 2002 The Mir-coders group\r
3  *\r
4  * This file is part of Mir.\r
5  *\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
10  *\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
15  *\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
19  *\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
29  */\r
30 package mir.util;\r
31 \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
41 \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
49 import multex.Exc;\r
50 import multex.Failure;\r
51 \r
52 public class XMLReader {\r
53   private Locator locator;\r
54   private String filename;\r
55   private boolean namespaceAware;\r
56 \r
57   public XMLReader() {\r
58     this(false);\r
59   }\r
60 \r
61   public XMLReader(boolean aNameSpaceAware) {\r
62     namespaceAware = aNameSpaceAware;\r
63     filename="";\r
64   }\r
65 \r
66   public void parseString(String aString, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {\r
67     try {\r
68       parseInputSource(new InputSource(new StringReader(aString)), aRootHandler);\r
69     }\r
70     catch (Throwable t) {\r
71       throw new XMLReaderFailure(t);\r
72     }\r
73   }\r
74 \r
75   public void parseString(boolean aTagSoup, String aString, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {\r
76     try {\r
77       parseInputSource(aTagSoup, new InputSource(new StringReader(aString)), aRootHandler);\r
78     }\r
79     catch (Throwable t) {\r
80       throw new XMLReaderFailure(t);\r
81     }\r
82   }\r
83 \r
84   public void parseFile(String aFileName, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {\r
85     filename= aFileName;\r
86     try {\r
87       parseInputStream(new FileInputStream(aFileName), aRootHandler);\r
88     }\r
89     catch (Throwable t) {\r
90       throw new XMLReaderFailure(t);\r
91     }\r
92   }\r
93 \r
94   public void parseInputStream(InputStream anInputStream, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {\r
95     parseInputSource(new InputSource(anInputStream), aRootHandler);\r
96   }\r
97 \r
98   public void parseInputStream(boolean aTagSoup, InputStream anInputStream, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {\r
99     parseInputSource(aTagSoup, new InputSource(anInputStream), aRootHandler);\r
100   }\r
101 \r
102   public void parseInputSource(InputSource anInputSource, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {\r
103     try {\r
104       parseInputSource(false, anInputSource, aRootHandler);\r
105     }\r
106     catch (Throwable e) {\r
107       Throwable t = ExceptionFunctions.traceCauseException(e);\r
108 \r
109       if (t instanceof XMLReaderExc) {\r
110         throw (XMLReaderExc) t;\r
111       }\r
112 \r
113       if (t instanceof XMLReaderFailure) {\r
114         throw (XMLReaderFailure) t;\r
115       }\r
116 \r
117       throw new XMLReaderFailure(t);\r
118     }\r
119   }\r
120 \r
121   public void parseInputSource(boolean aTagSoup, InputSource anInputSource, SectionHandler aRootHandler) throws XMLReaderFailure, XMLReaderExc {\r
122     try {\r
123       XMLReaderHandler handler = new XMLReaderHandler(aRootHandler);\r
124 \r
125       if (aTagSoup) {\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
130       }\r
131       else {\r
132         SAXParserFactory parserFactory = SAXParserFactory.newInstance();\r
133 \r
134         parserFactory.setNamespaceAware(true);\r
135         parserFactory.setValidating(true);\r
136         SAXParser parser = parserFactory.newSAXParser();\r
137 \r
138         parser.parse(anInputSource, handler);\r
139       }\r
140     }\r
141     catch (Throwable e) {\r
142       Throwable t = ExceptionFunctions.traceCauseException(e);\r
143 \r
144       if (t instanceof XMLReaderExc) {\r
145         throw (XMLReaderExc) t;\r
146       }\r
147 \r
148       if (t instanceof XMLReaderFailure) {\r
149         throw (XMLReaderFailure) t;\r
150       }\r
151 \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
156       }\r
157 \r
158       if (t instanceof SAXParseException) {\r
159         XMLReaderExc r = new XMLReaderExc(t.getMessage());\r
160 \r
161         if (locator!=null && filename!=null)\r
162           r.setLocation(filename, locator.getLineNumber(), locator.getColumnNumber());\r
163 \r
164         throw r;\r
165       }\r
166 \r
167       if (t instanceof XMLReaderFailure) {\r
168         throw (XMLReaderFailure) t;\r
169       }\r
170 \r
171       if (t instanceof ParserConfigurationException) {\r
172         throw new XMLReaderFailure("Internal exception: "+t.toString(), t);\r
173       }\r
174 \r
175       throw new XMLReaderFailure(t);\r
176     }\r
177   }\r
178   private class XMLReaderHandler extends DefaultHandler {\r
179     private SectionsManager manager;\r
180 \r
181     public XMLReaderHandler(SectionHandler aRootHandler) {\r
182       super();\r
183 \r
184       manager = new SectionsManager();\r
185       manager.pushHandler(aRootHandler);\r
186    }\r
187 \r
188     public void setDocumentLocator(Locator aLocator) {\r
189       locator=aLocator;\r
190     }\r
191 \r
192     public void startElement(String aUri, String aLocalName, String aQualifiedName, Attributes anAttributes) throws SAXException {\r
193       Map attributesMap;\r
194       int i;\r
195 \r
196       try {\r
197         attributesMap = new HashMap();\r
198 \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
202         else\r
203           for (i=0; i<anAttributes.getLength(); i++)\r
204             attributesMap.put(anAttributes.getLocalName(i), anAttributes.getValue(i));\r
205 \r
206         SectionHandler handler = manager.currentHandler().startElement(new XMLName(aUri, XMLReaderTool.getNameSpaceFromQualifiedName(aQualifiedName), aLocalName), attributesMap);\r
207 \r
208         manager.pushHandler( handler );\r
209       }\r
210       catch (XMLReaderExc e) {\r
211         throw new SAXParseException(e.getMessage(), null, e);\r
212       }\r
213       catch (Exception e) {\r
214         throw new SAXException(e);\r
215       }\r
216     }\r
217 \r
218     public void endElement(String aUri, String aLocalName, String aQualifiedName) throws SAXException {\r
219       try\r
220       {\r
221         SectionHandler handler = manager.popHandler();\r
222 \r
223         handler.finishSection();\r
224 \r
225         if (!manager.isEmpty()) {\r
226           manager.currentHandler().endElement(handler);\r
227         }\r
228       }\r
229       catch (XMLReaderExc e) {\r
230         throw new SAXParseException(e.getMessage(), null, e);\r
231       }\r
232       catch (Exception e) {\r
233         throw new SAXException(e);\r
234       }\r
235     }\r
236 \r
237     public void endDocument() throws SAXException {\r
238       try\r
239       {\r
240         SectionHandler handler = manager.popHandler();\r
241 \r
242         handler.finishSection();\r
243       }\r
244       catch (XMLReaderExc e) {\r
245         throw new SAXParseException(e.getMessage(), null, e);\r
246       }\r
247       catch (Exception e) {\r
248         throw new SAXException(e);\r
249       }\r
250     }\r
251 \r
252     public void characters(char[] aBuffer, int aStart, int anEnd) throws SAXException {\r
253       try {\r
254         String text = new String(aBuffer, aStart, anEnd);\r
255 \r
256         manager.currentHandler().characters(text);\r
257       }\r
258       catch (XMLReaderExc e) {\r
259         throw new SAXParseException(e.getMessage(), null, e);\r
260       }\r
261       catch (Exception e) {\r
262         throw new SAXException(e);\r
263       }\r
264     }\r
265   }\r
266 \r
267   private class SectionsManager {\r
268     Stack handlerStack;\r
269 \r
270     public SectionsManager() {\r
271       handlerStack = new Stack();\r
272     }\r
273 \r
274     public void pushHandler(SectionHandler aSectionHandler) {\r
275       handlerStack.push(aSectionHandler);\r
276     }\r
277 \r
278     public SectionHandler popHandler() {\r
279       return (SectionHandler) handlerStack.pop();\r
280     }\r
281 \r
282     public SectionHandler currentHandler() {\r
283       return (SectionHandler) handlerStack.peek();\r
284     }\r
285 \r
286     public boolean isEmpty() {\r
287       return handlerStack.isEmpty();\r
288     }\r
289   }\r
290 \r
291   public static interface SectionHandler {\r
292     public abstract SectionHandler startElement(XMLName aTag, Map anAttributes) throws XMLReaderExc;\r
293 \r
294     public abstract void endElement(SectionHandler aHandler) throws XMLReaderExc;\r
295 \r
296     public void characters(String aCharacters) throws XMLReaderExc;\r
297 \r
298     public void finishSection() throws XMLReaderExc;\r
299   }\r
300 \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
304     };\r
305 \r
306     public SectionHandler startElement(String aLocalName, Map anAttributes) throws XMLReaderExc {\r
307       return null;\r
308     };\r
309 \r
310     public void endElement(SectionHandler aHandler) throws XMLReaderExc {\r
311     };\r
312 \r
313     public void finishSection() throws XMLReaderExc {\r
314     }\r
315 \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
319       }\r
320     }\r
321   }\r
322 \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
328 \r
329     public XMLReaderExc(String aMessage) {\r
330       super(aMessage);\r
331       hasLocation = false;\r
332     }\r
333 \r
334     protected void setLocation(String aFilename, int aLineNr, int aColumnNr) {\r
335       filename = aFilename;\r
336       lineNr = aLineNr;\r
337       columnNr = aColumnNr;\r
338       hasLocation = true;\r
339     }\r
340 \r
341     public boolean getHasLocation() {\r
342       return hasLocation;\r
343     }\r
344 \r
345     public int getLineNr() {\r
346       return lineNr;\r
347     }\r
348 \r
349     public int getColumnNr() {\r
350       return columnNr;\r
351     }\r
352 \r
353     public String getFilename() {\r
354       return filename;\r
355     }\r
356   }\r
357 \r
358   public static class XMLReaderFailure extends Failure {\r
359     public XMLReaderFailure(String aMessage, Throwable aCause) {\r
360       super(aMessage, aCause);\r
361     }\r
362 \r
363     public XMLReaderFailure(Throwable aCause) {\r
364       super(aCause.getMessage(), aCause);\r
365     }\r
366   }\r
367 \r
368   public static class XMLName {\r
369     private String namespaceURI;\r
370     private String localName;\r
371     private String prefix;\r
372 \r
373     public XMLName(String aLocalName) {\r
374       this(null, null, aLocalName);\r
375     }\r
376 \r
377     public XMLName(String aNamespaceURI, String aPrefix, String aLocalName) {\r
378       localName="";\r
379       prefix="";\r
380       namespaceURI="";\r
381 \r
382       if (aLocalName!=null)\r
383         localName = aLocalName;\r
384       if (aPrefix!=null)\r
385         prefix = aPrefix;\r
386       if (aNamespaceURI!=null)\r
387         namespaceURI = aNamespaceURI;\r
388     }\r
389 \r
390     public XMLName(String aNamespaceURI, String aLocalName) {\r
391       this (aNamespaceURI, null, aLocalName);\r
392     }\r
393 \r
394     public String getNamespaceURI() {\r
395       return namespaceURI;\r
396     }\r
397 \r
398     public String getLocalName() {\r
399       return localName;\r
400     }\r
401 \r
402     public String getPrefix() {\r
403       return prefix;\r
404     }\r
405 \r
406     public int hashCode() {\r
407       if (namespaceURI == null)\r
408         return localName.hashCode() + 3*prefix.hashCode();\r
409       else\r
410         return localName.hashCode() + 3*namespaceURI.hashCode();\r
411     }\r
412 \r
413     public String toString() {\r
414       return ((namespaceURI.length()>0)? "["+namespaceURI+"]":"")+((prefix.length()>0)?prefix+":":"")+localName;\r
415     }\r
416 \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
423         else\r
424           return namespaceURI.equals(((XMLName) anObject).namespaceURI) &&\r
425                  localName.equals(((XMLName) anObject).localName);\r
426       }\r
427       else\r
428         return false;\r
429     }\r
430   }\r
431 \r
432 }