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

Thu, 12 Oct 2017 19:44:07 +0800

author
aoqi
date
Thu, 12 Oct 2017 19:44:07 +0800
changeset 760
e530533619ec
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

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

mercurial