--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/XMLStreamReaderToContentHandler.java Tue Mar 06 16:09:35 2012 -0800
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.istack.internal;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.Locator;
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.AttributesImpl;
+
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.namespace.QName;
+
+/**
+ * This is a simple utility class that adapts StAX events from an
+ * {@link XMLStreamReader} to SAX events on a
+ * {@link ContentHandler}, bridging between the two
+ * parser technologies.
+ *
+ * @author Ryan.Shoemaker@Sun.COM
+ * @version 1.0
+ */
+public class XMLStreamReaderToContentHandler {
+
+ // StAX event source
+ private final XMLStreamReader staxStreamReader;
+
+ // SAX event sink
+ private final ContentHandler saxHandler;
+
+ // if true, when the conversion is completed, leave the cursor to the last
+ // event that was fired (such as end element)
+ private final boolean eagerQuit;
+
+ /**
+ * If true, not start/endDocument event.
+ */
+ private final boolean fragment;
+
+ // array of the even length of the form { prefix0, uri0, prefix1, uri1, ... }
+ private final String[] inscopeNamespaces;
+
+ /**
+ * @see #XMLStreamReaderToContentHandler(XMLStreamReader, ContentHandler, boolean, boolean, String[])
+ */
+ public XMLStreamReaderToContentHandler(XMLStreamReader staxCore, ContentHandler saxCore, boolean eagerQuit, boolean fragment) {
+ this(staxCore, saxCore, eagerQuit, fragment, new String[0]);
+ }
+
+ /**
+ * Construct a new StAX to SAX adapter that will convert a StAX event
+ * stream into a SAX event stream.
+ *
+ * @param staxCore
+ * StAX event source
+ * @param saxCore
+ * SAXevent sink
+ * @param eagerQuit
+ * @param fragment
+ * @param inscopeNamespaces
+ * array of the even length of the form { prefix0, uri0, prefix1, uri1, ... }
+ */
+ public XMLStreamReaderToContentHandler(XMLStreamReader staxCore, ContentHandler saxCore,
+ boolean eagerQuit, boolean fragment, String[] inscopeNamespaces) {
+ this.staxStreamReader = staxCore;
+ this.saxHandler = saxCore;
+ this.eagerQuit = eagerQuit;
+ this.fragment = fragment;
+ this.inscopeNamespaces = inscopeNamespaces;
+ assert inscopeNamespaces.length%2 == 0;
+ }
+
+
+ /*
+ * @see StAXReaderToContentHandler#bridge()
+ */
+ public void bridge() throws XMLStreamException {
+
+ try {
+ // remembers the nest level of elements to know when we are done.
+ int depth=0;
+
+ // if the parser is at the start tag, proceed to the first element
+ int event = staxStreamReader.getEventType();
+ if(event == XMLStreamConstants.START_DOCUMENT) {
+ // nextTag doesn't correctly handle DTDs
+ while( !staxStreamReader.isStartElement() )
+ event = staxStreamReader.next();
+ }
+
+
+ if( event!=XMLStreamConstants.START_ELEMENT)
+ throw new IllegalStateException("The current event is not START_ELEMENT\n but " + event);
+
+ handleStartDocument();
+
+ for(int i=0; i < inscopeNamespaces.length; i+=2) {
+ saxHandler.startPrefixMapping(inscopeNamespaces[i], inscopeNamespaces[i+1]);
+ }
+
+ OUTER:
+ do {
+ // These are all of the events listed in the javadoc for
+ // XMLEvent.
+ // The spec only really describes 11 of them.
+ switch (event) {
+ case XMLStreamConstants.START_ELEMENT :
+ depth++;
+ handleStartElement();
+ break;
+ case XMLStreamConstants.END_ELEMENT :
+ handleEndElement();
+ depth--;
+ if(depth==0 && eagerQuit)
+ break OUTER;
+ break;
+ case XMLStreamConstants.CHARACTERS :
+ handleCharacters();
+ break;
+ case XMLStreamConstants.ENTITY_REFERENCE :
+ handleEntityReference();
+ break;
+ case XMLStreamConstants.PROCESSING_INSTRUCTION :
+ handlePI();
+ break;
+ case XMLStreamConstants.COMMENT :
+ handleComment();
+ break;
+ case XMLStreamConstants.DTD :
+ handleDTD();
+ break;
+ case XMLStreamConstants.ATTRIBUTE :
+ handleAttribute();
+ break;
+ case XMLStreamConstants.NAMESPACE :
+ handleNamespace();
+ break;
+ case XMLStreamConstants.CDATA :
+ handleCDATA();
+ break;
+ case XMLStreamConstants.ENTITY_DECLARATION :
+ handleEntityDecl();
+ break;
+ case XMLStreamConstants.NOTATION_DECLARATION :
+ handleNotationDecl();
+ break;
+ case XMLStreamConstants.SPACE :
+ handleSpace();
+ break;
+ default :
+ throw new InternalError("processing event: " + event);
+ }
+
+ event=staxStreamReader.next();
+ } while (depth!=0);
+
+ for(int i=0; i < inscopeNamespaces.length; i+=2) {
+ saxHandler.endPrefixMapping(inscopeNamespaces[i]);
+ }
+
+ handleEndDocument();
+ } catch (SAXException e) {
+ throw new XMLStreamException2(e);
+ }
+ }
+
+ private void handleEndDocument() throws SAXException {
+ if(fragment)
+ return;
+
+ saxHandler.endDocument();
+ }
+
+ private void handleStartDocument() throws SAXException {
+ if(fragment)
+ return;
+
+ saxHandler.setDocumentLocator(new Locator() {
+ public int getColumnNumber() {
+ return staxStreamReader.getLocation().getColumnNumber();
+ }
+ public int getLineNumber() {
+ return staxStreamReader.getLocation().getLineNumber();
+ }
+ public String getPublicId() {
+ return staxStreamReader.getLocation().getPublicId();
+ }
+ public String getSystemId() {
+ return staxStreamReader.getLocation().getSystemId();
+ }
+ });
+ saxHandler.startDocument();
+ }
+
+ private void handlePI() throws XMLStreamException {
+ try {
+ saxHandler.processingInstruction(
+ staxStreamReader.getPITarget(),
+ staxStreamReader.getPIData());
+ } catch (SAXException e) {
+ throw new XMLStreamException2(e);
+ }
+ }
+
+ private void handleCharacters() throws XMLStreamException {
+ try {
+ saxHandler.characters(
+ staxStreamReader.getTextCharacters(),
+ staxStreamReader.getTextStart(),
+ staxStreamReader.getTextLength() );
+ } catch (SAXException e) {
+ throw new XMLStreamException2(e);
+ }
+ }
+
+ private void handleEndElement() throws XMLStreamException {
+ QName qName = staxStreamReader.getName();
+
+ try {
+ String pfix = qName.getPrefix();
+ String rawname = (pfix == null || pfix.length() == 0)
+ ? qName.getLocalPart()
+ : pfix + ':' + qName.getLocalPart();
+ // fire endElement
+ saxHandler.endElement(
+ qName.getNamespaceURI(),
+ qName.getLocalPart(),
+ rawname);
+
+ // end namespace bindings
+ int nsCount = staxStreamReader.getNamespaceCount();
+ for (int i = nsCount - 1; i >= 0; i--) {
+ String prefix = staxStreamReader.getNamespacePrefix(i);
+ if (prefix == null) { // true for default namespace
+ prefix = "";
+ }
+ saxHandler.endPrefixMapping(prefix);
+ }
+ } catch (SAXException e) {
+ throw new XMLStreamException2(e);
+ }
+ }
+
+ private void handleStartElement() throws XMLStreamException {
+
+ try {
+ // start namespace bindings
+ int nsCount = staxStreamReader.getNamespaceCount();
+ for (int i = 0; i < nsCount; i++) {
+ saxHandler.startPrefixMapping(
+ fixNull(staxStreamReader.getNamespacePrefix(i)),
+ fixNull(staxStreamReader.getNamespaceURI(i)));
+ }
+
+ // fire startElement
+ QName qName = staxStreamReader.getName();
+ String prefix = qName.getPrefix();
+ String rawname;
+ if(prefix==null || prefix.length()==0)
+ rawname = qName.getLocalPart();
+ else
+ rawname = prefix + ':' + qName.getLocalPart();
+ Attributes attrs = getAttributes();
+ saxHandler.startElement(
+ qName.getNamespaceURI(),
+ qName.getLocalPart(),
+ rawname,
+ attrs);
+ } catch (SAXException e) {
+ throw new XMLStreamException2(e);
+ }
+ }
+
+ private static String fixNull(String s) {
+ if(s==null) return "";
+ else return s;
+ }
+
+ /**
+ * Get the attributes associated with the given START_ELEMENT or ATTRIBUTE
+ * StAXevent.
+ *
+ * @return the StAX attributes converted to an org.xml.sax.Attributes
+ */
+ private Attributes getAttributes() {
+ AttributesImpl attrs = new AttributesImpl();
+
+ int eventType = staxStreamReader.getEventType();
+ if (eventType != XMLStreamConstants.ATTRIBUTE
+ && eventType != XMLStreamConstants.START_ELEMENT) {
+ throw new InternalError(
+ "getAttributes() attempting to process: " + eventType);
+ }
+
+ // in SAX, namespace declarations are not part of attributes by default.
+ // (there's a property to control that, but as far as we are concerned
+ // we don't use it.) So don't add xmlns:* to attributes.
+
+ // gather non-namespace attrs
+ for (int i = 0; i < staxStreamReader.getAttributeCount(); i++) {
+ String uri = staxStreamReader.getAttributeNamespace(i);
+ if(uri==null) uri="";
+ String localName = staxStreamReader.getAttributeLocalName(i);
+ String prefix = staxStreamReader.getAttributePrefix(i);
+ String qName;
+ if(prefix==null || prefix.length()==0)
+ qName = localName;
+ else
+ qName = prefix + ':' + localName;
+ String type = staxStreamReader.getAttributeType(i);
+ String value = staxStreamReader.getAttributeValue(i);
+
+ attrs.addAttribute(uri, localName, qName, type, value);
+ }
+
+ return attrs;
+ }
+
+ private void handleNamespace() {
+ // no-op ???
+ // namespace events don't normally occur outside of a startElement
+ // or endElement
+ }
+
+ private void handleAttribute() {
+ // no-op ???
+ // attribute events don't normally occur outside of a startElement
+ // or endElement
+ }
+
+ private void handleDTD() {
+ // no-op ???
+ // it seems like we need to pass this info along, but how?
+ }
+
+ private void handleComment() {
+ // no-op ???
+ }
+
+ private void handleEntityReference() {
+ // no-op ???
+ }
+
+ private void handleSpace() {
+ // no-op ???
+ // this event is listed in the javadoc, but not in the spec.
+ }
+
+ private void handleNotationDecl() {
+ // no-op ???
+ // this event is listed in the javadoc, but not in the spec.
+ }
+
+ private void handleEntityDecl() {
+ // no-op ???
+ // this event is listed in the javadoc, but not in the spec.
+ }
+
+ private void handleCDATA() {
+ // no-op ???
+ // this event is listed in the javadoc, but not in the spec.
+ }
+}