001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.converter.jaxp; 018 019import javax.xml.stream.XMLStreamConstants; 020import javax.xml.stream.XMLStreamException; 021import javax.xml.stream.XMLStreamReader; 022import javax.xml.transform.sax.SAXSource; 023 024import org.xml.sax.Attributes; 025import org.xml.sax.ContentHandler; 026import org.xml.sax.DTDHandler; 027import org.xml.sax.EntityResolver; 028import org.xml.sax.ErrorHandler; 029import org.xml.sax.InputSource; 030import org.xml.sax.SAXException; 031import org.xml.sax.SAXNotRecognizedException; 032import org.xml.sax.SAXNotSupportedException; 033import org.xml.sax.SAXParseException; 034import org.xml.sax.XMLReader; 035import org.xml.sax.ext.LexicalHandler; 036 037/** 038 * Adapter to turn a StAX {@link XMLStreamReader} into a {@link SAXSource}. 039 */ 040public class StAX2SAXSource extends SAXSource implements XMLReader { 041 042 private XMLStreamReader streamReader; 043 044 private ContentHandler contentHandler; 045 046 private LexicalHandler lexicalHandler; 047 048 public StAX2SAXSource(XMLStreamReader streamReader) { 049 this.streamReader = streamReader; 050 setInputSource(new InputSource()); 051 } 052 053 public XMLReader getXMLReader() { 054 return this; 055 } 056 057 public XMLStreamReader getXMLStreamReader() { 058 return streamReader; 059 } 060 061 protected void parse() throws SAXException { 062 final StAX2SAXAttributes attributes = new StAX2SAXAttributes(); 063 try { 064 while (true) { 065 switch (streamReader.getEventType()) { 066 // Attributes are handled in START_ELEMENT 067 case XMLStreamConstants.ATTRIBUTE: 068 break; 069 case XMLStreamConstants.CDATA: 070 { 071 if (lexicalHandler != null) { 072 lexicalHandler.startCDATA(); 073 } 074 int length = streamReader.getTextLength(); 075 int start = streamReader.getTextStart(); 076 char[] chars = streamReader.getTextCharacters(); 077 contentHandler.characters(chars, start, length); 078 if (lexicalHandler != null) { 079 lexicalHandler.endCDATA(); 080 } 081 break; 082 } 083 case XMLStreamConstants.CHARACTERS: 084 { 085 int length = streamReader.getTextLength(); 086 int start = streamReader.getTextStart(); 087 char[] chars = streamReader.getTextCharacters(); 088 contentHandler.characters(chars, start, length); 089 break; 090 } 091 case XMLStreamConstants.SPACE: 092 { 093 int length = streamReader.getTextLength(); 094 int start = streamReader.getTextStart(); 095 char[] chars = streamReader.getTextCharacters(); 096 contentHandler.ignorableWhitespace(chars, start, length); 097 break; 098 } 099 case XMLStreamConstants.COMMENT: 100 if (lexicalHandler != null) { 101 int length = streamReader.getTextLength(); 102 int start = streamReader.getTextStart(); 103 char[] chars = streamReader.getTextCharacters(); 104 lexicalHandler.comment(chars, start, length); 105 } 106 break; 107 case XMLStreamConstants.DTD: 108 break; 109 case XMLStreamConstants.END_DOCUMENT: 110 contentHandler.endDocument(); 111 return; 112 case XMLStreamConstants.END_ELEMENT: { 113 String uri = nullToEmpty(streamReader.getNamespaceURI()); 114 String localName = streamReader.getLocalName(); 115 String qname = getPrefixedName(streamReader.getPrefix(), localName); 116 contentHandler.endElement(uri, localName, qname); 117 118 // namespaces 119 for (int i = 0; i < streamReader.getNamespaceCount(); i++) { 120 String nsPrefix = streamReader.getNamespacePrefix(i); 121 contentHandler.endPrefixMapping(nsPrefix); 122 } 123 break; 124 } 125 case XMLStreamConstants.ENTITY_DECLARATION: 126 case XMLStreamConstants.ENTITY_REFERENCE: 127 case XMLStreamConstants.NAMESPACE: 128 case XMLStreamConstants.NOTATION_DECLARATION: 129 break; 130 case XMLStreamConstants.PROCESSING_INSTRUCTION: 131 break; 132 case XMLStreamConstants.START_DOCUMENT: 133 contentHandler.startDocument(); 134 break; 135 case XMLStreamConstants.START_ELEMENT: { 136 // namespaces 137 for (int i = 0; i < streamReader.getNamespaceCount(); i++) { 138 String nsPrefix = nullToEmpty(streamReader.getNamespacePrefix(i)); 139 String nsUri = nullToEmpty(streamReader.getNamespaceURI(i)); 140 contentHandler.startPrefixMapping(nsPrefix, nsUri); 141 } 142 143 String uri = nullToEmpty(streamReader.getNamespaceURI()); 144 String localName = streamReader.getLocalName(); 145 String qname = getPrefixedName(streamReader.getPrefix(), localName); 146 attributes.init(); 147 contentHandler.startElement(uri, localName, qname, attributes); 148 attributes.reset(); 149 break; 150 } 151 default: 152 break; 153 } 154 if (!streamReader.hasNext()) { 155 return; 156 } 157 streamReader.next(); 158 } 159 } catch (XMLStreamException e) { 160 SAXParseException spe; 161 if (e.getLocation() != null) { 162 spe = new SAXParseException(e.getMessage(), null, null, 163 e.getLocation().getLineNumber(), 164 e.getLocation().getColumnNumber(), e); 165 } else { 166 spe = new SAXParseException(e.getMessage(), null, null, -1, -1, e); 167 } 168 spe.initCause(e); 169 throw spe; 170 } 171 } 172 173 private String getPrefixedName(String prefix, String localName) { 174 if (prefix == null || prefix.length() == 0) { 175 return localName; 176 } 177 return prefix + ":" + localName; 178 } 179 180 private String nullToEmpty(String s) { 181 return s == null ? "" : s; 182 } 183 184 class StAX2SAXAttributes implements Attributes { 185 186 private int attributeCount; 187 188 void init() { 189 attributeCount = streamReader.getAttributeCount(); 190 } 191 192 void reset() { 193 attributeCount = 0; 194 } 195 196 @Override 197 public int getLength() { 198 return attributeCount; 199 } 200 201 private boolean checkIndex(int index) { 202 return index >= 0 && index < attributeCount; 203 } 204 205 @Override 206 public String getURI(int index) { 207 if (!checkIndex(index)) { 208 return null; 209 } 210 return nullToEmpty(streamReader.getAttributeNamespace(index)); 211 } 212 213 @Override 214 public String getLocalName(int index) { 215 if (!checkIndex(index)) { 216 return null; 217 } 218 return streamReader.getAttributeLocalName(index); 219 } 220 221 @Override 222 public String getQName(int index) { 223 if (!checkIndex(index)) { 224 return null; 225 } 226 String localName = streamReader.getAttributeLocalName(index); 227 String prefix = streamReader.getAttributePrefix(index); 228 return getPrefixedName(prefix, localName); 229 } 230 231 @Override 232 public String getType(int index) { 233 if (!checkIndex(index)) { 234 return null; 235 } 236 return streamReader.getAttributeType(index); 237 } 238 239 @Override 240 public String getValue(int index) { 241 if (!checkIndex(index)) { 242 return null; 243 } 244 return nullToEmpty(streamReader.getAttributeValue(index)); 245 } 246 247 @Override 248 public int getIndex(String searchUri, String searchLocalName) { 249 for (int i = 0; i < attributeCount; i++) { 250 if (getURI(i).equals(searchUri) && getLocalName(i).equals(searchLocalName)) { 251 return i; 252 } 253 } 254 return -1; 255 } 256 257 @Override 258 public int getIndex(String searchQName) { 259 for (int i = 0; i < attributeCount; i++) { 260 if (getQName(i).equals(searchQName)) { 261 return i; 262 } 263 } 264 return -1; 265 } 266 267 @Override 268 public String getType(String uri, String localName) { 269 return getType(getIndex(uri, localName)); 270 } 271 272 @Override 273 public String getType(String qName) { 274 return getType(getIndex(qName)); 275 } 276 277 @Override 278 public String getValue(String uri, String localName) { 279 return getValue(getIndex(uri, localName)); 280 } 281 282 @Override 283 public String getValue(String qName) { 284 return getValue(getIndex(qName)); 285 } 286 } 287 288 public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException { 289 return false; 290 } 291 292 public void setFeature(String name, boolean value) 293 throws SAXNotRecognizedException, SAXNotSupportedException { 294 } 295 296 public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException { 297 return null; 298 } 299 300 public void setProperty(String name, Object value) 301 throws SAXNotRecognizedException, SAXNotSupportedException { 302 if ("http://xml.org/sax/properties/lexical-handler".equals(name)) { 303 lexicalHandler = (LexicalHandler) value; 304 } else { 305 throw new SAXNotRecognizedException(name); 306 } 307 } 308 309 public void setEntityResolver(EntityResolver resolver) { 310 } 311 312 public EntityResolver getEntityResolver() { 313 return null; 314 } 315 316 public void setDTDHandler(DTDHandler handler) { 317 } 318 319 public DTDHandler getDTDHandler() { 320 return null; 321 } 322 323 public void setContentHandler(ContentHandler handler) { 324 this.contentHandler = handler; 325 if (handler instanceof LexicalHandler 326 && lexicalHandler == null) { 327 lexicalHandler = (LexicalHandler)handler; 328 } 329 } 330 331 public ContentHandler getContentHandler() { 332 return this.contentHandler; 333 } 334 335 public void setErrorHandler(ErrorHandler handler) { 336 } 337 338 public ErrorHandler getErrorHandler() { 339 return null; 340 } 341 342 public void parse(InputSource input) throws SAXException { 343 StAX2SAXSource.this.parse(); 344 } 345 346 public void parse(String systemId) throws SAXException { 347 StAX2SAXSource.this.parse(); 348 } 349 350}