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 */ 017 package org.apache.camel.converter.jaxp; 018 019 import java.io.ByteArrayInputStream; 020 import java.io.File; 021 import java.io.FileInputStream; 022 import java.io.FileNotFoundException; 023 import java.io.IOException; 024 import java.io.InputStream; 025 import java.io.InputStreamReader; 026 import java.io.Reader; 027 import java.io.StringReader; 028 import java.io.StringWriter; 029 import java.lang.reflect.Constructor; 030 import java.nio.ByteBuffer; 031 import java.util.Properties; 032 033 import javax.xml.parsers.DocumentBuilder; 034 import javax.xml.parsers.DocumentBuilderFactory; 035 import javax.xml.parsers.ParserConfigurationException; 036 import javax.xml.stream.XMLStreamException; 037 import javax.xml.stream.XMLStreamReader; 038 import javax.xml.transform.OutputKeys; 039 import javax.xml.transform.Result; 040 import javax.xml.transform.Source; 041 import javax.xml.transform.Transformer; 042 import javax.xml.transform.TransformerConfigurationException; 043 import javax.xml.transform.TransformerException; 044 import javax.xml.transform.TransformerFactory; 045 import javax.xml.transform.dom.DOMResult; 046 import javax.xml.transform.dom.DOMSource; 047 import javax.xml.transform.sax.SAXSource; 048 import javax.xml.transform.stax.StAXSource; 049 import javax.xml.transform.stream.StreamResult; 050 import javax.xml.transform.stream.StreamSource; 051 052 import org.w3c.dom.Document; 053 import org.w3c.dom.Element; 054 import org.w3c.dom.Node; 055 import org.w3c.dom.NodeList; 056 057 import org.xml.sax.InputSource; 058 import org.xml.sax.SAXException; 059 import org.xml.sax.XMLReader; 060 061 import org.apache.camel.BytesSource; 062 import org.apache.camel.Converter; 063 import org.apache.camel.Exchange; 064 import org.apache.camel.StringSource; 065 import org.apache.camel.util.IOHelper; 066 import org.apache.camel.util.ObjectHelper; 067 068 /** 069 * A helper class to transform to and from various JAXB types such as {@link Source} and {@link Document} 070 * 071 * @version 072 */ 073 @Converter 074 public class XmlConverter { 075 @Deprecated 076 //It will be removed in Camel 3.0, please use the Exchange.DEFAULT_CHARSET 077 public static final String DEFAULT_CHARSET_PROPERTY = "org.apache.camel.default.charset"; 078 079 public static final String OUTPUT_PROPERTIES_PREFIX = "org.apache.camel.xmlconverter.output."; 080 public static String defaultCharset = ObjectHelper.getSystemProperty(Exchange.DEFAULT_CHARSET_PROPERTY, "UTF-8"); 081 082 /* 083 * When converting a DOM tree to a SAXSource, we try to use Xalan internal DOM parser if 084 * available. Else, transform the DOM tree to a String and build a SAXSource on top of it. 085 */ 086 private static final Class<?> DOM_TO_SAX_CLASS; 087 088 private DocumentBuilderFactory documentBuilderFactory; 089 private TransformerFactory transformerFactory; 090 091 static { 092 Class<?> cl = null; 093 try { 094 // will not warn the user if the class could not be found 095 cl = ObjectHelper.loadClass("org.apache.xalan.xsltc.trax.DOM2SAX", XmlConverter.class.getClassLoader(), false); 096 } catch (Exception e) { 097 // ignore 098 } 099 DOM_TO_SAX_CLASS = cl; 100 } 101 102 103 public XmlConverter() { 104 } 105 106 public XmlConverter(DocumentBuilderFactory documentBuilderFactory) { 107 this.documentBuilderFactory = documentBuilderFactory; 108 } 109 110 /** 111 * Returns the default set of output properties for conversions. 112 */ 113 public Properties defaultOutputProperties() { 114 Properties properties = new Properties(); 115 properties.put(OutputKeys.ENCODING, defaultCharset); 116 properties.put(OutputKeys.OMIT_XML_DECLARATION, "yes"); 117 return properties; 118 } 119 120 /** 121 * Converts the given input Source into the required result 122 */ 123 public void toResult(Source source, Result result) throws TransformerException { 124 toResult(source, result, defaultOutputProperties()); 125 } 126 127 /** 128 * Converts the given input Source into the required result 129 */ 130 public void toResult(Source source, Result result, Properties outputProperties) throws TransformerException { 131 if (source == null) { 132 return; 133 } 134 135 Transformer transformer = createTransformer(); 136 if (transformer == null) { 137 throw new TransformerException("Could not create a transformer - JAXP is misconfigured!"); 138 } 139 transformer.setOutputProperties(outputProperties); 140 transformer.transform(source, result); 141 } 142 143 /** 144 * Converts the given NodeList to a boolean 145 */ 146 @Converter 147 public Boolean toBoolean(NodeList list) { 148 return list.getLength() > 0; 149 } 150 151 /** 152 * Converts the given byte[] to a Source 153 */ 154 @Converter 155 public BytesSource toBytesSource(byte[] data) { 156 return new BytesSource(data); 157 } 158 159 160 /** 161 * Converts the given String to a Source 162 */ 163 @Converter 164 public StringSource toStringSource(String data) { 165 return new StringSource(data); 166 } 167 168 /** 169 * Converts the given Document to a Source 170 * @deprecated use toDOMSource instead 171 */ 172 @Deprecated 173 public DOMSource toSource(Document document) { 174 return new DOMSource(document); 175 } 176 177 /** 178 * Converts the given Node to a Source 179 * @throws TransformerException 180 * @throws ParserConfigurationException 181 * @deprecated use toDOMSource instead 182 */ 183 @Deprecated 184 public Source toSource(Node node) throws ParserConfigurationException, TransformerException { 185 return toDOMSource(node); 186 } 187 188 /** 189 * Converts the given Node to a Source 190 * @throws TransformerException 191 * @throws ParserConfigurationException 192 */ 193 @Converter 194 public DOMSource toDOMSource(Node node) throws ParserConfigurationException, TransformerException { 195 Document document = toDOMDocument(node); 196 return new DOMSource(document); 197 } 198 199 /** 200 * Converts the given Document to a DOMSource 201 */ 202 @Converter 203 public DOMSource toDOMSource(Document document) { 204 return new DOMSource(document); 205 } 206 207 /** 208 * Converts the given String to a Source 209 */ 210 @Converter 211 public Source toSource(String data) { 212 return new StringSource(data); 213 } 214 215 /** 216 * Converts the given input Source into text. 217 * 218 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 219 */ 220 @Deprecated 221 public String toString(Source source) throws TransformerException { 222 return toString(source, null); 223 } 224 225 /** 226 * Converts the given input Source into text 227 */ 228 @Converter 229 public String toString(Source source, Exchange exchange) throws TransformerException { 230 if (source == null) { 231 return null; 232 } else if (source instanceof StringSource) { 233 return ((StringSource) source).getText(); 234 } else if (source instanceof BytesSource) { 235 return new String(((BytesSource) source).getData()); 236 } else { 237 StringWriter buffer = new StringWriter(); 238 if (exchange != null) { 239 // check the camelContext properties first 240 Properties properties = ObjectHelper.getCamelPropertiesWithPrefix(OUTPUT_PROPERTIES_PREFIX, exchange.getContext()); 241 if (properties.size() > 0) { 242 toResult(source, new StreamResult(buffer), properties); 243 return buffer.toString(); 244 } 245 } 246 // using the old way to deal with it 247 toResult(source, new StreamResult(buffer)); 248 return buffer.toString(); 249 } 250 } 251 252 /** 253 * Converts the given input Source into bytes 254 */ 255 @Converter 256 public byte[] toByteArray(Source source, Exchange exchange) throws TransformerException { 257 String answer = toString(source, exchange); 258 if (exchange != null) { 259 return exchange.getContext().getTypeConverter().convertTo(byte[].class, exchange, answer); 260 } else { 261 return answer.getBytes(); 262 } 263 } 264 265 /** 266 * Converts the given input Node into text 267 * 268 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 269 */ 270 @Deprecated 271 public String toString(Node node) throws TransformerException { 272 return toString(node, null); 273 } 274 275 /** 276 * Converts the given input Node into text 277 */ 278 @Converter 279 public String toString(Node node, Exchange exchange) throws TransformerException { 280 return toString(new DOMSource(node), exchange); 281 } 282 283 /** 284 * Converts the source instance to a {@link DOMSource} or returns null if the conversion is not 285 * supported (making it easy to derive from this class to add new kinds of conversion). 286 */ 287 @Converter 288 public DOMSource toDOMSource(Source source) throws ParserConfigurationException, IOException, SAXException, TransformerException { 289 if (source instanceof DOMSource) { 290 return (DOMSource) source; 291 } else if (source instanceof SAXSource) { 292 return toDOMSourceFromSAX((SAXSource) source); 293 } else if (source instanceof StreamSource) { 294 return toDOMSourceFromStream((StreamSource) source); 295 } else if (source instanceof StAXSource) { 296 return toDOMSourceFromStAX((StAXSource)source); 297 } else { 298 return null; 299 } 300 } 301 302 /** 303 * Converts the source instance to a {@link DOMSource} or returns null if the conversion is not 304 * supported (making it easy to derive from this class to add new kinds of conversion). 305 */ 306 @Converter 307 public DOMSource toDOMSource(String text) throws ParserConfigurationException, IOException, SAXException, TransformerException { 308 Source source = toSource(text); 309 if (source != null) { 310 return toDOMSourceFromStream((StreamSource) source); 311 } else { 312 return null; 313 } 314 } 315 316 /** 317 * Converts the source instance to a {@link DOMSource} or returns null if the conversion is not 318 * supported (making it easy to derive from this class to add new kinds of conversion). 319 */ 320 @Converter 321 public DOMSource toDOMSource(byte[] bytes) throws IOException, SAXException, ParserConfigurationException { 322 InputStream is = new ByteArrayInputStream(bytes); 323 try { 324 return toDOMSource(is); 325 } finally { 326 IOHelper.close(is); 327 } 328 } 329 330 331 /** 332 * Converts the source instance to a {@link SAXSource} or returns null if the conversion is not 333 * supported (making it easy to derive from this class to add new kinds of conversion). 334 * 335 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 336 */ 337 @Deprecated 338 public SAXSource toSAXSource(String source) throws IOException, SAXException, TransformerException { 339 return toSAXSource(source, null); 340 } 341 342 /** 343 * Converts the source instance to a {@link SAXSource} or returns null if the conversion is not 344 * supported (making it easy to derive from this class to add new kinds of conversion). 345 */ 346 @Converter 347 public SAXSource toSAXSource(String source, Exchange exchange) throws IOException, SAXException, TransformerException { 348 return toSAXSource(toSource(source), exchange); 349 } 350 351 /** 352 * Converts the source instance to a {@link StAXSource} or returns null if the conversion is not 353 * supported (making it easy to derive from this class to add new kinds of conversion). 354 * @throws XMLStreamException 355 */ 356 @Converter 357 public StAXSource toStAXSource(String source, Exchange exchange) throws XMLStreamException { 358 XMLStreamReader r = new StaxConverter().createXMLStreamReader(new StringReader(source)); 359 return new StAXSource(r); 360 } 361 362 /** 363 * Converts the source instance to a {@link StAXSource} or returns null if the conversion is not 364 * supported (making it easy to derive from this class to add new kinds of conversion). 365 * @throws XMLStreamException 366 */ 367 @Converter 368 public StAXSource toStAXSource(byte[] in, Exchange exchange) throws XMLStreamException { 369 XMLStreamReader r = new StaxConverter().createXMLStreamReader(new ByteArrayInputStream(in), exchange); 370 return new StAXSource(r); 371 } 372 373 /** 374 * Converts the source instance to a {@link SAXSource} or returns null if the conversion is not 375 * supported (making it easy to derive from this class to add new kinds of conversion). 376 * 377 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 378 */ 379 @Deprecated 380 public SAXSource toSAXSource(InputStream source) throws IOException, SAXException, TransformerException { 381 return toSAXSource(source, null); 382 } 383 384 /** 385 * Converts the source instance to a {@link SAXSource} or returns null if the conversion is not 386 * supported (making it easy to derive from this class to add new kinds of conversion). 387 */ 388 @Converter 389 public SAXSource toSAXSource(InputStream source, Exchange exchange) throws IOException, SAXException, TransformerException { 390 return toSAXSource(toStreamSource(source), exchange); 391 } 392 393 /** 394 * Converts the source instance to a {@link SAXSource} or returns null if the conversion is not 395 * supported (making it easy to derive from this class to add new kinds of conversion). 396 */ 397 @Converter 398 public SAXSource toSAXSource(byte[] in, Exchange exchange) throws IOException, SAXException, TransformerException { 399 return toSAXSource(toStreamSource(in, exchange), exchange); 400 } 401 402 /** 403 * Converts the source instance to a {@link StAXSource} or returns null if the conversion is not 404 * supported (making it easy to derive from this class to add new kinds of conversion). 405 * @throws XMLStreamException 406 */ 407 @Converter 408 public StAXSource toStAXSource(InputStream source, Exchange exchange) throws XMLStreamException { 409 XMLStreamReader r = new StaxConverter().createXMLStreamReader(source, exchange); 410 return new StAXSource(r); 411 } 412 413 /** 414 * Converts the source instance to a {@link SAXSource} or returns null if the conversion is not 415 * supported (making it easy to derive from this class to add new kinds of conversion). 416 */ 417 @Converter 418 public SAXSource toSAXSource(File file, Exchange exchange) throws IOException, SAXException, TransformerException { 419 InputStream is = IOHelper.buffered(new FileInputStream(file)); 420 return toSAXSource(is, exchange); 421 } 422 423 /** 424 * Converts the source instance to a {@link StAXSource} or returns null if the conversion is not 425 * supported (making it easy to derive from this class to add new kinds of conversion). 426 * @throws FileNotFoundException 427 * @throws XMLStreamException 428 */ 429 @Converter 430 public StAXSource toStAXSource(File file, Exchange exchange) throws FileNotFoundException, XMLStreamException { 431 InputStream is = IOHelper.buffered(new FileInputStream(file)); 432 XMLStreamReader r = new StaxConverter().createXMLStreamReader(is, exchange); 433 return new StAXSource(r); 434 } 435 436 /** 437 * Converts the source instance to a {@link SAXSource} or returns null if the conversion is not 438 * supported (making it easy to derive from this class to add new kinds of conversion). 439 * 440 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 441 */ 442 @Deprecated 443 public SAXSource toSAXSource(Source source) throws IOException, SAXException, TransformerException { 444 return toSAXSource(source, null); 445 } 446 447 /** 448 * Converts the source instance to a {@link SAXSource} or returns null if the conversion is not 449 * supported (making it easy to derive from this class to add new kinds of conversion). 450 */ 451 @Converter 452 public SAXSource toSAXSource(Source source, Exchange exchange) throws IOException, SAXException, TransformerException { 453 if (source instanceof SAXSource) { 454 return (SAXSource) source; 455 } else if (source instanceof DOMSource) { 456 return toSAXSourceFromDOM((DOMSource) source, exchange); 457 } else if (source instanceof StreamSource) { 458 return toSAXSourceFromStream((StreamSource) source); 459 } else if (source instanceof StAXSource) { 460 return toSAXSourceFromStAX((StAXSource) source, exchange); 461 } else { 462 return null; 463 } 464 } 465 466 /** 467 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 468 */ 469 @Deprecated 470 public StreamSource toStreamSource(Source source) throws TransformerException { 471 return toStreamSource(source, null); 472 } 473 474 @Converter 475 public StreamSource toStreamSource(Source source, Exchange exchange) throws TransformerException { 476 if (source instanceof StreamSource) { 477 return (StreamSource) source; 478 } else if (source instanceof DOMSource) { 479 return toStreamSourceFromDOM((DOMSource) source, exchange); 480 } else if (source instanceof SAXSource) { 481 return toStreamSourceFromSAX((SAXSource) source, exchange); 482 } else if (source instanceof StAXSource) { 483 return toStreamSourceFromStAX((StAXSource) source, exchange); 484 } else { 485 return null; 486 } 487 } 488 489 @Converter 490 public StreamSource toStreamSource(InputStream in) throws TransformerException { 491 if (in != null) { 492 return new StreamSource(in); 493 } 494 return null; 495 } 496 497 @Converter 498 public StreamSource toStreamSource(Reader in) throws TransformerException { 499 if (in != null) { 500 return new StreamSource(in); 501 } 502 return null; 503 } 504 505 @Converter 506 public StreamSource toStreamSource(File in) throws TransformerException { 507 if (in != null) { 508 return new StreamSource(in); 509 } 510 return null; 511 } 512 513 @Converter 514 public StreamSource toStreamSource(byte[] in, Exchange exchange) throws TransformerException { 515 if (in != null) { 516 InputStream is = exchange.getContext().getTypeConverter().convertTo(InputStream.class, exchange, in); 517 return new StreamSource(is); 518 } 519 return null; 520 } 521 522 @Converter 523 public StreamSource toStreamSource(ByteBuffer in, Exchange exchange) throws TransformerException { 524 if (in != null) { 525 InputStream is = exchange.getContext().getTypeConverter().convertTo(InputStream.class, exchange, in); 526 return new StreamSource(is); 527 } 528 return null; 529 } 530 531 /** 532 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 533 */ 534 @Deprecated 535 public StreamSource toStreamSourceFromSAX(SAXSource source) throws TransformerException { 536 return toStreamSourceFromSAX(source, null); 537 } 538 539 @Converter 540 public StreamSource toStreamSourceFromSAX(SAXSource source, Exchange exchange) throws TransformerException { 541 InputSource inputSource = source.getInputSource(); 542 if (inputSource != null) { 543 if (inputSource.getCharacterStream() != null) { 544 return new StreamSource(inputSource.getCharacterStream()); 545 } 546 if (inputSource.getByteStream() != null) { 547 return new StreamSource(inputSource.getByteStream()); 548 } 549 } 550 String result = toString(source, exchange); 551 return new StringSource(result); 552 } 553 554 /** 555 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 556 */ 557 @Deprecated 558 public StreamSource toStreamSourceFromDOM(DOMSource source) throws TransformerException { 559 return toStreamSourceFromDOM(source, null); 560 } 561 562 @Converter 563 public StreamSource toStreamSourceFromDOM(DOMSource source, Exchange exchange) throws TransformerException { 564 String result = toString(source, exchange); 565 return new StringSource(result); 566 } 567 @Converter 568 public StreamSource toStreamSourceFromStAX(StAXSource source, Exchange exchange) throws TransformerException { 569 String result = toString(source, exchange); 570 return new StringSource(result); 571 } 572 573 @Converter 574 public SAXSource toSAXSourceFromStream(StreamSource source) { 575 InputSource inputSource; 576 if (source.getReader() != null) { 577 inputSource = new InputSource(source.getReader()); 578 } else { 579 inputSource = new InputSource(source.getInputStream()); 580 } 581 inputSource.setSystemId(source.getSystemId()); 582 inputSource.setPublicId(source.getPublicId()); 583 return new SAXSource(inputSource); 584 } 585 586 /** 587 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 588 */ 589 @Deprecated 590 public Reader toReaderFromSource(Source src) throws TransformerException { 591 return toReaderFromSource(src, null); 592 } 593 594 @Converter 595 public Reader toReaderFromSource(Source src, Exchange exchange) throws TransformerException { 596 StreamSource stSrc = toStreamSource(src, exchange); 597 Reader r = stSrc.getReader(); 598 if (r == null) { 599 r = new InputStreamReader(stSrc.getInputStream()); 600 } 601 return r; 602 } 603 604 @Converter 605 public DOMSource toDOMSource(InputStream is) throws ParserConfigurationException, IOException, SAXException { 606 InputSource source = new InputSource(is); 607 String systemId = source.getSystemId(); 608 DocumentBuilder builder = createDocumentBuilder(); 609 Document document = builder.parse(source); 610 return new DOMSource(document, systemId); 611 } 612 613 @Converter 614 public DOMSource toDOMSource(File file) throws ParserConfigurationException, IOException, SAXException { 615 InputStream is = IOHelper.buffered(new FileInputStream(file)); 616 return toDOMSource(is); 617 } 618 619 @Converter 620 public DOMSource toDOMSourceFromStream(StreamSource source) throws ParserConfigurationException, IOException, SAXException { 621 Document document; 622 String systemId = source.getSystemId(); 623 624 DocumentBuilder builder = createDocumentBuilder(); 625 Reader reader = source.getReader(); 626 if (reader != null) { 627 document = builder.parse(new InputSource(reader)); 628 } else { 629 InputStream inputStream = source.getInputStream(); 630 if (inputStream != null) { 631 InputSource inputsource = new InputSource(inputStream); 632 inputsource.setSystemId(systemId); 633 document = builder.parse(inputsource); 634 } else { 635 throw new IOException("No input stream or reader available on StreamSource: " + source); 636 } 637 } 638 return new DOMSource(document, systemId); 639 } 640 641 /** 642 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 643 */ 644 @Deprecated 645 public SAXSource toSAXSourceFromDOM(DOMSource source) throws TransformerException { 646 return toSAXSourceFromDOM(source, null); 647 } 648 649 @Converter 650 public SAXSource toSAXSourceFromDOM(DOMSource source, Exchange exchange) throws TransformerException { 651 if (DOM_TO_SAX_CLASS != null) { 652 try { 653 Constructor<?> cns = DOM_TO_SAX_CLASS.getConstructor(Node.class); 654 XMLReader converter = (XMLReader) cns.newInstance(source.getNode()); 655 return new SAXSource(converter, new InputSource()); 656 } catch (Exception e) { 657 throw new TransformerException(e); 658 } 659 } else { 660 String str = toString(source, exchange); 661 StringReader reader = new StringReader(str); 662 return new SAXSource(new InputSource(reader)); 663 } 664 } 665 666 @Converter 667 public SAXSource toSAXSourceFromStAX(StAXSource source, Exchange exchange) throws TransformerException { 668 String str = toString(source, exchange); 669 StringReader reader = new StringReader(str); 670 return new SAXSource(new InputSource(reader)); 671 } 672 673 @Converter 674 public DOMSource toDOMSourceFromSAX(SAXSource source) throws IOException, SAXException, ParserConfigurationException, TransformerException { 675 return new DOMSource(toDOMNodeFromSAX(source)); 676 } 677 678 @Converter 679 public DOMSource toDOMSourceFromStAX(StAXSource source) throws IOException, SAXException, ParserConfigurationException, TransformerException { 680 return new DOMSource(toDOMNodeFromStAX(source)); 681 } 682 683 @Converter 684 public Node toDOMNodeFromSAX(SAXSource source) throws ParserConfigurationException, IOException, SAXException, TransformerException { 685 DOMResult result = new DOMResult(); 686 toResult(source, result); 687 return result.getNode(); 688 } 689 690 @Converter 691 public Node toDOMNodeFromStAX(StAXSource source) throws ParserConfigurationException, IOException, SAXException, TransformerException { 692 DOMResult result = new DOMResult(); 693 toResult(source, result); 694 return result.getNode(); 695 } 696 697 /** 698 * Convert a NodeList consisting of just 1 node to a DOM Node. 699 * @param nl the NodeList 700 * @return the DOM Node 701 */ 702 @Converter 703 public Node toDOMNodeFromSingleNodeList(NodeList nl) { 704 return nl.getLength() == 1 ? nl.item(0) : null; 705 } 706 707 /** 708 * Convert a NodeList consisting of just 1 node to a DOM Document. 709 * Cannot convert NodeList with length > 1 because they require a root node. 710 * @param nl the NodeList 711 * @return the DOM Document 712 */ 713 @Converter 714 public Document toDOMDocumentFromSingleNodeList(NodeList nl) throws ParserConfigurationException, TransformerException { 715 return nl.getLength() == 1 ? toDOMDocument(nl.item(0)) : null; 716 } 717 718 /** 719 * Converts the given TRaX Source into a W3C DOM node 720 */ 721 @Converter 722 public Node toDOMNode(Source source) throws TransformerException, ParserConfigurationException, IOException, SAXException { 723 DOMSource domSrc = toDOMSource(source); 724 return domSrc != null ? domSrc.getNode() : null; 725 } 726 727 /** 728 * Create a DOM element from the given source. 729 */ 730 @Converter 731 public Element toDOMElement(Source source) throws TransformerException, ParserConfigurationException, IOException, SAXException { 732 Node node = toDOMNode(source); 733 return toDOMElement(node); 734 } 735 736 /** 737 * Create a DOM element from the DOM node. 738 * Simply cast if the node is an Element, or 739 * return the root element if it is a Document. 740 */ 741 @Converter 742 public Element toDOMElement(Node node) throws TransformerException { 743 // If the node is an document, return the root element 744 if (node instanceof Document) { 745 return ((Document) node).getDocumentElement(); 746 // If the node is an element, just cast it 747 } else if (node instanceof Element) { 748 return (Element) node; 749 // Other node types are not handled 750 } else { 751 throw new TransformerException("Unable to convert DOM node to an Element"); 752 } 753 } 754 755 /** 756 * Converts the given data to a DOM document 757 * 758 * @param data is the data to be parsed 759 * @return the parsed document 760 */ 761 @Converter 762 public Document toDOMDocument(byte[] data) throws IOException, SAXException, ParserConfigurationException { 763 DocumentBuilder documentBuilder = getDocumentBuilderFactory().newDocumentBuilder(); 764 return documentBuilder.parse(new ByteArrayInputStream(data)); 765 } 766 767 /** 768 * Converts the given {@link InputStream} to a DOM document 769 * 770 * @param in is the data to be parsed 771 * @return the parsed document 772 */ 773 @Converter 774 public Document toDOMDocument(InputStream in) throws IOException, SAXException, ParserConfigurationException { 775 DocumentBuilder documentBuilder = getDocumentBuilderFactory().newDocumentBuilder(); 776 return documentBuilder.parse(in); 777 } 778 779 /** 780 * Converts the given {@link InputStream} to a DOM document 781 * 782 * @param in is the data to be parsed 783 * @return the parsed document 784 */ 785 @Converter 786 public Document toDOMDocument(Reader in) throws IOException, SAXException, ParserConfigurationException { 787 return toDOMDocument(new InputSource(in)); 788 } 789 790 /** 791 * Converts the given {@link InputSource} to a DOM document 792 * 793 * @param in is the data to be parsed 794 * @return the parsed document 795 */ 796 @Converter 797 public Document toDOMDocument(InputSource in) throws IOException, SAXException, ParserConfigurationException { 798 DocumentBuilder documentBuilder = getDocumentBuilderFactory().newDocumentBuilder(); 799 return documentBuilder.parse(in); 800 } 801 802 /** 803 * Converts the given {@link String} to a DOM document 804 * 805 * @param text is the data to be parsed 806 * @return the parsed document 807 */ 808 @Converter 809 public Document toDOMDocument(String text) throws IOException, SAXException, ParserConfigurationException { 810 return toDOMDocument(new StringReader(text)); 811 } 812 813 /** 814 * Converts the given {@link File} to a DOM document 815 * 816 * @param file is the data to be parsed 817 * @return the parsed document 818 */ 819 @Converter 820 public Document toDOMDocument(File file) throws IOException, SAXException, ParserConfigurationException { 821 DocumentBuilder documentBuilder = getDocumentBuilderFactory().newDocumentBuilder(); 822 return documentBuilder.parse(file); 823 } 824 825 /** 826 * Create a DOM document from the given source. 827 */ 828 @Converter 829 public Document toDOMDocument(Source source) throws TransformerException, ParserConfigurationException, IOException, SAXException { 830 Node node = toDOMNode(source); 831 return toDOMDocument(node); 832 } 833 834 /** 835 * Create a DOM document from the given Node. 836 * 837 * If the node is an document, just cast it, if the node is an root element, retrieve its 838 * owner element or create a new document and import the node. 839 */ 840 @Converter 841 public Document toDOMDocument(final Node node) throws ParserConfigurationException, TransformerException { 842 ObjectHelper.notNull(node, "node"); 843 844 // If the node is the document, just cast it 845 if (node instanceof Document) { 846 return (Document) node; 847 // If the node is an element 848 } else if (node instanceof Element) { 849 Element elem = (Element) node; 850 // If this is the root element, return its owner document 851 if (elem.getOwnerDocument().getDocumentElement() == elem) { 852 return elem.getOwnerDocument(); 853 // else, create a new doc and copy the element inside it 854 } else { 855 Document doc = createDocument(); 856 // import node must not occur concurrent on the same node (must be its owner) 857 // so we need to synchronize on it 858 synchronized (node.getOwnerDocument()) { 859 doc.appendChild(doc.importNode(node, true)); 860 } 861 return doc; 862 } 863 // other element types are not handled 864 } else { 865 throw new TransformerException("Unable to convert DOM node to a Document: " + node); 866 } 867 } 868 869 /** 870 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 871 */ 872 @Deprecated 873 public InputStream toInputStream(DOMSource source) throws TransformerException, IOException { 874 return toInputStream(source, null); 875 } 876 877 @Converter 878 public InputStream toInputStream(DOMSource source, Exchange exchange) throws TransformerException, IOException { 879 String s = toString(source, exchange); 880 return new ByteArrayInputStream(s.getBytes()); 881 } 882 883 /** 884 * @deprecated will be removed in Camel 3.0. Use the method which has 2 parameters. 885 */ 886 @Deprecated 887 public InputStream toInputStream(Document dom) throws TransformerException, IOException { 888 return toInputStream(dom, null); 889 } 890 891 @Converter 892 public InputStream toInputStream(Document dom, Exchange exchange) throws TransformerException, IOException { 893 String s = toString(dom, exchange); 894 return new ByteArrayInputStream(s.getBytes()); 895 } 896 897 @Converter 898 public InputSource toInputSource(InputStream is, Exchange exchange) { 899 return new InputSource(is); 900 } 901 902 @Converter 903 public InputSource toInputSource(File file, Exchange exchange) throws FileNotFoundException { 904 InputStream is = IOHelper.buffered(new FileInputStream(file)); 905 return new InputSource(is); 906 } 907 908 // Properties 909 //------------------------------------------------------------------------- 910 public DocumentBuilderFactory getDocumentBuilderFactory() { 911 if (documentBuilderFactory == null) { 912 documentBuilderFactory = createDocumentBuilderFactory(); 913 } 914 return documentBuilderFactory; 915 } 916 917 public void setDocumentBuilderFactory(DocumentBuilderFactory documentBuilderFactory) { 918 this.documentBuilderFactory = documentBuilderFactory; 919 } 920 921 922 // Helper methods 923 //------------------------------------------------------------------------- 924 public DocumentBuilderFactory createDocumentBuilderFactory() { 925 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 926 factory.setNamespaceAware(true); 927 factory.setIgnoringElementContentWhitespace(true); 928 factory.setIgnoringComments(true); 929 return factory; 930 } 931 932 933 public DocumentBuilder createDocumentBuilder() throws ParserConfigurationException { 934 DocumentBuilderFactory factory = getDocumentBuilderFactory(); 935 return factory.newDocumentBuilder(); 936 } 937 938 public Document createDocument() throws ParserConfigurationException { 939 DocumentBuilder builder = createDocumentBuilder(); 940 return builder.newDocument(); 941 } 942 943 public TransformerFactory getTransformerFactory() { 944 if (transformerFactory == null) { 945 transformerFactory = createTransformerFactory(); 946 } 947 return transformerFactory; 948 } 949 950 public void setTransformerFactory(TransformerFactory transformerFactory) { 951 this.transformerFactory = transformerFactory; 952 } 953 954 /** 955 * @deprecated use {@link #createTransformer}, will be removed in Camel 3.0 956 */ 957 @Deprecated 958 public Transformer createTransfomer() throws TransformerConfigurationException { 959 return createTransformer(); 960 } 961 962 public Transformer createTransformer() throws TransformerConfigurationException { 963 TransformerFactory factory = getTransformerFactory(); 964 return factory.newTransformer(); 965 } 966 967 public TransformerFactory createTransformerFactory() { 968 TransformerFactory factory = TransformerFactory.newInstance(); 969 factory.setErrorListener(new XmlErrorListener()); 970 return factory; 971 } 972 973 }