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