blob: 83960bb304354b0a135b136d40d3e5ff318a3180 [file] [log] [blame]
/*
* 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.component.xslt;
import java.io.InputStream;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Node;
import org.apache.camel.Exchange;
import org.apache.camel.ExpectedBodyTypeException;
import org.apache.camel.RuntimeTransformException;
import org.apache.camel.TypeConverter;
import org.apache.camel.support.builder.xml.XMLConverterHelper;
/**
* Handler for xml sources
*/
public class XmlSourceHandlerFactoryImpl implements SourceHandlerFactory {
private XMLConverterHelper converter = new XMLConverterHelper();
private boolean isFailOnNullBody = true;
/**
* Returns true if we fail when the body is null.
*/
public boolean isFailOnNullBody() {
return isFailOnNullBody;
}
/**
* Set if we should fail when the body is null
*/
public void setFailOnNullBody(boolean failOnNullBody) {
isFailOnNullBody = failOnNullBody;
}
@Override
public Source getSource(Exchange exchange) throws Exception {
// only convert to input stream if really needed
if (isInputStreamNeeded(exchange)) {
InputStream is = exchange.getIn().getBody(InputStream.class);
return getSource(exchange, is);
} else {
Object body = exchange.getIn().getBody();
return getSource(exchange, body);
}
}
/**
* Checks whether we need an {@link InputStream} to access the message body.
* <p/>
* Depending on the content in the message body, we may not need to convert
* to {@link InputStream}.
*
* @param exchange the current exchange
* @return <tt>true</tt> to convert to {@link InputStream} beforehand converting to {@link Source} afterwards.
*/
protected boolean isInputStreamNeeded(Exchange exchange) {
Object body = exchange.getIn().getBody();
if (body == null) {
return false;
}
if (body instanceof InputStream) {
return true;
} else if (body instanceof Source) {
return false;
} else if (body instanceof String) {
return false;
} else if (body instanceof byte[]) {
return false;
} else if (body instanceof Node) {
return false;
} else if (exchange.getContext().getTypeConverterRegistry().lookup(Source.class, body.getClass()) != null) {
//there is a direct and hopefully optimized converter to Source
return false;
}
// yes an input stream is needed
return true;
}
/**
* Converts the inbound body to a {@link Source}, if the body is <b>not</b> already a {@link Source}.
* <p/>
* This implementation will prefer to source in the following order:
* <ul>
* <li>StAX - If StAX is allowed</li>
* <li>SAX - SAX as 2nd choice</li>
* <li>Stream - Stream as 3rd choice</li>
* <li>DOM - DOM as 4th choice</li>
* </ul>
*/
protected Source getSource(Exchange exchange, Object body) {
// body may already be a source
if (body instanceof Source) {
return (Source) body;
}
Source source = null;
if (body != null) {
// then try SAX
source = exchange.getContext().getTypeConverter().tryConvertTo(SAXSource.class, exchange, body);
if (source == null) {
// then try stream
source = exchange.getContext().getTypeConverter().tryConvertTo(StreamSource.class, exchange, body);
}
if (source == null) {
// and fallback to DOM
source = exchange.getContext().getTypeConverter().tryConvertTo(DOMSource.class, exchange, body);
}
// as the TypeConverterRegistry will look up source the converter differently if the type converter is loaded different
// now we just put the call of source converter at last
if (source == null) {
TypeConverter tc = exchange.getContext().getTypeConverterRegistry().lookup(Source.class, body.getClass());
if (tc != null) {
source = tc.convertTo(Source.class, exchange, body);
}
}
}
if (source == null) {
if (isFailOnNullBody()) {
throw new ExpectedBodyTypeException(exchange, Source.class);
} else {
try {
source = converter.toDOMSource(converter.createDocument());
} catch (ParserConfigurationException | TransformerException e) {
throw new RuntimeTransformException(e);
}
}
}
return source;
}
}