1.1 restoration
[mir.git] / source / mir / util / xml / XMLParserEngine.java
1 /*
2  * Copyright (C) 2001, 2002 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
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.
10  *
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.
15  *
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
19  *
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.
29  */
30
31 package mir.util.xml;
32
33 import java.io.BufferedInputStream;
34 import java.io.FileInputStream;
35 import java.io.InputStream;
36 import java.io.StringReader;
37 import java.io.File;
38 import java.io.Reader;
39 import java.io.InputStreamReader;
40 import java.io.UnsupportedEncodingException;
41 import java.util.HashMap;
42 import java.util.Map;
43
44 import java.util.Stack;
45
46 import mir.util.ExceptionFunctions;
47 import mir.util.xml.html.XMLHTMLParserProvider;
48
49 public class XMLParserEngine {
50   private Map providers;
51   private XMLParserProvider defaultProvider;
52
53   private static XMLParserEngine instance = new XMLParserEngine();
54
55   public static XMLParserEngine getInstance() {
56     return instance;
57   }
58
59   private XMLParserEngine() {
60     providers = new HashMap();
61     defaultProvider = new XMLSAXParserProvider(false);
62     providers.put("xml", defaultProvider);
63     providers.put("xml.namespaceaware", new XMLSAXParserProvider(true));
64     providers.put("html", new XMLHTMLParserProvider());
65   }
66
67   /**
68    *
69    * @param aString
70    * @param aRootHandler
71    * @throws XMLParserFailure
72    * @throws XMLParserExc
73    */
74   public void parseString(String aProvider, String aString, SectionHandler aRootHandler) throws XMLParserFailure, XMLParserExc{
75     try {
76       parse(aProvider, new StringReader(aString), aRootHandler);
77     }
78     catch (Throwable t) {
79       throw new XMLParserFailure(t);
80     }
81   }
82
83   /**
84    *
85    * @param aFile
86    * @param aRootHandler
87    */
88   public void parse(String aProvider, File aFile, SectionHandler aRootHandler) throws XMLParserFailure, XMLParserExc {
89 //    filename = aFileName;
90
91     try {
92       parse(aProvider, new BufferedInputStream(new FileInputStream(aFile), 8192), aRootHandler);
93     }
94     catch (XMLParserExc e) {
95       throw e;
96     }
97     catch (Throwable t) {
98       throw new XMLParserFailure(t);
99     }
100   }
101
102   /**
103    * Parse xml coming from an input stream with the system default encoding
104    */
105   public void parse(String aProvider, InputStream anInputStream, SectionHandler aRootHandler) throws XMLParserFailure, XMLParserExc{
106     parse(aProvider, new InputStreamReader(anInputStream), aRootHandler);
107   }
108
109   /**
110    * Parse xml coming from an input stream according to the given encoding
111    */
112   public void parse(String aProvider, InputStream anInputStream, String anEncoding, SectionHandler aRootHandler) throws XMLParserFailure, XMLParserExc{
113     try {
114       parse(aProvider, new InputStreamReader(anInputStream, anEncoding), aRootHandler);
115     }
116     catch (UnsupportedEncodingException e) {
117       throw new XMLParserExc("Unsupported encoding: " + anEncoding);
118     }
119   }
120
121
122   /**
123    *
124    * @param aRootHandler
125    * @throws mir.util.xml.XMLParserFailure
126    * @throws mir.util.xml.XMLParserExc
127    */
128   public void parse(String aProvider, Reader aReader, SectionHandler aRootHandler) throws XMLParserFailure, XMLParserExc{
129     XMLParserProvider provider = (XMLParserProvider) providers.get(aProvider);
130
131     if (provider==null)
132       provider = defaultProvider;
133
134     XMLParserRunner runner = new XMLParserRunner(aRootHandler);
135
136     try {
137       provider.parse(aReader, runner);
138     }
139     catch (Throwable e) {
140       Throwable t = ExceptionFunctions.traceCauseException(e);
141
142       if (t instanceof XMLParserExc && runner.getLocator()!=null) {
143         ((XMLParserExc) t).setLocation(runner.getLocator().getLineNr(), runner.getLocator().getColumnNr());
144       }
145
146       if (t instanceof XMLParserExc) {
147         throw (XMLParserExc) t;
148       }
149
150       if (t instanceof XMLParserFailure) {
151         throw (XMLParserFailure) t;
152       }
153
154       throw new XMLParserFailure(t);
155     }
156   }
157
158   public interface XMLLocator {
159     public int getLineNr();
160     public int getColumnNr();
161   }
162
163   public interface XMLParserReceiver {
164     /**
165      * Provides an object with which it's possible to track the parser's
166      *    position.
167      */
168     public void setLocator(XMLLocator aLocator);
169
170     /**
171      * Extra document data, outside of tags and CDATA, will be passed verbatim
172      * to this method. This may include comments, DTDs, XML specifications,
173      * etc.
174      */
175     public void extra(String aPreAmble) throws XMLParserExc, XMLParserFailure;
176
177     public void startElement(XMLName anElement, Map anAttributes) throws XMLParserExc, XMLParserFailure;
178     public void endElement(XMLName anElement) throws XMLParserExc, XMLParserFailure;
179     public void startDocument() throws XMLParserExc, XMLParserFailure;
180     public void endDocument() throws XMLParserExc, XMLParserFailure;
181     public void text(String aText) throws XMLParserExc, XMLParserFailure;
182   }
183
184   public interface XMLParserProvider {
185     public void parse(Reader aReader, XMLParserReceiver aReceiver) throws XMLParserExc, XMLParserFailure;
186   }
187
188   private class XMLParserRunner implements XMLParserReceiver {
189     private SectionsManager manager;
190     private XMLLocator locator;
191     private SectionHandler rootHandler;
192
193     public XMLParserRunner(SectionHandler aRootHandler) {
194       super();
195
196       locator = null;
197       manager = new SectionsManager();
198       rootHandler = aRootHandler;
199     }
200
201     public void setLocator(XMLLocator aLocator) {
202       locator=aLocator;
203     }
204
205     public void extra(String anExtraData) throws XMLParserExc, XMLParserFailure {
206       SectionHandler handler = manager.currentHandler();
207
208       handler.extra(anExtraData);
209     }
210
211     public void startElement(XMLName anElement, Map anAttributes) throws XMLParserExc, XMLParserFailure {
212       SectionHandler handler = manager.currentHandler().startElement(anElement, anAttributes);
213
214       handler.startSection();
215
216       manager.pushHandler(handler);
217     }
218
219     public void endElement(XMLName anElement) throws XMLParserExc, XMLParserFailure {
220       SectionHandler handler = manager.popHandler();
221
222       handler.finishSection();
223
224       manager.currentHandler().endElement(handler);
225     }
226
227     public void startDocument() throws XMLParserExc, XMLParserFailure {
228       rootHandler.startSection();
229       manager.pushHandler(rootHandler);
230     }
231
232     public void endDocument() throws XMLParserExc, XMLParserFailure {
233       SectionHandler handler = manager.popHandler();
234
235       handler.finishSection();
236     }
237
238     public void text(String aText) throws XMLParserExc, XMLParserFailure {
239       manager.currentHandler().characters(aText);
240     }
241
242     public XMLLocator getLocator() {
243       return locator;
244     }
245   }
246
247   /**
248    *
249    * <p>Title: </p>
250    * <p>Description: </p>
251    * <p>Copyright: Copyright (c) 2003</p>
252    * <p>Company: </p>
253    * @author not attributable
254    * @version 1.0
255    */
256   private class SectionsManager {
257     private Stack handlerStack;
258
259     public SectionsManager() {
260       handlerStack = new Stack();
261     }
262
263     public void pushHandler(SectionHandler aSectionHandler) {
264       handlerStack.push(aSectionHandler);
265     }
266
267     public SectionHandler popHandler() {
268       return (SectionHandler) handlerStack.pop();
269     }
270
271     public SectionHandler currentHandler() {
272       return (SectionHandler) handlerStack.peek();
273     }
274
275     public boolean isEmpty() {
276       return handlerStack.isEmpty();
277     }
278   }
279
280 }