| /* |
| * Copyright (c) 2005, 2015, 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.org.apache.xalan.internal.xsltc.trax; |
| |
| import java.io.IOException; |
| import java.util.Iterator; |
| |
| import org.xml.sax.Attributes; |
| import org.xml.sax.ContentHandler; |
| import org.xml.sax.DTDHandler; |
| import org.xml.sax.EntityResolver; |
| import org.xml.sax.ErrorHandler; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.Locator; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXNotRecognizedException; |
| import org.xml.sax.SAXNotSupportedException; |
| import org.xml.sax.XMLReader; |
| import org.xml.sax.ext.LexicalHandler; |
| import org.xml.sax.helpers.AttributesImpl; |
| import org.xml.sax.ext.Locator2; |
| import com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl; |
| |
| import javax.xml.namespace.QName; |
| import javax.xml.stream.XMLEventReader; |
| import javax.xml.stream.XMLStreamConstants; |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.events.Attribute; |
| import javax.xml.stream.events.Characters; |
| import javax.xml.stream.events.EndElement; |
| import javax.xml.stream.events.Namespace; |
| import javax.xml.stream.events.ProcessingInstruction; |
| import javax.xml.stream.events.StartElement; |
| import javax.xml.stream.events.XMLEvent; |
| import javax.xml.stream.events.StartDocument; |
| |
| |
| /** |
| * @author Suresh Kumar |
| * @author Sunitha Reddy |
| * @since 1.6 |
| */ |
| public class StAXEvent2SAX implements XMLReader, Locator { |
| |
| //private final static String EMPTYSTRING = ""; |
| //private static final String XMLNS_PREFIX = "xmlns"; |
| |
| // StAX event source |
| private final XMLEventReader staxEventReader; |
| |
| //private Node _dom = null; |
| private ContentHandler _sax = null; |
| private LexicalHandler _lex = null; |
| private SAXImpl _saxImpl = null; |
| private String version = null; |
| private String encoding = null; |
| |
| |
| public StAXEvent2SAX(XMLEventReader staxCore) { |
| staxEventReader = staxCore; |
| } |
| |
| public ContentHandler getContentHandler() { |
| return _sax; |
| } |
| |
| public void setContentHandler(ContentHandler handler) throws |
| NullPointerException |
| { |
| _sax = handler; |
| if (handler instanceof LexicalHandler) { |
| _lex = (LexicalHandler) handler; |
| } |
| |
| if (handler instanceof SAXImpl) { |
| _saxImpl = (SAXImpl)handler; |
| } |
| } |
| |
| |
| public void parse(InputSource unused) throws IOException, SAXException { |
| try { |
| bridge(); |
| } catch (XMLStreamException e) { |
| throw new SAXException(e); |
| } |
| } |
| |
| |
| //Main Work Starts Here. |
| public void parse() throws IOException, SAXException, XMLStreamException { |
| bridge(); |
| } |
| |
| |
| /* public void parse() throws IOException, SAXException { |
| if (_dom != null) { |
| boolean isIncomplete = |
| (_dom.getNodeType() != org.w3c.dom.Node.DOCUMENT_NODE); |
| |
| if (isIncomplete) { |
| _sax.startDocument(); |
| parse(_dom); |
| _sax.endDocument(); |
| } |
| else { |
| parse(_dom); |
| } |
| } |
| } |
| */ |
| |
| /* |
| * @see StAXReaderToContentHandler#bridge() |
| */ |
| private void bridge() throws XMLStreamException { |
| |
| try { |
| // remembers the nest level of elements to know when we are done. |
| int depth=0; |
| boolean startedAtDocument = false; |
| |
| XMLEvent event = staxEventReader.peek(); |
| |
| if (!event.isStartDocument() && !event.isStartElement()) { |
| throw new IllegalStateException(); |
| } |
| |
| if (event.getEventType() == XMLStreamConstants.START_DOCUMENT){ |
| startedAtDocument = true; |
| version = ((StartDocument)event).getVersion(); |
| if (((StartDocument)event).encodingSet()) |
| encoding = ((StartDocument)event).getCharacterEncodingScheme(); |
| event=staxEventReader.nextEvent(); // that gets the one we peeked at |
| event=staxEventReader.nextEvent(); // that really gets the next one |
| } |
| |
| handleStartDocument(event); |
| |
| // Handle the prolog: http://www.w3.org/TR/REC-xml/#NT-prolog |
| while (event.getEventType() != XMLStreamConstants.START_ELEMENT) { |
| switch (event.getEventType()) { |
| case XMLStreamConstants.CHARACTERS : |
| handleCharacters(event.asCharacters()); |
| break; |
| case XMLStreamConstants.PROCESSING_INSTRUCTION : |
| handlePI((ProcessingInstruction)event); |
| break; |
| case XMLStreamConstants.COMMENT : |
| handleComment(); |
| break; |
| case XMLStreamConstants.DTD : |
| handleDTD(); |
| break; |
| case XMLStreamConstants.SPACE : |
| handleSpace(); |
| break; |
| default : |
| throw new InternalError("processing prolog event: " + event); |
| } |
| event=staxEventReader.nextEvent(); |
| } |
| |
| // Process the (document) element |
| do { |
| // These are all of the events listed in the javadoc for |
| // XMLEvent. |
| // The spec only really describes 11 of them. |
| switch (event.getEventType()) { |
| case XMLStreamConstants.START_ELEMENT : |
| depth++; |
| handleStartElement(event.asStartElement()); |
| break; |
| case XMLStreamConstants.END_ELEMENT : |
| handleEndElement(event.asEndElement()); |
| depth--; |
| break; |
| case XMLStreamConstants.CHARACTERS : |
| handleCharacters(event.asCharacters()); |
| break; |
| case XMLStreamConstants.ENTITY_REFERENCE : |
| handleEntityReference(); |
| break; |
| case XMLStreamConstants.PROCESSING_INSTRUCTION : |
| handlePI((ProcessingInstruction)event); |
| 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=staxEventReader.nextEvent(); |
| } while (depth!=0); |
| |
| if (startedAtDocument) { |
| // Handle the Misc (http://www.w3.org/TR/REC-xml/#NT-Misc) that can follow the document element |
| while (event.getEventType() != XMLStreamConstants.END_DOCUMENT) { |
| switch (event.getEventType()) { |
| case XMLStreamConstants.CHARACTERS : |
| handleCharacters(event.asCharacters()); |
| break; |
| case XMLStreamConstants.PROCESSING_INSTRUCTION : |
| handlePI((ProcessingInstruction)event); |
| break; |
| case XMLStreamConstants.COMMENT : |
| handleComment(); |
| break; |
| case XMLStreamConstants.SPACE : |
| handleSpace(); |
| break; |
| default : |
| throw new InternalError("processing misc event after document element: " + event); |
| } |
| event=staxEventReader.nextEvent(); |
| } |
| } |
| |
| handleEndDocument(); |
| } catch (SAXException e) { |
| throw new XMLStreamException(e); |
| } |
| } |
| |
| |
| private void handleEndDocument() throws SAXException { |
| _sax.endDocument(); |
| } |
| |
| private void handleStartDocument(final XMLEvent event) throws SAXException { |
| _sax.setDocumentLocator(new Locator2() { |
| public int getColumnNumber() { |
| return event.getLocation().getColumnNumber(); |
| } |
| public int getLineNumber() { |
| return event.getLocation().getLineNumber(); |
| } |
| public String getPublicId() { |
| return event.getLocation().getPublicId(); |
| } |
| public String getSystemId() { |
| return event.getLocation().getSystemId(); |
| } |
| public String getXMLVersion(){ |
| return version; |
| } |
| public String getEncoding(){ |
| return encoding; |
| } |
| |
| }); |
| _sax.startDocument(); |
| } |
| |
| private void handlePI(ProcessingInstruction event) |
| throws XMLStreamException { |
| try { |
| _sax.processingInstruction( |
| event.getTarget(), |
| event.getData()); |
| } catch (SAXException e) { |
| throw new XMLStreamException(e); |
| } |
| } |
| |
| private void handleCharacters(Characters event) throws XMLStreamException { |
| try { |
| _sax.characters( |
| event.getData().toCharArray(), |
| 0, |
| event.getData().length()); |
| } catch (SAXException e) { |
| throw new XMLStreamException(e); |
| } |
| } |
| |
| private void handleEndElement(EndElement event) throws XMLStreamException { |
| QName qName = event.getName(); |
| |
| //construct prefix:localName from qName |
| String qname = ""; |
| if (qName.getPrefix() != null && qName.getPrefix().trim().length() != 0){ |
| qname = qName.getPrefix() + ":"; |
| } |
| qname += qName.getLocalPart(); |
| |
| try { |
| // fire endElement |
| _sax.endElement( |
| qName.getNamespaceURI(), |
| qName.getLocalPart(), |
| qname); |
| |
| // end namespace bindings |
| for( Iterator i = event.getNamespaces(); i.hasNext();) { |
| String prefix = (String)i.next(); |
| if( prefix == null ) { // true for default namespace |
| prefix = ""; |
| } |
| _sax.endPrefixMapping(prefix); |
| } |
| } catch (SAXException e) { |
| throw new XMLStreamException(e); |
| } |
| } |
| |
| private void handleStartElement(StartElement event) |
| throws XMLStreamException { |
| try { |
| // start namespace bindings |
| for (Iterator i = event.getNamespaces(); i.hasNext();) { |
| String prefix = ((Namespace)i.next()).getPrefix(); |
| if (prefix == null) { // true for default namespace |
| prefix = ""; |
| } |
| _sax.startPrefixMapping( |
| prefix, |
| event.getNamespaceURI(prefix)); |
| } |
| |
| // fire startElement |
| QName qName = event.getName(); |
| String prefix = qName.getPrefix(); |
| String rawname; |
| if (prefix == null || prefix.length() == 0) { |
| rawname = qName.getLocalPart(); |
| } else { |
| rawname = prefix + ':' + qName.getLocalPart(); |
| } |
| |
| Attributes saxAttrs = getAttributes(event); |
| _sax.startElement( |
| qName.getNamespaceURI(), |
| qName.getLocalPart(), |
| rawname, |
| saxAttrs); |
| } catch (SAXException e) { |
| throw new XMLStreamException(e); |
| } |
| } |
| |
| /** |
| * Get the attributes associated with the given START_ELEMENT StAXevent. |
| * |
| * @return the StAX attributes converted to an org.xml.sax.Attributes |
| */ |
| private Attributes getAttributes(StartElement event) { |
| AttributesImpl attrs = new AttributesImpl(); |
| |
| if ( !event.isStartElement() ) { |
| throw new InternalError( |
| "getAttributes() attempting to process: " + event); |
| } |
| |
| // 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 (Iterator i = event.getAttributes(); i.hasNext();) { |
| Attribute staxAttr = (javax.xml.stream.events.Attribute)i.next(); |
| |
| String uri = staxAttr.getName().getNamespaceURI(); |
| if (uri == null) { |
| uri = ""; |
| } |
| String localName = staxAttr.getName().getLocalPart(); |
| String prefix = staxAttr.getName().getPrefix(); |
| String qName; |
| if (prefix == null || prefix.length() == 0) { |
| qName = localName; |
| } else { |
| qName = prefix + ':' + localName; |
| } |
| String type = staxAttr.getDTDType(); |
| String value = staxAttr.getValue(); |
| |
| 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. |
| } |
| |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public DTDHandler getDTDHandler() { |
| return null; |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public ErrorHandler getErrorHandler() { |
| return null; |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public boolean getFeature(String name) throws SAXNotRecognizedException, |
| SAXNotSupportedException |
| { |
| return false; |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public void setFeature(String name, boolean value) throws |
| SAXNotRecognizedException, SAXNotSupportedException |
| { |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public void parse(String sysId) throws IOException, SAXException { |
| throw new IOException("This method is not yet implemented."); |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public void setDTDHandler(DTDHandler handler) throws NullPointerException { |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public void setEntityResolver(EntityResolver resolver) throws |
| NullPointerException |
| { |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public EntityResolver getEntityResolver() { |
| return null; |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public void setErrorHandler(ErrorHandler handler) throws |
| NullPointerException |
| { |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public void setProperty(String name, Object value) throws |
| SAXNotRecognizedException, SAXNotSupportedException { |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public Object getProperty(String name) throws SAXNotRecognizedException, |
| SAXNotSupportedException |
| { |
| return null; |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public int getColumnNumber() { |
| return 0; |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public int getLineNumber() { |
| return 0; |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public String getPublicId() { |
| return null; |
| } |
| |
| /** |
| * This class is only used internally so this method should never |
| * be called. |
| */ |
| public String getSystemId() { |
| return null; |
| } |
| } |