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, 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, 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 }