View Javadoc

1   /*
2    * $Id$
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.module.xml.stax;
12  
13  import javanet.staxutils.StAXReaderToContentHandler;
14  import javanet.staxutils.StAXSource;
15  import javanet.staxutils.helpers.XMLFilterImplEx;
16  
17  import javax.xml.stream.XMLStreamException;
18  import javax.xml.stream.XMLStreamReader;
19  
20  import org.xml.sax.ContentHandler;
21  import org.xml.sax.DTDHandler;
22  import org.xml.sax.EntityResolver;
23  import org.xml.sax.ErrorHandler;
24  import org.xml.sax.InputSource;
25  import org.xml.sax.SAXException;
26  import org.xml.sax.SAXNotRecognizedException;
27  import org.xml.sax.SAXNotSupportedException;
28  import org.xml.sax.SAXParseException;
29  import org.xml.sax.XMLReader;
30  import org.xml.sax.ext.LexicalHandler;
31  
32  /**
33   * A StaxSource which gives us access to the underlying XMLStreamReader if we are
34   * StaxCapable down the line.
35   */
36  public class StaxSource extends StAXSource
37  {
38  
39      private XMLStreamReader reader;
40  
41      // StAX to SAX converter that will read from StAX and produce SAX
42      // this object will be wrapped by the XMLReader exposed to the client
43      protected final StAXReaderToContentHandler handler;
44  
45      // SAX allows ContentHandler to be changed during the parsing,
46      // but JAXB doesn't. So this repeater will sit between those
47      // two components.
48      protected XMLFilterImplEx repeater = new XMLFilterImplEx();
49  
50      protected final XMLReader pseudoParser = new PseudoReader();
51  
52      public StaxSource(XMLStreamReader reader)
53      {
54          super(reader);
55  
56          this.reader = reader;
57  
58          this.handler = new XMLStreamReaderToContentHandler(reader, repeater);
59  
60          super.setXMLReader(pseudoParser);
61          // pass a dummy InputSource. We don't care
62          super.setInputSource(new InputSource());
63      }
64  
65      public XMLStreamReader getXMLStreamReader()
66      {
67          return reader;
68      }
69  
70      public final class PseudoReader implements XMLReader
71      {
72          // we will store this value but never use it by ourselves.
73          private EntityResolver entityResolver;
74          private DTDHandler dtdHandler;
75          private ErrorHandler errorHandler;
76  
77          public boolean getFeature(String name) throws SAXNotRecognizedException
78          {
79              if ("http://xml.org/sax/features/namespaces".equals(name))
80              {
81                  return true;
82              }
83              else if ("http://xml.org/sax/features/namespace-prefixes".equals(name))
84              {
85                  return repeater.getNamespacePrefixes();
86              }
87              else if ("http://xml.org/sax/features/external-general-entities".equals(name))
88              {
89                  return true;
90              }
91              else if ("http://xml.org/sax/features/external-parameter-entities".equals(name))
92              {
93                  return true;
94              }
95  
96              throw new SAXNotRecognizedException(name);
97          }
98  
99          public void setFeature(String name, boolean value)
100             throws SAXNotRecognizedException, SAXNotSupportedException
101         {
102             if ("http://xml.org/sax/features/namespaces".equals(name))
103             {
104                 // Presently we only support namespaces==true. [Issue 9]
105                 if (!value)
106                 {
107                     throw new SAXNotSupportedException(name);
108                 }
109             }
110             else if ("http://xml.org/sax/features/namespace-prefixes".equals(name))
111             {
112                 repeater.setNamespacePrefixes(value);
113             }
114             else if ("http://xml.org/sax/features/external-general-entities".equals(name))
115             {
116                 // Pass over, XOM likes to get this feature
117             }
118             else if ("http://xml.org/sax/features/external-parameter-entities".equals(name))
119             {
120                 // Pass over, XOM likes to get this feature
121             }
122             else
123             {
124                 throw new SAXNotRecognizedException(name);
125             }
126         }
127 
128         public Object getProperty(String name) throws SAXNotRecognizedException
129         {
130             if ("http://xml.org/sax/properties/lexical-handler".equals(name))
131             {
132                 return repeater.getLexicalHandler();
133             }
134 
135             throw new SAXNotRecognizedException(name);
136         }
137 
138         public void setProperty(String name, Object value) throws SAXNotRecognizedException
139         {
140             if ("http://xml.org/sax/properties/lexical-handler".equals(name))
141             {
142                 repeater.setLexicalHandler((LexicalHandler) value);
143             }
144             else
145             {
146                 throw new SAXNotRecognizedException(name);
147             }
148         }
149 
150         public void setEntityResolver(EntityResolver resolver)
151         {
152             this.entityResolver = resolver;
153         }
154 
155         public EntityResolver getEntityResolver()
156         {
157             return entityResolver;
158         }
159 
160         public void setDTDHandler(DTDHandler handler)
161         {
162             this.dtdHandler = handler;
163         }
164 
165         public DTDHandler getDTDHandler()
166         {
167             return dtdHandler;
168         }
169 
170         public void setContentHandler(ContentHandler handler)
171         {
172             repeater.setContentHandler(handler);
173         }
174 
175         public ContentHandler getContentHandler()
176         {
177             return repeater.getContentHandler();
178         }
179 
180         public void setErrorHandler(ErrorHandler handler)
181         {
182             this.errorHandler = handler;
183         }
184 
185         public ErrorHandler getErrorHandler()
186         {
187             return errorHandler;
188         }
189 
190         public void parse(InputSource input) throws SAXException
191         {
192             parse();
193         }
194 
195         public void parse(String systemId) throws SAXException
196         {
197             parse();
198         }
199 
200         public void parse() throws SAXException
201         {
202             // parses from a StAX reader and generates SAX events which
203             // go through the repeater and are forwarded to the appropriate
204             // component
205             try
206             {
207                 handler.bridge();
208             }
209             catch (XMLStreamException e)
210             {
211                 // wrap it in a SAXException
212                 SAXParseException se = new SAXParseException(e.getMessage(), null, null, e.getLocation()
213                     .getLineNumber(), e.getLocation().getColumnNumber(), e);
214 
215                 // if the consumer sets an error handler, it is our responsibility
216                 // to notify it.
217                 if (errorHandler != null) errorHandler.fatalError(se);
218 
219                 // this is a fatal error. Even if the error handler
220                 // returns, we will abort anyway.
221                 throw se;
222 
223             }
224         }
225     }
226 
227 }