src/share/jaxws_classes/com/sun/istack/internal/XMLStreamReaderToContentHandler.java

changeset 0
373ffda63c9a
child 637
9c07ef4934dd
equal deleted inserted replaced
-1:000000000000 0:373ffda63c9a
1 /*
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.istack.internal;
27
28 import org.xml.sax.ContentHandler;
29 import org.xml.sax.SAXException;
30 import org.xml.sax.Locator;
31 import org.xml.sax.Attributes;
32 import org.xml.sax.helpers.AttributesImpl;
33
34 import javax.xml.stream.XMLStreamReader;
35 import javax.xml.stream.XMLStreamException;
36 import javax.xml.stream.XMLStreamConstants;
37 import javax.xml.namespace.QName;
38
39 /**
40 * This is a simple utility class that adapts StAX events from an
41 * {@link XMLStreamReader} to SAX events on a
42 * {@link ContentHandler}, bridging between the two
43 * parser technologies.
44 *
45 * @author Ryan.Shoemaker@Sun.COM
46 * @version 1.0
47 */
48 public class XMLStreamReaderToContentHandler {
49
50 // StAX event source
51 private final XMLStreamReader staxStreamReader;
52
53 // SAX event sink
54 private final ContentHandler saxHandler;
55
56 // if true, when the conversion is completed, leave the cursor to the last
57 // event that was fired (such as end element)
58 private final boolean eagerQuit;
59
60 /**
61 * If true, not start/endDocument event.
62 */
63 private final boolean fragment;
64
65 // array of the even length of the form { prefix0, uri0, prefix1, uri1, ... }
66 private final String[] inscopeNamespaces;
67
68 /**
69 * @see #XMLStreamReaderToContentHandler(XMLStreamReader, ContentHandler, boolean, boolean, String[])
70 */
71 public XMLStreamReaderToContentHandler(XMLStreamReader staxCore, ContentHandler saxCore, boolean eagerQuit, boolean fragment) {
72 this(staxCore, saxCore, eagerQuit, fragment, new String[0]);
73 }
74
75 /**
76 * Construct a new StAX to SAX adapter that will convert a StAX event
77 * stream into a SAX event stream.
78 *
79 * @param staxCore
80 * StAX event source
81 * @param saxCore
82 * SAXevent sink
83 * @param eagerQuit
84 * @param fragment
85 * @param inscopeNamespaces
86 * array of the even length of the form { prefix0, uri0, prefix1, uri1, ... }
87 */
88 public XMLStreamReaderToContentHandler(XMLStreamReader staxCore, ContentHandler saxCore,
89 boolean eagerQuit, boolean fragment, String[] inscopeNamespaces) {
90 this.staxStreamReader = staxCore;
91 this.saxHandler = saxCore;
92 this.eagerQuit = eagerQuit;
93 this.fragment = fragment;
94 this.inscopeNamespaces = inscopeNamespaces;
95 assert inscopeNamespaces.length%2 == 0;
96 }
97
98
99 /*
100 * @see StAXReaderToContentHandler#bridge()
101 */
102 public void bridge() throws XMLStreamException {
103
104 try {
105 // remembers the nest level of elements to know when we are done.
106 int depth=0;
107
108 // if the parser is at the start tag, proceed to the first element
109 int event = staxStreamReader.getEventType();
110 if(event == XMLStreamConstants.START_DOCUMENT) {
111 // nextTag doesn't correctly handle DTDs
112 while( !staxStreamReader.isStartElement() )
113 event = staxStreamReader.next();
114 }
115
116
117 if( event!=XMLStreamConstants.START_ELEMENT)
118 throw new IllegalStateException("The current event is not START_ELEMENT\n but " + event);
119
120 handleStartDocument();
121
122 for(int i=0; i < inscopeNamespaces.length; i+=2) {
123 saxHandler.startPrefixMapping(inscopeNamespaces[i], inscopeNamespaces[i+1]);
124 }
125
126 OUTER:
127 do {
128 // These are all of the events listed in the javadoc for
129 // XMLEvent.
130 // The spec only really describes 11 of them.
131 switch (event) {
132 case XMLStreamConstants.START_ELEMENT :
133 depth++;
134 handleStartElement();
135 break;
136 case XMLStreamConstants.END_ELEMENT :
137 handleEndElement();
138 depth--;
139 if(depth==0 && eagerQuit)
140 break OUTER;
141 break;
142 case XMLStreamConstants.CHARACTERS :
143 handleCharacters();
144 break;
145 case XMLStreamConstants.ENTITY_REFERENCE :
146 handleEntityReference();
147 break;
148 case XMLStreamConstants.PROCESSING_INSTRUCTION :
149 handlePI();
150 break;
151 case XMLStreamConstants.COMMENT :
152 handleComment();
153 break;
154 case XMLStreamConstants.DTD :
155 handleDTD();
156 break;
157 case XMLStreamConstants.ATTRIBUTE :
158 handleAttribute();
159 break;
160 case XMLStreamConstants.NAMESPACE :
161 handleNamespace();
162 break;
163 case XMLStreamConstants.CDATA :
164 handleCDATA();
165 break;
166 case XMLStreamConstants.ENTITY_DECLARATION :
167 handleEntityDecl();
168 break;
169 case XMLStreamConstants.NOTATION_DECLARATION :
170 handleNotationDecl();
171 break;
172 case XMLStreamConstants.SPACE :
173 handleSpace();
174 break;
175 default :
176 throw new InternalError("processing event: " + event);
177 }
178
179 event=staxStreamReader.next();
180 } while (depth!=0);
181
182 for(int i=0; i < inscopeNamespaces.length; i+=2) {
183 saxHandler.endPrefixMapping(inscopeNamespaces[i]);
184 }
185
186 handleEndDocument();
187 } catch (SAXException e) {
188 throw new XMLStreamException2(e);
189 }
190 }
191
192 private void handleEndDocument() throws SAXException {
193 if(fragment)
194 return;
195
196 saxHandler.endDocument();
197 }
198
199 private void handleStartDocument() throws SAXException {
200 if(fragment)
201 return;
202
203 saxHandler.setDocumentLocator(new Locator() {
204 public int getColumnNumber() {
205 return staxStreamReader.getLocation().getColumnNumber();
206 }
207 public int getLineNumber() {
208 return staxStreamReader.getLocation().getLineNumber();
209 }
210 public String getPublicId() {
211 return staxStreamReader.getLocation().getPublicId();
212 }
213 public String getSystemId() {
214 return staxStreamReader.getLocation().getSystemId();
215 }
216 });
217 saxHandler.startDocument();
218 }
219
220 private void handlePI() throws XMLStreamException {
221 try {
222 saxHandler.processingInstruction(
223 staxStreamReader.getPITarget(),
224 staxStreamReader.getPIData());
225 } catch (SAXException e) {
226 throw new XMLStreamException2(e);
227 }
228 }
229
230 private void handleCharacters() throws XMLStreamException {
231 try {
232 saxHandler.characters(
233 staxStreamReader.getTextCharacters(),
234 staxStreamReader.getTextStart(),
235 staxStreamReader.getTextLength() );
236 } catch (SAXException e) {
237 throw new XMLStreamException2(e);
238 }
239 }
240
241 private void handleEndElement() throws XMLStreamException {
242 QName qName = staxStreamReader.getName();
243
244 try {
245 String pfix = qName.getPrefix();
246 String rawname = (pfix == null || pfix.length() == 0)
247 ? qName.getLocalPart()
248 : pfix + ':' + qName.getLocalPart();
249 // fire endElement
250 saxHandler.endElement(
251 qName.getNamespaceURI(),
252 qName.getLocalPart(),
253 rawname);
254
255 // end namespace bindings
256 int nsCount = staxStreamReader.getNamespaceCount();
257 for (int i = nsCount - 1; i >= 0; i--) {
258 String prefix = staxStreamReader.getNamespacePrefix(i);
259 if (prefix == null) { // true for default namespace
260 prefix = "";
261 }
262 saxHandler.endPrefixMapping(prefix);
263 }
264 } catch (SAXException e) {
265 throw new XMLStreamException2(e);
266 }
267 }
268
269 private void handleStartElement() throws XMLStreamException {
270
271 try {
272 // start namespace bindings
273 int nsCount = staxStreamReader.getNamespaceCount();
274 for (int i = 0; i < nsCount; i++) {
275 saxHandler.startPrefixMapping(
276 fixNull(staxStreamReader.getNamespacePrefix(i)),
277 fixNull(staxStreamReader.getNamespaceURI(i)));
278 }
279
280 // fire startElement
281 QName qName = staxStreamReader.getName();
282 String prefix = qName.getPrefix();
283 String rawname;
284 if(prefix==null || prefix.length()==0)
285 rawname = qName.getLocalPart();
286 else
287 rawname = prefix + ':' + qName.getLocalPart();
288 Attributes attrs = getAttributes();
289 saxHandler.startElement(
290 qName.getNamespaceURI(),
291 qName.getLocalPart(),
292 rawname,
293 attrs);
294 } catch (SAXException e) {
295 throw new XMLStreamException2(e);
296 }
297 }
298
299 private static String fixNull(String s) {
300 if(s==null) return "";
301 else return s;
302 }
303
304 /**
305 * Get the attributes associated with the given START_ELEMENT or ATTRIBUTE
306 * StAXevent.
307 *
308 * @return the StAX attributes converted to an org.xml.sax.Attributes
309 */
310 private Attributes getAttributes() {
311 AttributesImpl attrs = new AttributesImpl();
312
313 int eventType = staxStreamReader.getEventType();
314 if (eventType != XMLStreamConstants.ATTRIBUTE
315 && eventType != XMLStreamConstants.START_ELEMENT) {
316 throw new InternalError(
317 "getAttributes() attempting to process: " + eventType);
318 }
319
320 // in SAX, namespace declarations are not part of attributes by default.
321 // (there's a property to control that, but as far as we are concerned
322 // we don't use it.) So don't add xmlns:* to attributes.
323
324 // gather non-namespace attrs
325 for (int i = 0; i < staxStreamReader.getAttributeCount(); i++) {
326 String uri = staxStreamReader.getAttributeNamespace(i);
327 if(uri==null) uri="";
328 String localName = staxStreamReader.getAttributeLocalName(i);
329 String prefix = staxStreamReader.getAttributePrefix(i);
330 String qName;
331 if(prefix==null || prefix.length()==0)
332 qName = localName;
333 else
334 qName = prefix + ':' + localName;
335 String type = staxStreamReader.getAttributeType(i);
336 String value = staxStreamReader.getAttributeValue(i);
337
338 attrs.addAttribute(uri, localName, qName, type, value);
339 }
340
341 return attrs;
342 }
343
344 private void handleNamespace() {
345 // no-op ???
346 // namespace events don't normally occur outside of a startElement
347 // or endElement
348 }
349
350 private void handleAttribute() {
351 // no-op ???
352 // attribute events don't normally occur outside of a startElement
353 // or endElement
354 }
355
356 private void handleDTD() {
357 // no-op ???
358 // it seems like we need to pass this info along, but how?
359 }
360
361 private void handleComment() {
362 // no-op ???
363 }
364
365 private void handleEntityReference() {
366 // no-op ???
367 }
368
369 private void handleSpace() {
370 // no-op ???
371 // this event is listed in the javadoc, but not in the spec.
372 }
373
374 private void handleNotationDecl() {
375 // no-op ???
376 // this event is listed in the javadoc, but not in the spec.
377 }
378
379 private void handleEntityDecl() {
380 // no-op ???
381 // this event is listed in the javadoc, but not in the spec.
382 }
383
384 private void handleCDATA() {
385 // no-op ???
386 // this event is listed in the javadoc, but not in the spec.
387 }
388 }

mercurial