/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.converter.jaxp; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.transform.sax.SAXSource; 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.SAXException; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; import org.xml.sax.ext.LexicalHandler; /** * Adapter to turn a StAX {@link XMLStreamReader} into a {@link SAXSource}. */ public class StAX2SAXSource extends SAXSource implements XMLReader { private XMLStreamReader streamReader; private ContentHandler contentHandler; private LexicalHandler lexicalHandler; public StAX2SAXSource(XMLStreamReader streamReader) { this.streamReader = streamReader; setInputSource(new InputSource()); } public XMLReader getXMLReader() { return this; } public XMLStreamReader getXMLStreamReader() { return streamReader; } protected void parse() throws SAXException { final StAX2SAXAttributes attributes = new StAX2SAXAttributes(); try { while (true) { switch (streamReader.getEventType()) { // Attributes are handled in START_ELEMENT case XMLStreamConstants.ATTRIBUTE: break; case XMLStreamConstants.CDATA: { if (lexicalHandler != null) { lexicalHandler.startCDATA(); } int length = streamReader.getTextLength(); int start = streamReader.getTextStart(); char[] chars = streamReader.getTextCharacters(); contentHandler.characters(chars, start, length); if (lexicalHandler != null) { lexicalHandler.endCDATA(); } break; } case XMLStreamConstants.CHARACTERS: { int length = streamReader.getTextLength(); int start = streamReader.getTextStart(); char[] chars = streamReader.getTextCharacters(); contentHandler.characters(chars, start, length); break; } case XMLStreamConstants.SPACE: { int length = streamReader.getTextLength(); int start = streamReader.getTextStart(); char[] chars = streamReader.getTextCharacters(); contentHandler.ignorableWhitespace(chars, start, length); break; } case XMLStreamConstants.COMMENT: if (lexicalHandler != null) { int length = streamReader.getTextLength(); int start = streamReader.getTextStart(); char[] chars = streamReader.getTextCharacters(); lexicalHandler.comment(chars, start, length); } break; case XMLStreamConstants.DTD: break; case XMLStreamConstants.END_DOCUMENT: contentHandler.endDocument(); return; case XMLStreamConstants.END_ELEMENT: { String uri = nullToEmpty(streamReader.getNamespaceURI()); String localName = streamReader.getLocalName(); String qname = getPrefixedName(streamReader.getPrefix(), localName); contentHandler.endElement(uri, localName, qname); // namespaces for (int i = 0; i < streamReader.getNamespaceCount(); i++) { String nsPrefix = streamReader.getNamespacePrefix(i); contentHandler.endPrefixMapping(nsPrefix); } break; } case XMLStreamConstants.ENTITY_DECLARATION: case XMLStreamConstants.ENTITY_REFERENCE: case XMLStreamConstants.NAMESPACE: case XMLStreamConstants.NOTATION_DECLARATION: break; case XMLStreamConstants.PROCESSING_INSTRUCTION: break; case XMLStreamConstants.START_DOCUMENT: contentHandler.startDocument(); break; case XMLStreamConstants.START_ELEMENT: { // namespaces for (int i = 0; i < streamReader.getNamespaceCount(); i++) { String nsPrefix = nullToEmpty(streamReader.getNamespacePrefix(i)); String nsUri = nullToEmpty(streamReader.getNamespaceURI(i)); contentHandler.startPrefixMapping(nsPrefix, nsUri); } String uri = nullToEmpty(streamReader.getNamespaceURI()); String localName = streamReader.getLocalName(); String qname = getPrefixedName(streamReader.getPrefix(), localName); attributes.init(); contentHandler.startElement(uri, localName, qname, attributes); attributes.reset(); break; } default: break; } if (!streamReader.hasNext()) { return; } streamReader.next(); } } catch (XMLStreamException e) { SAXParseException spe; if (e.getLocation() != null) { spe = new SAXParseException(e.getMessage(), null, null, e.getLocation().getLineNumber(), e.getLocation().getColumnNumber(), e); } else { spe = new SAXParseException(e.getMessage(), null, null, -1, -1, e); } spe.initCause(e); throw spe; } } private String getPrefixedName(String prefix, String localName) { if (prefix == null || prefix.length() == 0) { return localName; } return prefix + ":" + localName; } private String nullToEmpty(String s) { return s == null ? "" : s; } class StAX2SAXAttributes implements Attributes { private int attributeCount; void init() { attributeCount = streamReader.getAttributeCount(); } void reset() { attributeCount = 0; } @Override public int getLength() { return attributeCount; } private boolean checkIndex(int index) { return index >= 0 && index < attributeCount; } @Override public String getURI(int index) { if (!checkIndex(index)) { return null; } return nullToEmpty(streamReader.getAttributeNamespace(index)); } @Override public String getLocalName(int index) { if (!checkIndex(index)) { return null; } return streamReader.getAttributeLocalName(index); } @Override public String getQName(int index) { if (!checkIndex(index)) { return null; } String localName = streamReader.getAttributeLocalName(index); String prefix = streamReader.getAttributePrefix(index); return getPrefixedName(prefix, localName); } @Override public String getType(int index) { if (!checkIndex(index)) { return null; } return streamReader.getAttributeType(index); } @Override public String getValue(int index) { if (!checkIndex(index)) { return null; } return nullToEmpty(streamReader.getAttributeValue(index)); } @Override public int getIndex(String searchUri, String searchLocalName) { for (int i = 0; i < attributeCount; i++) { if (getURI(i).equals(searchUri) && getLocalName(i).equals(searchLocalName)) { return i; } } return -1; } @Override public int getIndex(String searchQName) { for (int i = 0; i < attributeCount; i++) { if (getQName(i).equals(searchQName)) { return i; } } return -1; } @Override public String getType(String uri, String localName) { return getType(getIndex(uri, localName)); } @Override public String getType(String qName) { return getType(getIndex(qName)); } @Override public String getValue(String uri, String localName) { return getValue(getIndex(uri, localName)); } @Override public String getValue(String qName) { return getValue(getIndex(qName)); } } public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException { return false; } public void setFeature(String name, boolean value) throws SAXNotRecognizedException, SAXNotSupportedException { } public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException { return null; } public void setProperty(String name, Object value) throws SAXNotRecognizedException, SAXNotSupportedException { if ("http://xml.org/sax/properties/lexical-handler".equals(name)) { lexicalHandler = (LexicalHandler) value; } else { throw new SAXNotRecognizedException(name); } } public void setEntityResolver(EntityResolver resolver) { } public EntityResolver getEntityResolver() { return null; } public void setDTDHandler(DTDHandler handler) { } public DTDHandler getDTDHandler() { return null; } public void setContentHandler(ContentHandler handler) { this.contentHandler = handler; if (handler instanceof LexicalHandler && lexicalHandler == null) { lexicalHandler = (LexicalHandler)handler; } } public ContentHandler getContentHandler() { return this.contentHandler; } public void setErrorHandler(ErrorHandler handler) { } public ErrorHandler getErrorHandler() { return null; } public void parse(InputSource input) throws SAXException { StAX2SAXSource.this.parse(); } public void parse(String systemId) throws SAXException { StAX2SAXSource.this.parse(); } }