KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dom4j > io > XPPPacketReader


1 /*
2  * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
3  *
4  * This software is open source.
5  * See the bottom of this file for the licence.
6  *
7  * $Id: XPPPacketReader.java,v 1.10 2005/07/11 16:26:57 gaston Exp $
8  */

9
10 package org.dom4j.io;
11
12 import java.io.*;
13 import java.net.URL JavaDoc;
14 import org.dom4j.Document;
15 import org.dom4j.DocumentException;
16 import org.dom4j.DocumentFactory;
17 import org.dom4j.Element;
18 import org.dom4j.ElementHandler;
19 import org.dom4j.QName;
20 import org.xmlpull.v1.XmlPullParser;
21 import org.xmlpull.v1.XmlPullParserException;
22 import org.xmlpull.v1.XmlPullParserFactory;
23
24 /**
25  * <p><code>XPPPacketReader</code> is a Reader of DOM4J documents that
26  * uses the fast
27  * <a HREF="http://www.extreme.indiana.edu/soap/xpp/">XML Pull Parser 3.x</a>.
28  * It is very fast for use in SOAP style environments.</p>
29  *
30  * @author <a HREF="mailto:pelle@neubia.com">Pelle Braendgaard</a>
31  * @author <a HREF="mailto:jstrachan@apache.org">James Strachan</a>
32  * @version $Revision: 1.10 $
33  */

