src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StAXEventConnector.java

changeset 0
373ffda63c9a
equal deleted inserted replaced
-1:000000000000 0:373ffda63c9a
1 /*
2 * Copyright (c) 1997, 2011, 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.xml.internal.bind.v2.runtime.unmarshaller;
27
28 import java.util.Iterator;
29
30 import javax.xml.namespace.QName;
31 import javax.xml.stream.Location;
32 import javax.xml.stream.XMLEventReader;
33 import javax.xml.stream.XMLStreamConstants;
34 import javax.xml.stream.XMLStreamException;
35 import javax.xml.stream.events.Attribute;
36 import javax.xml.stream.events.Characters;
37 import javax.xml.stream.events.EndElement;
38 import javax.xml.stream.events.Namespace;
39 import javax.xml.stream.events.StartElement;
40 import javax.xml.stream.events.XMLEvent;
41
42 import org.xml.sax.Attributes;
43 import org.xml.sax.SAXException;
44 import org.xml.sax.helpers.AttributesImpl;
45
46 /**
47 * This is a simple utility class that adapts StAX events from an
48 * {@link XMLEventReader} to unmarshaller events on a
49 * {@link XmlVisitor}, bridging between the two
50 * parser technologies.
51 *
52 * @author Ryan.Shoemaker@Sun.COM
53 * @version 1.0
54 */
55 final class StAXEventConnector extends StAXConnector {
56
57 // StAX event source
58 private final XMLEventReader staxEventReader;
59
60 /** Current event. */
61 private XMLEvent event;
62
63 /**
64 * Shared and reused {@link Attributes}.
65 */
66 private final AttributesImpl attrs = new AttributesImpl();
67
68 /**
69 * SAX may fire consective characters event, but we don't allow it.
70 * so use this buffer to perform buffering.
71 */
72 private final StringBuilder buffer = new StringBuilder();
73
74 private boolean seenText;
75
76 /**
77 * Construct a new StAX to SAX adapter that will convert a StAX event
78 * stream into a SAX event stream.
79 *
80 * @param staxCore
81 * StAX event source
82 * @param visitor
83 * sink
84 */
85 public StAXEventConnector(XMLEventReader staxCore, XmlVisitor visitor) {
86 super(visitor);
87 staxEventReader = staxCore;
88 }
89
90 public void bridge() throws XMLStreamException {
91
92 try {
93 // remembers the nest level of elements to know when we are done.
94 int depth=0;
95
96 event = staxEventReader.peek();
97
98 if( !event.isStartDocument() && !event.isStartElement() )
99 throw new IllegalStateException();
100
101 // if the parser is on START_DOCUMENT, skip ahead to the first element
102 do {
103 event = staxEventReader.nextEvent();
104 } while( !event.isStartElement() );
105
106 handleStartDocument(event.asStartElement().getNamespaceContext());
107
108 OUTER:
109 while(true) {
110 // These are all of the events listed in the javadoc for
111 // XMLEvent.
112 // The spec only really describes 11 of them.
113 switch (event.getEventType()) {
114 case XMLStreamConstants.START_ELEMENT :
115 handleStartElement(event.asStartElement());
116 depth++;
117 break;
118 case XMLStreamConstants.END_ELEMENT :
119 depth--;
120 handleEndElement(event.asEndElement());
121 if(depth==0) break OUTER;
122 break;
123 case XMLStreamConstants.CHARACTERS :
124 case XMLStreamConstants.CDATA :
125 case XMLStreamConstants.SPACE :
126 handleCharacters(event.asCharacters());
127 break;
128 }
129
130
131 event=staxEventReader.nextEvent();
132 }
133
134 handleEndDocument();
135 event = null; // avoid keeping a stale reference
136 } catch (SAXException e) {
137 throw new XMLStreamException(e);
138 }
139 }
140
141 protected Location getCurrentLocation() {
142 return event.getLocation();
143 }
144
145 protected String getCurrentQName() {
146 QName qName;
147 if(event.isEndElement())
148 qName = event.asEndElement().getName();
149 else
150 qName = event.asStartElement().getName();
151 return getQName(qName.getPrefix(), qName.getLocalPart());
152 }
153
154
155 private void handleCharacters(Characters event) throws SAXException, XMLStreamException {
156 if(!predictor.expectText())
157 return; // text isn't expected. simply skip
158
159 seenText = true;
160
161 // check the next event
162 XMLEvent next;
163 while(true) {
164 next = staxEventReader.peek();
165 if(!isIgnorable(next))
166 break;
167 staxEventReader.nextEvent();
168 }
169
170 if(isTag(next)) {
171 // this is by far the common case --- you have <foo>abc</foo> or <foo>abc<bar/>...</foo>
172 visitor.text(event.getData());
173 return;
174 }
175
176 // otherwise we have things like "abc<!-- test -->def".
177 // concatenate all text
178 buffer.append(event.getData());
179
180 while(true) {
181 while(true) {
182 next = staxEventReader.peek();
183 if(!isIgnorable(next))
184 break;
185 staxEventReader.nextEvent();
186 }
187
188 if(isTag(next)) {
189 // found all adjacent text
190 visitor.text(buffer);
191 buffer.setLength(0);
192 return;
193 }
194
195 buffer.append(next.asCharacters().getData());
196 staxEventReader.nextEvent(); // consume
197 }
198 }
199
200 private boolean isTag(XMLEvent event) {
201 int eventType = event.getEventType();
202 return eventType==XMLEvent.START_ELEMENT || eventType==XMLEvent.END_ELEMENT;
203 }
204
205 private boolean isIgnorable(XMLEvent event) {
206 int eventType = event.getEventType();
207 return eventType==XMLEvent.COMMENT || eventType==XMLEvent.PROCESSING_INSTRUCTION;
208 }
209
210 private void handleEndElement(EndElement event) throws SAXException {
211 if(!seenText && predictor.expectText()) {
212 visitor.text("");
213 }
214
215 // fire endElement
216 QName qName = event.getName();
217 tagName.uri = fixNull(qName.getNamespaceURI());
218 tagName.local = qName.getLocalPart();
219 visitor.endElement(tagName);
220
221 // end namespace bindings
222 for( Iterator<Namespace> i = event.getNamespaces(); i.hasNext();) {
223 String prefix = fixNull(i.next().getPrefix()); // be defensive
224 visitor.endPrefixMapping(prefix);
225 }
226
227 seenText = false;
228 }
229
230 private void handleStartElement(StartElement event) throws SAXException {
231 // start namespace bindings
232 for (Iterator i = event.getNamespaces(); i.hasNext();) {
233 Namespace ns = (Namespace)i.next();
234 visitor.startPrefixMapping(
235 fixNull(ns.getPrefix()),
236 fixNull(ns.getNamespaceURI()));
237 }
238
239 // fire startElement
240 QName qName = event.getName();
241 tagName.uri = fixNull(qName.getNamespaceURI());
242 String localName = qName.getLocalPart();
243 tagName.uri = fixNull(qName.getNamespaceURI());
244 tagName.local = localName;
245 tagName.atts = getAttributes(event);
246 visitor.startElement(tagName);
247
248 seenText = false;
249 }
250
251
252
253 /**
254 * Get the attributes associated with the given START_ELEMENT StAXevent.
255 *
256 * @return the StAX attributes converted to an org.xml.sax.Attributes
257 */
258 private Attributes getAttributes(StartElement event) {
259 attrs.clear();
260
261 // in SAX, namespace declarations are not part of attributes by default.
262 // (there's a property to control that, but as far as we are concerned
263 // we don't use it.) So don't add xmlns:* to attributes.
264
265 // gather non-namespace attrs
266 for (Iterator i = event.getAttributes(); i.hasNext();) {
267 Attribute staxAttr = (Attribute)i.next();
268
269 QName name = staxAttr.getName();
270 String uri = fixNull(name.getNamespaceURI());
271 String localName = name.getLocalPart();
272 String prefix = name.getPrefix();
273 String qName;
274 if (prefix == null || prefix.length() == 0)
275 qName = localName;
276 else
277 qName = prefix + ':' + localName;
278 String type = staxAttr.getDTDType();
279 String value = staxAttr.getValue();
280
281 attrs.addAttribute(uri, localName, qName, type, value);
282 }
283
284 return attrs;
285 }
286 }

mercurial