34 public class XPPPacketReader {
35
36     /**
37      * <code>DocumentFactory</code> used to create new document objects
38      */

39     private DocumentFactory factory;
40
41     /**
42      * <code>XmlPullParser</code> used to parse XML
43      */

44     private XmlPullParser xppParser;
45
46     /**
47      * <code>XmlPullParser</code> used to parse XML
48      */

49     private XmlPullParserFactory xppFactory;
50
51     /**
52      * DispatchHandler to call when each <code>Element</code> is encountered
53      */

54     private DispatchHandler dispatchHandler;
55
56
57     public XPPPacketReader() {
58     }
59
60     public XPPPacketReader(DocumentFactory factory) {
61         this.factory = factory;
62     }
63
64
65     /**
66      * <p>Reads a Document from the given <code>File</code></p>
67      *
68      * @param file is the <code>File</code> to read from.
69      * @return the newly created Document instance
70      * @throws DocumentException if an error occurs during parsing.
71      * @throws java.net.MalformedURLException if a URL could not be made for the given File
72      */

73     public Document read(File file) throws DocumentException, IOException, XmlPullParserException {
74         String JavaDoc systemID = file.getAbsolutePath();
75         return read(new BufferedReader(new FileReader(file)), systemID);
76     }
77
78     /**
79      * <p>Reads a Document from the given <code>URL</code></p>
80      *
81      * @param url <code>URL</code> to read from.
82      * @return the newly created Document instance
83      * @throws DocumentException if an error occurs during parsing.
84      */

85     public Document read(URL JavaDoc url) throws DocumentException, IOException, XmlPullParserException {
86         String JavaDoc systemID = url.toExternalForm();
87         return read(createReader(url.openStream()), systemID);
88     }
89
90     /**
91      * <p>Reads a Document from the given URL or filename.</p>
92      * <p/>
93      * <p/>
94      * If the systemID contains a <code>':'</code> character then it is
95      * assumed to be a URL otherwise its assumed to be a file name.
96      * If you want finer grained control over this mechansim then please
97      * explicitly pass in either a {@link URL} or a {@link File} instance
98      * instead of a {@link String} to denote the source of the document.
99      * </p>
100      *
101      * @param systemID is a URL for a document or a file name.
102      * @return the newly created Document instance
103      * @throws DocumentException if an error occurs during parsing.
104      * @throws java.net.MalformedURLException if a URL could not be made for the given File
105      */

106     public Document read(String JavaDoc systemID) throws DocumentException, IOException, XmlPullParserException {
107         if (systemID.indexOf(':') >= 0) {
108             // lets assume its a URL
109
return read(new URL JavaDoc(systemID));
110         }
111         else {
112             // lets assume that we are given a file name
113
return read(new File(systemID));
114         }
115     }
116
117     /**
118      * <p>Reads a Document from the given stream</p>
119      *
120      * @param in <code>InputStream</code> to read from.
121      * @return the newly created Document instance
122      * @throws DocumentException if an error occurs during parsing.
123      */

124     public Document read(InputStream in) throws DocumentException, IOException, XmlPullParserException {
125         return read(createReader(in));
126     }
127
128     /**
129      * <p>Reads a Document from the given <code>Reader</code></p>
130      *
131      * @param reader is the reader for the input
132      * @return the newly created Document instance
133      * @throws DocumentException if an error occurs during parsing.
134      */

135     public Document read(Reader reader) throws DocumentException, IOException, XmlPullParserException {
136         getXPPParser().setInput(reader);
137         return parseDocument();
138     }
139
140     /**
141      * <p>Reads a Document from the given array of characters</p>
142      *
143      * @param text is the text to parse
144      * @return the newly created Document instance
145      * @throws DocumentException if an error occurs during parsing.
146      */

147     public Document read(char[] text) throws DocumentException, IOException, XmlPullParserException {
148         getXPPParser().setInput(new CharArrayReader(text));
149         return parseDocument();
150     }
151
152     /**
153      * <p>Reads a Document from the given stream</p>
154      *
155      * @param in <code>InputStream</code> to read from.
156      * @param systemID is the URI for the input
157      * @return the newly created Document instance
158      * @throws DocumentException if an error occurs during parsing.
159      */

160     public Document read(InputStream in, String JavaDoc systemID) throws DocumentException, IOException, XmlPullParserException {
161         return read(createReader(in), systemID);
162     }
163
164     /**
165      * <p>Reads a Document from the given <code>Reader</code></p>
166      *
167      * @param reader is the reader for the input
168      * @param systemID is the URI for the input
169      * @return the newly created Document instance
170      * @throws DocumentException if an error occurs during parsing.
171      */

172     public Document read(Reader reader, String JavaDoc systemID) throws DocumentException, IOException, XmlPullParserException {
173         Document document = read(reader);
174         document.setName(systemID);
175         return document;
176     }
177
178
179     // Properties
180
//-------------------------------------------------------------------------
181

182     public XmlPullParser getXPPParser() throws XmlPullParserException {
183         if (xppParser == null) {
184             xppParser = getXPPFactory().newPullParser();
185         }
186         return xppParser;
187     }
188
189     public XmlPullParserFactory getXPPFactory() throws XmlPullParserException {
190         if (xppFactory == null) {
191             xppFactory = XmlPullParserFactory.newInstance();
192         }
193         xppFactory.setNamespaceAware(true);
194         return xppFactory;
195     }
196
197     public void setXPPFactory(XmlPullParserFactory xppFactory) {
198         this.xppFactory = xppFactory;
199     }
200
201     /**
202      * @return the <code>DocumentFactory</code> used to create document objects
203      */

204     public DocumentFactory getDocumentFactory() {
205         if (factory == null) {
206             factory = DocumentFactory.getInstance();
207         }
208         return factory;
209     }
210
211     /**
212      * <p>This sets the <code>DocumentFactory</code> used to create new documents.
213      * This method allows the building of custom DOM4J tree objects to be implemented
214      * easily using a custom derivation of {@link DocumentFactory}</p>
215      *
216      * @param factory <code>DocumentFactory</code> used to create DOM4J objects
217      */

218     public void setDocumentFactory(DocumentFactory factory) {
219         this.factory = factory;
220     }
221
222
223     /**
224      * Adds the <code>ElementHandler</code> to be called when the
225      * specified path is encounted.
226      *
227      * @param path is the path to be handled
228      * @param handler is the <code>ElementHandler</code> to be called
229      * by the event based processor.
230      */

231     public void addHandler(String JavaDoc path, ElementHandler handler) {
232         getDispatchHandler().addHandler(path, handler);
233     }
234
235     /**
236      * Removes the <code>ElementHandler</code> from the event based
237      * processor, for the specified path.
238      *
239      * @param path is the path to remove the <code>ElementHandler</code> for.
240      */

241     public void removeHandler(String JavaDoc path) {
242         getDispatchHandler().removeHandler(path);
243     }
244
245     /**
246      * When multiple <code>ElementHandler</code> instances have been
247      * registered, this will set a default <code>ElementHandler</code>
248      * to be called for any path which does <b>NOT</b> have a handler
249      * registered.
250      *
251      * @param handler is the <code>ElementHandler</code> to be called
252      * by the event based processor.
253      */

254     public void setDefaultHandler(ElementHandler handler) {
255         getDispatchHandler().setDefaultHandler(handler);
256     }
257
258     // Implementation methods
259
//-------------------------------------------------------------------------
260
public Document parseDocument() throws DocumentException, IOException, XmlPullParserException {
261         DocumentFactory df = getDocumentFactory();
262         Document document = df.createDocument();
263         Element parent = null;
264         XmlPullParser pp = getXPPParser();
265         int count = 0;
266         while (true) {
267             int type = -1;
268             type = pp.nextToken();
269             switch (type) {
270                 case XmlPullParser.PROCESSING_INSTRUCTION: {
271                     String JavaDoc text = pp.getText();
272                     int loc = text.indexOf(" ");
273                     if (loc >= 0) {
274                         document.addProcessingInstruction(text.substring(0, loc), text.substring(loc + 1));
275                     }
276                     else
277                         document.addProcessingInstruction(text, "");
278                     break;
279                 }
280                 case XmlPullParser.COMMENT: {
281                     if (parent != null)
282                         parent.addComment(pp.getText());
283                     else
284                         document.addComment(pp.getText());
285                     break;
286                 }
287                 case XmlPullParser.CDSECT: {
288                     String JavaDoc text = pp.getText();
289                     if (parent != null) {
290                         parent.addCDATA(text);
291                     }
292                     else {
293                         if (text.trim().length() > 0) {
294                             throw new DocumentException("Cannot have text content outside of the root document");
295                         }
296                     }
297                     break;
298
299                 }
300                 case XmlPullParser.ENTITY_REF: {
301                     String JavaDoc text = pp.getText();
302                     if (parent != null) {
303                         parent.addText(text);
304                     }
305                     else {
306                         if (text.trim().length() > 0) {
307                             throw new DocumentException("Cannot have an entityref outside of the root document");
308                         }
309                     }
310                     break;
311                 }
312                 case XmlPullParser.END_DOCUMENT: {
313                     return document;
314                 }
315                 case XmlPullParser.START_TAG: {
316                     QName qname = (pp.getPrefix() == null) ? df.createQName(pp.getName(), pp.getNamespace()) : df.createQName(pp.getName(), pp.getPrefix(), pp.getNamespace());
317                     Element newElement = null;
318                     // Do not include the namespace if this is the start tag of a new packet
319
// This avoids including "jabber:client", "jabber:server" or
320
// "jabber:component:accept"
321
if ("jabber:client".equals(qname.getNamespaceURI()) ||
322                             "jabber:server".equals(qname.getNamespaceURI()) ||
323                             "jabber:component:accept".equals(qname.getNamespaceURI())) {
324                         newElement = df.createElement(pp.getName());
325                     }
326                     else {
327                         newElement = df.createElement(qname);
328                     }
329                     int nsStart = pp.getNamespaceCount(pp.getDepth() - 1);
330                     int nsEnd = pp.getNamespaceCount(pp.getDepth());
331                     for (int i = nsStart; i < nsEnd; i++)
332                         if (pp.getNamespacePrefix(i) != null)
333                             newElement.addNamespace(pp.getNamespacePrefix(i), pp.getNamespaceUri(i));
334                     for (int i = 0; i < pp.getAttributeCount(); i++) {
335                         QName qa = (pp.getAttributePrefix(i) == null) ? df.createQName(pp.getAttributeName(i)) : df.createQName(pp.getAttributeName(i), pp.getAttributePrefix(i), pp.getAttributeNamespace(i));
336                         newElement.addAttribute(qa, pp.getAttributeValue(i));
337                     }
338                     if (parent != null) {
339                         parent.add(newElement);
340                     }
341                     else {
342                         document.add(newElement);
343                     }
344                     parent = newElement;
345                     count++;
346                     break;
347                 }
348                 case XmlPullParser.END_TAG: {
349                     if (parent != null) {
350                         parent = parent.getParent();
351                     }
352                     count--;
353                     if (count < 1) {
354                         return document;
355                     }
356                     break;
357                 }
358                 case XmlPullParser.TEXT: {
359                     String JavaDoc text = pp.getText();
360                     if (parent != null) {
361                         parent.addText(text);
362                     }
363                     else {
364                         if (text.trim().length() > 0) {
365                             throw new DocumentException("Cannot have text content outside of the root document");
366                         }
367                     }
368                     break;
369                 }
370                 default:
371                 {
372                     ;
373                 }
374             }
375         }
376     }
377
378     protected DispatchHandler getDispatchHandler() {
379         if (dispatchHandler == null) {
380             dispatchHandler = new DispatchHandler();
381         }
382         return dispatchHandler;
383     }
384
385     protected void setDispatchHandler(DispatchHandler dispatchHandler) {
386         this.dispatchHandler = dispatchHandler;
387     }
388
389     /**
390      * Factory method to create a Reader from the given InputStream.
391      */

392     protected Reader createReader(InputStream in) throws IOException {
393         return new BufferedReader(new InputStreamReader(in));
394     }
395 }
396
397 /*
398  * Redistribution and use of this software and associated documentation
399  * ("Software"), with or without modification, are permitted provided
400  * that the following conditions are met:
401  *
402  * 1. Redistributions of source code must retain copyright
403  * statements and notices. Redistributions must also contain a
404  * copy of this document.
405  *
406  * 2. Redistributions in binary form must reproduce the
407  * above copyright notice, this list of conditions and the
408  * following disclaimer in the documentation and/or other
409  * materials provided with the distribution.
410  *
411  * 3. The name "DOM4J" must not be used to endorse or promote
412  * products derived from this Software without prior written
413  * permission of MetaStuff, Ltd. For written permission,
414  * please contact dom4j-info@metastuff.com.
415  *
416  * 4. Products derived from this Software may not be called "DOM4J"
417  * nor may "DOM4J" appear in their names without prior written
418  * permission of MetaStuff, Ltd. DOM4J is a registered
419  * trademark of MetaStuff, Ltd.
420  *
421  * 5. Due credit should be given to the DOM4J Project -
422  * http://www.dom4j.org
423  *
424  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
425  * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
426  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
427  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
428  * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
429  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
430  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
431  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
432  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
433  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
434  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
435  * OF THE POSSIBILITY OF SUCH DAMAGE.
436  *
437  * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
438  *
439  * $Id: XPPPacketReader.java,v 1.10 2005/07/11 16:26:57 gaston Exp $
440  */

441
Popular Tags