This is an automated email from the ASF dual-hosted git repository. orpiske pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new 6a363a7ee2a (chores) camel-cxf: code cleanup 6a363a7ee2a is described below commit 6a363a7ee2a1fd1b595ce4fa3ccc02e2885dcea2 Author: Otavio Rodolfo Piske <angusyo...@gmail.com> AuthorDate: Mon May 13 11:44:23 2024 +0200 (chores) camel-cxf: code cleanup - break large and complex methods - use final when possible - use Java-style array declaration - use charset constants - fix logging --- .../camel/component/cxf/common/CxfPayload.java | 2 +- .../component/cxf/converter/CachedCxfPayload.java | 35 +- .../component/cxf/converter/CxfConverter.java | 53 +- .../cxf/converter/CxfPayloadConverter.java | 217 ++++---- .../component/cxf/jaxrs/CamelResourceProvider.java | 2 +- .../camel/component/cxf/jaxrs/CxfConverter.java | 30 +- .../camel/component/cxf/jaxrs/CxfRsComponent.java | 110 ++-- .../camel/component/cxf/jaxrs/CxfRsEndpoint.java | 44 +- .../camel/component/cxf/jaxrs/CxfRsProducer.java | 85 +-- .../component/cxf/jaxrs/DataFormatProvider.java | 2 +- .../component/cxf/jaxrs/DefaultCxfRsBinding.java | 86 ++-- .../component/cxf/jaxrs/SimpleCxfRsBinding.java | 49 +- .../component/cxf/jaxrs/CxfRsStreamCacheTest.java | 4 +- .../cxf/feature/AbstractDataFormatFeature.java | 48 +- .../RawMessageContentRedirectInterceptor.java | 51 +- .../camel/component/cxf/jaxws/CxfComponent.java | 75 +-- .../camel/component/cxf/jaxws/CxfConsumer.java | 92 ++-- .../camel/component/cxf/jaxws/CxfEndpoint.java | 186 ++++--- .../camel/component/cxf/jaxws/CxfProducer.java | 78 ++- .../component/cxf/jaxws/DefaultCxfBinding.java | 568 ++++++++++++--------- .../cxf/jaxws/CxfConsumerStreamCacheTest.java | 4 +- .../component/cxf/CxfDispatchMessageTest.java | 3 +- .../component/cxf/CxfDispatchPayloadTest.java | 3 +- .../cxf/mtom/CxfJavaMtomProducerPayloadTest.java | 5 +- .../component/cxf/mtom/CxfMtomConsumerTest.java | 9 +- .../cxf/mtom/CxfMtomProducerPayloadModeTest.java | 3 +- .../cxf/transport/CamelDestinationTest.java | 2 +- .../component/cxf/transport/CamelConduit.java | 8 +- .../component/cxf/transport/CamelDestination.java | 4 +- .../component/cxf/transport/CamelOutputStream.java | 8 +- .../cxf/transport/CamelTransportFactory.java | 40 +- .../transport/header/CxfHeaderFilterStrategy.java | 2 +- 32 files changed, 1107 insertions(+), 801 deletions(-) diff --git a/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/common/CxfPayload.java b/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/common/CxfPayload.java index fde600aa40b..9adf76fea75 100644 --- a/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/common/CxfPayload.java +++ b/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/common/CxfPayload.java @@ -38,7 +38,7 @@ import org.apache.cxf.staxutils.StaxUtils; public class CxfPayload<T> { private List<Source> body; - private List<T> headers; + private final List<T> headers; private Map<String, String> nsMap; public CxfPayload(List<T> headers, List<Source> body, Map<String, String> nsMap) { diff --git a/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/converter/CachedCxfPayload.java b/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/converter/CachedCxfPayload.java index 459b721b4cf..fd8968b845d 100644 --- a/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/converter/CachedCxfPayload.java +++ b/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/converter/CachedCxfPayload.java @@ -55,7 +55,7 @@ import org.slf4j.LoggerFactory; */ public class CachedCxfPayload<T> extends CxfPayload<T> implements StreamCache { private static final Logger LOG = LoggerFactory.getLogger(CachedCxfPayload.class); - private static String defaultCharset = ObjectHelper.getSystemProperty("org.apache.camel.default.charset", "UTF-8"); + private static final String DEFAULT_CHARSET = ObjectHelper.getSystemProperty("org.apache.camel.default.charset", "UTF-8"); public CachedCxfPayload(CxfPayload<T> orig, Exchange exchange) { super(orig.getHeaders(), new ArrayList<>(orig.getBodySources()), orig.getNsMap()); @@ -86,19 +86,8 @@ public class CachedCxfPayload<T> extends CxfPayload<T> implements StreamCache { // this worked so continue continue; } catch (Exception e) { - // fallback to trying to read the reader using another way - StreamResult sr = new StreamResult(cos); - try { - toResult(source, sr); - li.set(new StreamSourceCache(cos.newStreamCache())); - // this worked so continue + if (tryUsingReader(cos, source, li)) { continue; - } catch (Exception e2) { - // ignore did not work so we will fallback to DOM mode - // this can happens in some rare cases such as reported by CAMEL-11681 - LOG.debug( - "Error during parsing XMLStreamReader from StaxSource/StAXSource. Will fallback to using DOM mode. This exception is ignored", - e2); } } } @@ -111,6 +100,24 @@ public class CachedCxfPayload<T> extends CxfPayload<T> implements StreamCache { orig.setBodySources(getBodySources()); } + private static boolean tryUsingReader(CachedOutputStream cos, Source source, ListIterator<Source> li) { + // fallback to trying to read the reader using another way + StreamResult sr = new StreamResult(cos); + try { + toResult(source, sr); + li.set(new StreamSourceCache(cos.newStreamCache())); + // this worked so continue + return true; + } catch (Exception e2) { + // ignore did not work so we will fallback to DOM mode + // this can happens in some rare cases such as reported by CAMEL-11681 + LOG.debug( + "Error during parsing XMLStreamReader from StaxSource/StAXSource. Will fallback to using DOM mode. This exception is ignored", + e2); + } + return false; + } + private CachedCxfPayload(CachedCxfPayload<T> orig, Exchange exchange) throws IOException { super(orig.getHeaders(), new ArrayList<>(orig.getBodySources()), orig.getNsMap()); ListIterator<Source> li = getBodySources().listIterator(); @@ -131,7 +138,7 @@ public class CachedCxfPayload<T> extends CxfPayload<T> implements StreamCache { throw new TransformerException("Could not create a transformer - JAXP is misconfigured!"); } else { Properties outputProperties = new Properties(); - outputProperties.put("encoding", defaultCharset); + outputProperties.put("encoding", DEFAULT_CHARSET); outputProperties.put("omit-xml-declaration", "yes"); transformer.setOutputProperties(outputProperties); diff --git a/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/converter/CxfConverter.java b/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/converter/CxfConverter.java index 7b9af2687e8..8ed02c22bd0 100644 --- a/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/converter/CxfConverter.java +++ b/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/converter/CxfConverter.java @@ -138,36 +138,41 @@ public final class CxfConverter { } // try to turn the first array element into the object that we want - for (Object embedded : list) { - if (embedded != null) { - if (type.isInstance(embedded)) { - return type.cast(embedded); - } else { - TypeConverter tc = registry.lookup(type, embedded.getClass()); - if (tc == null) { - // maybe one of its interface fits - for (Class<?> clazz : embedded.getClass().getInterfaces()) { - tc = registry.lookup(type, clazz); - if (tc != null) { - break; - } + return tryCoerceFirstArrayElement(type, exchange, registry, list); + } + + return null; + } + + public static <T> T tryCoerceFirstArrayElement( + Class<T> type, Exchange exchange, TypeConverterRegistry registry, MessageContentsList list) { + for (Object embedded : list) { + if (embedded != null) { + if (type.isInstance(embedded)) { + return type.cast(embedded); + } else { + TypeConverter tc = registry.lookup(type, embedded.getClass()); + if (tc == null) { + // maybe one of its interfaces fits + for (Class<?> clazz : embedded.getClass().getInterfaces()) { + tc = registry.lookup(type, clazz); + if (tc != null) { + break; } } - if (tc != null) { - Object result = tc.convertTo(type, exchange, embedded); - if (result != null) { - return (T) result; - } - // there is no suitable result will be return - break; + } + if (tc != null) { + Object result = tc.convertTo(type, exchange, embedded); + if (result != null) { + return (T) result; } + // there is no suitable result will be return + break; } } } - // return void to indicate its not possible to convert at this time - return (T) MISS_VALUE; } - - return null; + // return void to indicate its not possible to convert at this time + return (T) MISS_VALUE; } } diff --git a/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/converter/CxfPayloadConverter.java b/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/converter/CxfPayloadConverter.java index c984af7c958..9a09861f205 100644 --- a/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/converter/CxfPayloadConverter.java +++ b/components/camel-cxf/camel-cxf-common/src/main/java/org/apache/camel/component/cxf/converter/CxfPayloadConverter.java @@ -125,56 +125,9 @@ public final class CxfPayloadConverter { // CxfPayloads from other types if (type.isAssignableFrom(CxfPayload.class)) { try { - if (!value.getClass().isArray()) { - Source src = null; - // many of the common format that can have a Source created - // directly - if (value instanceof InputStream) { - src = new StreamSource((InputStream) value); - } else if (value instanceof Reader) { - src = new StreamSource((Reader) value); - } else if (value instanceof String) { - src = new StreamSource(new StringReader((String) value)); - } else if (value instanceof Node) { - src = new DOMSource((Node) value); - } else if (value instanceof Source) { - src = (Source) value; - } - if (src == null) { - // assuming staxsource is preferred, otherwise use the - // one preferred - TypeConverter tc = registry.lookup(javax.xml.transform.stax.StAXSource.class, value.getClass()); - if (tc == null) { - tc = registry.lookup(Source.class, value.getClass()); - } - if (tc != null) { - src = tc.convertTo(Source.class, exchange, value); - } - } - if (src != null) { - return (T) sourceToCxfPayload(src, exchange); - } - } - TypeConverter tc = registry.lookup(NodeList.class, value.getClass()); - if (tc != null) { - NodeList nodeList = tc.convertTo(NodeList.class, exchange, value); - return (T) nodeListToCxfPayload(nodeList, exchange); - } - tc = registry.lookup(Document.class, value.getClass()); - if (tc != null) { - Document document = tc.convertTo(Document.class, exchange, value); - return (T) documentToCxfPayload(document, exchange); - } - // maybe we can convert via an InputStream - CxfPayload<?> p; - p = convertVia(InputStream.class, exchange, value, registry); - if (p != null) { - return (T) p; - } - // String is the converter of last resort - p = convertVia(String.class, exchange, value, registry); - if (p != null) { - return (T) p; + final T src = tryConvertViaCxfPayload(exchange, value, registry); + if (src != null) { + return src; } } catch (RuntimeCamelException e) { // the internal conversion to XML can throw an exception if the content is not XML @@ -185,19 +138,16 @@ public final class CxfPayloadConverter { return null; } // Convert a CxfPayload into something else + return tryConvertCxfPayload(type, exchange, value, registry); + } + + private static <T> T tryConvertCxfPayload(Class<T> type, Exchange exchange, Object value, TypeConverterRegistry registry) { if (CxfPayload.class.isAssignableFrom(value.getClass())) { CxfPayload<?> payload = (CxfPayload<?>) value; int size = payload.getBodySources().size(); if (size == 1) { if (type.isAssignableFrom(Document.class)) { - Source s = payload.getBodySources().get(0); - Document d; - try { - d = StaxUtils.read(s); - } catch (XMLStreamException e) { - throw new RuntimeException(e); - } - return type.cast(d); + return tryFromDocument(type, payload); } // CAMEL-8410 Just make sure we get the Source object directly from the payload body source Source s = payload.getBodySources().get(0); @@ -206,51 +156,23 @@ public final class CxfPayloadConverter { } TypeConverter tc = registry.lookup(type, XMLStreamReader.class); if (tc != null && (s instanceof StaxSource || s instanceof StAXSource)) { - XMLStreamReader r = (s instanceof StAXSource) - ? ((StAXSource) s).getXMLStreamReader() : ((StaxSource) s).getXMLStreamReader(); - if (payload.getNsMap() != null) { - r = new DelegatingXMLStreamReader(r, payload.getNsMap()); - } - return tc.convertTo(type, exchange, r); + return tryFromStaxSource(type, exchange, s, payload, tc); } tc = registry.lookup(type, Source.class); if (tc != null) { - XMLStreamReader r = null; - if (payload.getNsMap() != null) { - if (s instanceof StaxSource) { - r = ((StaxSource) s).getXMLStreamReader(); - } else if (s instanceof StAXSource) { - r = ((StAXSource) s).getXMLStreamReader(); - } - if (r != null) { - s = new StAXSource(new DelegatingXMLStreamReader(r, payload.getNsMap())); - } - } - return tc.convertTo(type, exchange, s); + return tryFromSource(type, exchange, payload, s, tc); } } TypeConverter tc = registry.lookup(type, NodeList.class); if (tc != null) { - Object result = tc.convertTo(type, exchange, cxfPayloadToNodeList((CxfPayload<?>) value, exchange)); - if (result == null) { - // no we could not do it currently, and we just abort the convert here - return (T) MISS_VALUE; - } else { - return (T) result; - } + return tryForNodeList(type, exchange, (CxfPayload<?>) value, tc); } // we cannot convert a node list, so we try the first item from the // node list tc = registry.lookup(type, Node.class); if (tc != null) { - NodeList nodeList = cxfPayloadToNodeList((CxfPayload<?>) value, exchange); - if (nodeList.getLength() > 0) { - return tc.convertTo(type, exchange, nodeList.item(0)); - } else { - // no we could not do it currently - return (T) MISS_VALUE; - } + return tryFromNode(type, exchange, (CxfPayload<?>) value, tc); } else { if (size == 0) { // empty size so we cannot convert @@ -261,6 +183,121 @@ public final class CxfPayloadConverter { return null; } + private static <T> T tryConvertViaCxfPayload(Exchange exchange, Object value, TypeConverterRegistry registry) { + if (!value.getClass().isArray()) { + Source src = getSourceFromCommonFormats(value); + if (src == null) { + // assuming staxsource is preferred, otherwise use the + // one preferred + TypeConverter tc = registry.lookup(StAXSource.class, value.getClass()); + if (tc == null) { + tc = registry.lookup(Source.class, value.getClass()); + } + if (tc != null) { + src = tc.convertTo(Source.class, exchange, value); + } + } + if (src != null) { + return (T) sourceToCxfPayload(src, exchange); + } + } + final TypeConverter nodeListTc = registry.lookup(NodeList.class, value.getClass()); + if (nodeListTc != null) { + NodeList nodeList = nodeListTc.convertTo(NodeList.class, exchange, value); + return (T) nodeListToCxfPayload(nodeList, exchange); + } + final TypeConverter documentTc = registry.lookup(Document.class, value.getClass()); + if (documentTc != null) { + Document document = documentTc.convertTo(Document.class, exchange, value); + return (T) documentToCxfPayload(document, exchange); + } + // maybe we can convert via an InputStream + final CxfPayload<?> inputStreamPayload = convertVia(InputStream.class, exchange, value, registry); + if (inputStreamPayload != null) { + return (T) inputStreamPayload; + } + // String is the converter of last resort + final CxfPayload<?> stringPayload = convertVia(String.class, exchange, value, registry); + if (stringPayload != null) { + return (T) stringPayload; + } + return null; + } + + private static <T> T tryFromNode(Class<T> type, Exchange exchange, CxfPayload<?> value, TypeConverter tc) { + NodeList nodeList = cxfPayloadToNodeList(value, exchange); + if (nodeList.getLength() > 0) { + return tc.convertTo(type, exchange, nodeList.item(0)); + } else { + // no we could not do it currently + return (T) MISS_VALUE; + } + } + + private static <T> T tryForNodeList(Class<T> type, Exchange exchange, CxfPayload<?> value, TypeConverter tc) { + Object result = tc.convertTo(type, exchange, cxfPayloadToNodeList(value, exchange)); + if (result == null) { + // no we could not do it currently, and we just abort the convert here + return (T) MISS_VALUE; + } else { + return (T) result; + } + } + + private static <T> T tryFromSource(Class<T> type, Exchange exchange, CxfPayload<?> payload, Source s, TypeConverter tc) { + XMLStreamReader r = null; + if (payload.getNsMap() != null) { + if (s instanceof StaxSource) { + r = ((StaxSource) s).getXMLStreamReader(); + } else if (s instanceof StAXSource) { + r = ((StAXSource) s).getXMLStreamReader(); + } + if (r != null) { + s = new StAXSource(new DelegatingXMLStreamReader(r, payload.getNsMap())); + } + } + return tc.convertTo(type, exchange, s); + } + + private static < + T> T tryFromStaxSource(Class<T> type, Exchange exchange, Source s, CxfPayload<?> payload, TypeConverter tc) { + XMLStreamReader r = (s instanceof StAXSource) + ? ((StAXSource) s).getXMLStreamReader() : ((StaxSource) s).getXMLStreamReader(); + if (payload.getNsMap() != null) { + r = new DelegatingXMLStreamReader(r, payload.getNsMap()); + } + return tc.convertTo(type, exchange, r); + } + + private static <T> T tryFromDocument(Class<T> type, CxfPayload<?> payload) { + Source s = payload.getBodySources().get(0); + Document d; + try { + d = StaxUtils.read(s); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + return type.cast(d); + } + + private static Source getSourceFromCommonFormats(Object value) { + Source src = null; + // many of the common format that can have a Source created + // directly + if (value instanceof InputStream) { + src = new StreamSource((InputStream) value); + } else if (value instanceof Reader) { + src = new StreamSource((Reader) value); + } else if (value instanceof String) { + src = new StreamSource(new StringReader((String) value)); + } else if (value instanceof Node) { + src = new DOMSource((Node) value); + } else if (value instanceof Source) { + src = (Source) value; + } + return src; + } + private static < T, V> CxfPayload<T> convertVia(Class<V> via, Exchange exchange, Object value, TypeConverterRegistry registry) { TypeConverter tc = registry.lookup(via, value.getClass()); diff --git a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CamelResourceProvider.java b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CamelResourceProvider.java index fbfdf3fd8b4..60bbe27e185 100644 --- a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CamelResourceProvider.java +++ b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CamelResourceProvider.java @@ -24,7 +24,7 @@ import org.apache.cxf.message.Message; public class CamelResourceProvider implements ResourceProvider { // Using the dynamical proxy to provide the instance of client to invoke - private Class<?> clazz; + private final Class<?> clazz; private ResourceProvider provider; public CamelResourceProvider(Class<?> clazz) { diff --git a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfConverter.java b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfConverter.java index d04f46c47e0..7f86e18a6e7 100644 --- a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfConverter.java +++ b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfConverter.java @@ -37,6 +37,7 @@ import org.apache.camel.support.ExchangeHelper; import org.apache.cxf.message.MessageContentsList; import static org.apache.camel.TypeConverter.MISS_VALUE; +import static org.apache.camel.component.cxf.converter.CxfConverter.tryCoerceFirstArrayElement; /** * The <a href="http://camel.apache.org/type-converter.html">Type Converters</a> for CXF related types' converting . @@ -144,34 +145,7 @@ public final class CxfConverter { MessageContentsList list = (MessageContentsList) value; // try to turn the first array element into the object that we want - for (Object embedded : list) { - if (embedded != null) { - if (type.isInstance(embedded)) { - return type.cast(embedded); - } else { - TypeConverter tc = registry.lookup(type, embedded.getClass()); - if (tc == null) { - // maybe one of its interface fits - for (Class<?> clazz : embedded.getClass().getInterfaces()) { - tc = registry.lookup(type, clazz); - if (tc != null) { - break; - } - } - } - if (tc != null) { - Object result = tc.convertTo(type, exchange, embedded); - if (result != null) { - return (T) result; - } - // there is no suitable result will be return - break; - } - } - } - } - // return void to indicate its not possible to convert at this time - return (T) MISS_VALUE; + return tryCoerceFirstArrayElement(type, exchange, registry, list); } // CXF-RS Response class diff --git a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsComponent.java b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsComponent.java index dd4bf523919..7746740c804 100644 --- a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsComponent.java +++ b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsComponent.java @@ -54,8 +54,6 @@ public class CxfRsComponent extends HeaderFilterStrategyComponent implements SSL @Override protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { - CxfRsEndpoint answer; - Object value = parameters.remove("setDefaultBus"); if (value != null) { LOG.warn("The option setDefaultBus is @deprecated, use name defaultBus instead"); @@ -64,60 +62,15 @@ public class CxfRsComponent extends HeaderFilterStrategyComponent implements SSL } } - if (remaining.startsWith(CxfConstants.SPRING_CONTEXT_ENDPOINT)) { - // Get the bean from the Spring context - String beanId = remaining.substring(CxfConstants.SPRING_CONTEXT_ENDPOINT.length()); - if (beanId.startsWith("//")) { - beanId = beanId.substring(2); - } - - AbstractJAXRSFactoryBean bean = CamelContextHelper.mandatoryLookup(getCamelContext(), beanId, - AbstractJAXRSFactoryBean.class); - - CxfRsEndpointFactoryBean factory = null; - if (bean.getClass().getName().contains("blueprint")) { - // use blueprint - Class<CxfRsEndpointFactoryBean> clazz = getCamelContext().getClassResolver().resolveMandatoryClass( - "org.apache.camel.component.cxf.jaxrs.blueprint.CxfRsBlueprintEndpointFactoryBean", - CxfRsEndpointFactoryBean.class); - factory = getCamelContext().getInjector().newInstance(clazz); - } else { - try { - //try spring first - Class<CxfRsEndpointFactoryBean> clazz = getCamelContext().getClassResolver() - .resolveMandatoryClass("org.apache.camel.component.cxf.spring.jaxrs.SpringCxfRsEndpointFactoryBean", - CxfRsEndpointFactoryBean.class); - factory = getCamelContext().getInjector().newInstance(clazz); - } catch (Exception ex) { - factory = new DefaultCxfRsEndpointFactoryBean(); - } - } - answer = factory.createEndpoint(this, remaining, bean); - - // Apply Spring bean properties (including # notation referenced bean). Note that the - // Spring bean properties values can be overridden by property defined in URI query. - // The super class (DefaultComponent) will invoke "setProperties" after this method - // with to apply properties defined by URI query. - if (bean.getProperties() != null) { - Map<String, Object> copy = new HashMap<>(bean.getProperties()); - setProperties(answer, copy); - } - // setup the skipFaultLogging - - answer.setBeanId(beanId); + final CxfRsEndpoint answer = doCreateEndpoint(remaining); - } else { - // endpoint URI does not specify a bean - answer = new CxfRsEndpoint(remaining, this); - } - - String resourceClass = getAndRemoveParameter(parameters, "resourceClass", String.class); + final String resourceClass = getAndRemoveParameter(parameters, "resourceClass", String.class); if (resourceClass != null) { Class<?> clazz = getCamelContext().getClassResolver().resolveMandatoryClass(resourceClass); answer.addResourceClass(clazz); } - String resourceClasses = getAndRemoveParameter(parameters, "resourceClasses", String.class); + final String resourceClasses = getAndRemoveParameter(parameters, "resourceClasses", String.class); Iterator<?> it = ObjectHelper.createIterator(resourceClasses); while (it.hasNext()) { String name = (String) it.next(); @@ -138,6 +91,63 @@ public class CxfRsComponent extends HeaderFilterStrategyComponent implements SSL return answer; } + private CxfRsEndpoint doCreateEndpoint(String remaining) throws Exception { + final CxfRsEndpoint answer; + if (remaining.startsWith(CxfConstants.SPRING_CONTEXT_ENDPOINT)) { + answer = createSpringContextEndpoint(remaining); + + } else { + // endpoint URI does not specify a bean + answer = new CxfRsEndpoint(remaining, this); + } + return answer; + } + + private CxfRsEndpoint createSpringContextEndpoint(String remaining) throws Exception { + + // Get the bean from the Spring context + String beanId = remaining.substring(CxfConstants.SPRING_CONTEXT_ENDPOINT.length()); + if (beanId.startsWith("//")) { + beanId = beanId.substring(2); + } + + AbstractJAXRSFactoryBean bean = CamelContextHelper.mandatoryLookup(getCamelContext(), beanId, + AbstractJAXRSFactoryBean.class); + + CxfRsEndpointFactoryBean factory = null; + if (bean.getClass().getName().contains("blueprint")) { + // use blueprint + Class<CxfRsEndpointFactoryBean> clazz = getCamelContext().getClassResolver().resolveMandatoryClass( + "org.apache.camel.component.cxf.jaxrs.blueprint.CxfRsBlueprintEndpointFactoryBean", + CxfRsEndpointFactoryBean.class); + factory = getCamelContext().getInjector().newInstance(clazz); + } else { + try { + //try spring first + Class<CxfRsEndpointFactoryBean> clazz = getCamelContext().getClassResolver() + .resolveMandatoryClass("org.apache.camel.component.cxf.spring.jaxrs.SpringCxfRsEndpointFactoryBean", + CxfRsEndpointFactoryBean.class); + factory = getCamelContext().getInjector().newInstance(clazz); + } catch (Exception ex) { + factory = new DefaultCxfRsEndpointFactoryBean(); + } + } + final CxfRsEndpoint answer = factory.createEndpoint(this, remaining, bean); + + // Apply Spring bean properties (including # notation referenced bean). Note that the + // Spring bean properties values can be overridden by property defined in URI query. + // The super class (DefaultComponent) will invoke "setProperties" after this method + // with to apply properties defined by URI query. + if (bean.getProperties() != null) { + Map<String, Object> copy = new HashMap<>(bean.getProperties()); + setProperties(answer, copy); + } + // setup the skipFaultLogging + + answer.setBeanId(beanId); + return answer; + } + @Override protected void afterConfiguration(String uri, String remaining, Endpoint endpoint, Map<String, Object> parameters) throws Exception { diff --git a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java index 39094b9835c..8da6e9f6cda 100644 --- a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java +++ b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java @@ -374,28 +374,40 @@ public class CxfRsEndpoint extends DefaultEndpoint implements HeaderFilterStrate } if (getProperties() != null) { - if (factory.getProperties() != null) { - // add to existing properties - factory.getProperties().putAll(getProperties()); - } else { - factory.setProperties(getProperties()); - } - LOG.debug("JAXRS FactoryBean: {} added properties: {}", factory, getProperties()); + setupProperties(factory); } if (isLoggingFeatureEnabled()) { - LoggingFeature loggingFeature = new LoggingFeature(); - if (getLoggingSizeLimit() >= -1) { - loggingFeature.setLimit(getLoggingSizeLimit()); - } - factory.getFeatures().add(loggingFeature); + setupLoggingFeature(factory); } if (this.isSkipFaultLogging()) { - if (factory.getProperties() == null) { - factory.setProperties(new HashMap<>()); - } - factory.getProperties().put(FaultListener.class.getName(), new NullFaultListener()); + setupSkipFaultLogging(factory); + } + } + + private void setupProperties(AbstractJAXRSFactoryBean factory) { + if (factory.getProperties() != null) { + // add to existing properties + factory.getProperties().putAll(getProperties()); + } else { + factory.setProperties(getProperties()); + } + LOG.debug("JAXRS FactoryBean: {} added properties: {}", factory, getProperties()); + } + + private void setupLoggingFeature(AbstractJAXRSFactoryBean factory) { + LoggingFeature loggingFeature = new LoggingFeature(); + if (getLoggingSizeLimit() >= -1) { + loggingFeature.setLimit(getLoggingSizeLimit()); + } + factory.getFeatures().add(loggingFeature); + } + + private static void setupSkipFaultLogging(AbstractJAXRSFactoryBean factory) { + if (factory.getProperties() == null) { + factory.setProperties(new HashMap<>()); } + factory.getProperties().put(FaultListener.class.getName(), new NullFaultListener()); } protected JAXRSServerFactoryBean newJAXRSServerFactoryBean() { diff --git a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java index 35029ec7c6f..809bd7c8801 100644 --- a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java +++ b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java @@ -154,11 +154,7 @@ public class CxfRsProducer extends DefaultAsyncProducer { // set the path if (path != null) { - if (ObjectHelper.isNotEmpty(pathValues) && pathValues.length > 0) { - client.path(path, pathValues); - } else { - client.path(path); - } + setupPath(pathValues, client, path); } CxfRsEndpoint cxfRsEndpoint = (CxfRsEndpoint) getEndpoint(); @@ -306,27 +302,21 @@ public class CxfRsProducer extends DefaultAsyncProducer { if (bus != null) { cfb.setBus(bus); } - WebClient client = cfb.createWebClient(); + final WebClient client = cfb.createWebClient(); ((CxfRsEndpoint) getEndpoint()).getChainedCxfRsEndpointConfigurer().configureClient(client); - String httpMethod = inMessage.getHeader(CxfConstants.HTTP_METHOD, String.class); - Class<?> responseClass = inMessage.getHeader(CxfConstants.CAMEL_CXF_RS_RESPONSE_CLASS, Class.class); - Type genericType = inMessage.getHeader(CxfConstants.CAMEL_CXF_RS_RESPONSE_GENERIC_TYPE, Type.class); - Object[] pathValues = inMessage.getHeader(CxfConstants.CAMEL_CXF_RS_VAR_VALUES, Object[].class); - String path = inMessage.getHeader(CxfConstants.HTTP_PATH, String.class); + final String httpMethod = inMessage.getHeader(CxfConstants.HTTP_METHOD, String.class); + final Class<?> responseClass = inMessage.getHeader(CxfConstants.CAMEL_CXF_RS_RESPONSE_CLASS, Class.class); + final Type genericType = inMessage.getHeader(CxfConstants.CAMEL_CXF_RS_RESPONSE_GENERIC_TYPE, Type.class); + final Object[] pathValues = inMessage.getHeader(CxfConstants.CAMEL_CXF_RS_VAR_VALUES, Object[].class); + final String path = inMessage.getHeader(CxfConstants.HTTP_PATH, String.class); if (LOG.isTraceEnabled()) { - LOG.trace("HTTP method = {}", httpMethod); - LOG.trace("path = {}", path); - LOG.trace("responseClass = {}", responseClass); + logInvokation(httpMethod, path, responseClass); } // set the path if (path != null) { - if (ObjectHelper.isNotEmpty(pathValues) && pathValues.length > 0) { - client.path(path, pathValues); - } else { - client.path(path); - } + setupPath(pathValues, client, path); } CxfRsEndpoint cxfRsEndpoint = (CxfRsEndpoint) getEndpoint(); @@ -378,20 +368,11 @@ public class CxfRsProducer extends DefaultAsyncProducer { //Throw exception on a response > 207 //http://en.wikipedia.org/wiki/List_of_HTTP_status_codes if (throwException) { - if (response instanceof Response) { - int respCode = ((Response) response).getStatus(); - if (respCode > 207) { - throw populateCxfRsProducerException(exchange, (Response) response, respCode); - } - } + evalException(exchange, response); } // set response if (exchange.getPattern().isOutCapable()) { - LOG.trace("Response body = {}", response); - exchange.getOut().getHeaders().putAll(exchange.getIn().getHeaders()); - exchange.getMessage().setBody(binding.bindResponseToCamelBody(response, exchange)); - exchange.getMessage().getHeaders().putAll(binding.bindResponseHeadersToCamelHeaders(response, exchange)); - exchange.getMessage().setHeader(CxfConstants.HTTP_RESPONSE_CODE, statesCode); + setResponse(exchange, response, binding, statesCode); } else { // just close the input stream of the response object if (response instanceof Response) { @@ -400,6 +381,37 @@ public class CxfRsProducer extends DefaultAsyncProducer { } } + private static void setResponse(Exchange exchange, Object response, CxfRsBinding binding, int statesCode) throws Exception { + LOG.trace("Response body = {}", response); + exchange.getOut().getHeaders().putAll(exchange.getIn().getHeaders()); + exchange.getMessage().setBody(binding.bindResponseToCamelBody(response, exchange)); + exchange.getMessage().getHeaders().putAll(binding.bindResponseHeadersToCamelHeaders(response, exchange)); + exchange.getMessage().setHeader(CxfConstants.HTTP_RESPONSE_CODE, statesCode); + } + + private void evalException(Exchange exchange, Object response) throws CxfOperationException { + if (response instanceof Response) { + int respCode = ((Response) response).getStatus(); + if (respCode > 207) { + throw populateCxfRsProducerException(exchange, (Response) response, respCode); + } + } + } + + private static void setupPath(Object[] pathValues, WebClient client, String path) { + if (ObjectHelper.isNotEmpty(pathValues) && pathValues.length > 0) { + client.path(path, pathValues); + } else { + client.path(path); + } + } + + private static void logInvokation(String httpMethod, String path, Class<?> responseClass) { + LOG.trace("HTTP method = {}", httpMethod); + LOG.trace("path = {}", path); + LOG.trace("responseClass = {}", responseClass); + } + private void saveCookies(Exchange exchange, Client client, CookieHandler cookieHandler) { if (cookieHandler != null) { CookieStore cookieStore = cookieHandler.getCookieStore(exchange); @@ -473,22 +485,13 @@ public class CxfRsProducer extends DefaultAsyncProducer { // handle cookies saveCookies(exchange, target, cookieHandler); if (throwException) { - if (response instanceof Response) { - int respCode = ((Response) response).getStatus(); - if (respCode > 207) { - throw populateCxfRsProducerException(exchange, (Response) response, respCode); - } - } + evalException(exchange, response); } CxfRsEndpoint cxfRsEndpoint = (CxfRsEndpoint) getEndpoint(); CxfRsBinding binding = cxfRsEndpoint.getBinding(); if (exchange.getPattern().isOutCapable()) { - LOG.trace("Response body = {}", response); - exchange.getOut().getHeaders().putAll(exchange.getIn().getHeaders()); - exchange.getMessage().setBody(binding.bindResponseToCamelBody(response, exchange)); - exchange.getMessage().getHeaders().putAll(binding.bindResponseHeadersToCamelHeaders(response, exchange)); - exchange.getMessage().setHeader(CxfConstants.HTTP_RESPONSE_CODE, statesCode); + setResponse(exchange, response, binding, statesCode); } else { // just close the input stream of the response object if (response instanceof Response) { diff --git a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/DataFormatProvider.java b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/DataFormatProvider.java index 751564f0bb0..72990b89bca 100644 --- a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/DataFormatProvider.java +++ b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/DataFormatProvider.java @@ -37,7 +37,7 @@ import org.apache.cxf.jaxrs.utils.JAXRSUtils; public class DataFormatProvider<T> implements MessageBodyWriter<T>, MessageBodyReader<T> { - private Map<String, DataFormat> formats = new HashMap<>(); + private final Map<String, DataFormat> formats = new HashMap<>(); @Override public boolean isReadable(Class<?> cls, Type type, Annotation[] anns, MediaType mt) { diff --git a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java index 2bf3e08af8f..b46fea88a17 100644 --- a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java +++ b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java @@ -89,51 +89,59 @@ public class DefaultCxfRsBinding implements CxfRsBinding, HeaderFilterStrategyAw Object o = response.getBody(); if (!(o instanceof Response)) { - //not a JAX-RS Response object, we need to set the headers from the Camel values - - if (response.getHeader(CxfConstants.PROTOCOL_HEADERS) != null) { - Map<String, Object> headers - = CastUtils.cast((Map<?, ?>) response.getHeader(CxfConstants.PROTOCOL_HEADERS)); - if (!ObjectHelper.isEmpty(cxfExchange) && !ObjectHelper.isEmpty(cxfExchange.getOutMessage())) { - cxfExchange.getOutMessage().putIfAbsent(CxfConstants.PROTOCOL_HEADERS, - new TreeMap<>(String.CASE_INSENSITIVE_ORDER)); - } - final Map<String, List<String>> cxfHeaders = CastUtils - .cast((Map<?, ?>) cxfExchange.getOutMessage().get(CxfConstants.PROTOCOL_HEADERS)); - - for (Map.Entry<String, Object> ent : headers.entrySet()) { - List<String> v; - if (ent.getValue() instanceof List) { - v = CastUtils.cast((List<?>) ent.getValue()); - } else { - v = Arrays.asList(ent.getValue().toString()); - } - cxfHeaders.put(ent.getKey(), v); - } + populateViaResponse(cxfExchange, response); + } + return o; + } + + private static void populateViaResponse(org.apache.cxf.message.Exchange cxfExchange, Message response) { + //not a JAX-RS Response object, we need to set the headers from the Camel values + + if (response.getHeader(CxfConstants.PROTOCOL_HEADERS) != null) { + setProtocolHeaders(cxfExchange, response); + } + + if (response.getHeader(CxfConstants.HTTP_RESPONSE_CODE) != null + && !cxfExchange.containsKey(org.apache.cxf.message.Message.RESPONSE_CODE)) { + cxfExchange.put(org.apache.cxf.message.Message.RESPONSE_CODE, + response.getHeader(CxfConstants.HTTP_RESPONSE_CODE, Integer.class)); + } + if (response.getHeader(CxfConstants.CONTENT_TYPE) != null + && !cxfExchange.containsKey(org.apache.cxf.message.Message.CONTENT_TYPE)) { + if (!ObjectHelper.isEmpty(cxfExchange) && !ObjectHelper.isEmpty(cxfExchange.getOutMessage())) { + cxfExchange.getOutMessage().putIfAbsent(CxfConstants.PROTOCOL_HEADERS, + new TreeMap<>(String.CASE_INSENSITIVE_ORDER)); } + final Map<String, List<String>> cxfHeaders = CastUtils + .cast((Map<?, ?>) cxfExchange.getOutMessage().get(CxfConstants.PROTOCOL_HEADERS)); - if (response.getHeader(CxfConstants.HTTP_RESPONSE_CODE) != null - && !cxfExchange.containsKey(org.apache.cxf.message.Message.RESPONSE_CODE)) { - cxfExchange.put(org.apache.cxf.message.Message.RESPONSE_CODE, - response.getHeader(CxfConstants.HTTP_RESPONSE_CODE, Integer.class)); + if (!cxfHeaders.containsKey(CxfConstants.CONTENT_TYPE)) { + List<String> a = Arrays.asList((String) response.getHeader(CxfConstants.CONTENT_TYPE)); + cxfHeaders.put(CxfConstants.CONTENT_TYPE, a); + cxfExchange.getOutMessage().put(CxfConstants.CONTENT_TYPE, response.getHeader(CxfConstants.CONTENT_TYPE)); } - if (response.getHeader(CxfConstants.CONTENT_TYPE) != null - && !cxfExchange.containsKey(org.apache.cxf.message.Message.CONTENT_TYPE)) { - if (!ObjectHelper.isEmpty(cxfExchange) && !ObjectHelper.isEmpty(cxfExchange.getOutMessage())) { - cxfExchange.getOutMessage().putIfAbsent(CxfConstants.PROTOCOL_HEADERS, - new TreeMap<>(String.CASE_INSENSITIVE_ORDER)); - } - final Map<String, List<String>> cxfHeaders = CastUtils - .cast((Map<?, ?>) cxfExchange.getOutMessage().get(CxfConstants.PROTOCOL_HEADERS)); + } + } - if (!cxfHeaders.containsKey(CxfConstants.CONTENT_TYPE)) { - List<String> a = Arrays.asList((String) response.getHeader(CxfConstants.CONTENT_TYPE)); - cxfHeaders.put(CxfConstants.CONTENT_TYPE, a); - cxfExchange.getOutMessage().put(CxfConstants.CONTENT_TYPE, response.getHeader(CxfConstants.CONTENT_TYPE)); - } + private static void setProtocolHeaders(org.apache.cxf.message.Exchange cxfExchange, Message response) { + Map<String, Object> headers + = CastUtils.cast((Map<?, ?>) response.getHeader(CxfConstants.PROTOCOL_HEADERS)); + if (!ObjectHelper.isEmpty(cxfExchange) && !ObjectHelper.isEmpty(cxfExchange.getOutMessage())) { + cxfExchange.getOutMessage().putIfAbsent(CxfConstants.PROTOCOL_HEADERS, + new TreeMap<>(String.CASE_INSENSITIVE_ORDER)); + } + final Map<String, List<String>> cxfHeaders = CastUtils + .cast((Map<?, ?>) cxfExchange.getOutMessage().get(CxfConstants.PROTOCOL_HEADERS)); + + for (Map.Entry<String, Object> ent : headers.entrySet()) { + List<String> v; + if (ent.getValue() instanceof List) { + v = CastUtils.cast((List<?>) ent.getValue()); + } else { + v = Arrays.asList(ent.getValue().toString()); } + cxfHeaders.put(ent.getKey(), v); } - return o; } @Override diff --git a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/SimpleCxfRsBinding.java b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/SimpleCxfRsBinding.java index bbfa45d7ca9..7f5f942fc0e 100644 --- a/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/SimpleCxfRsBinding.java +++ b/components/camel-cxf/camel-cxf-rest/src/main/java/org/apache/camel/component/cxf/jaxrs/SimpleCxfRsBinding.java @@ -130,7 +130,7 @@ public class SimpleCxfRsBinding extends DefaultCxfRsBinding { private static final Object[] NO_PARAMETERS = null; /** Caches the Method to Parameters associations to avoid reflection with every request */ - private Map<Method, MethodSpec> methodSpecCache = new ConcurrentHashMap<>(); + private final Map<Method, MethodSpec> methodSpecCache = new ConcurrentHashMap<>(); @Override public void populateExchangeFromCxfRsRequest( @@ -342,26 +342,7 @@ public class SimpleCxfRsBinding extends DefaultCxfRsBinding { answer.multipartTypes = new String[paramCount]; // remember the names of parameters to be bound to headers and/or attachments for (int i = 0; i < paramCount; i++) { - // if the parameter has no annotations, let its array element remain = null - for (Annotation a : annotations[i]) { - // am I a header? - if (HEADER_ANNOTATIONS.contains(a.annotationType())) { - try { - answer.paramNames[i] = (String) a.annotationType().getMethod("value", NO_PARAMETER_TYPES).invoke(a, - NO_PARAMETERS); - answer.numberParameters++; - } catch (Exception e) { - } - } - - // am I multipart? - if (Multipart.class.equals(a.annotationType())) { - Multipart multipart = (Multipart) a; - answer.multipart = true; - answer.multipartNames[i] = multipart.value(); - answer.multipartTypes[i] = multipart.type(); - } - } + rememberParameter(annotations, i, answer); } // if we are not multipart and the number of detected JAX-RS parameters (query, headers, etc.) is less than the number of method parameters @@ -378,6 +359,32 @@ public class SimpleCxfRsBinding extends DefaultCxfRsBinding { return answer; } + private static void rememberParameter(Annotation[][] annotations, int i, MethodSpec answer) { + // if the parameter has no annotations, let its array element remain = null + for (Annotation a : annotations[i]) { + // am I a header? + if (HEADER_ANNOTATIONS.contains(a.annotationType())) { + try { + answer.paramNames[i] = (String) a.annotationType().getMethod("value", NO_PARAMETER_TYPES).invoke(a, + NO_PARAMETERS); + answer.numberParameters++; + } catch (Exception e) { + } + } + + // am I multipart? + if (Multipart.class.equals(a.annotationType())) { + rememberMultiPart(i, answer, (Multipart) a); + } + } + } + + private static void rememberMultiPart(int i, MethodSpec answer, Multipart multipart) { + answer.multipart = true; + answer.multipartNames[i] = multipart.value(); + answer.multipartTypes[i] = multipart.type(); + } + } } diff --git a/components/camel-cxf/camel-cxf-rest/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsStreamCacheTest.java b/components/camel-cxf/camel-cxf-rest/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsStreamCacheTest.java index 3070a4fb98d..2ecd882bc45 100644 --- a/components/camel-cxf/camel-cxf-rest/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsStreamCacheTest.java +++ b/components/camel-cxf/camel-cxf-rest/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsStreamCacheTest.java @@ -16,6 +16,8 @@ */ package org.apache.camel.component.cxf.jaxrs; +import java.nio.charset.StandardCharsets; + import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.cxf.common.CXFTestSupport; @@ -61,7 +63,7 @@ public class CxfRsStreamCacheTest extends CamelTestSupport { .process(exchange -> { // respond with OK CachedOutputStream cos = new CachedOutputStream(exchange); - cos.write(RESPONSE.getBytes("UTF-8")); + cos.write(RESPONSE.getBytes(StandardCharsets.UTF_8)); cos.close(); exchange.getMessage().setBody(cos.newStreamCache()); diff --git a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/feature/AbstractDataFormatFeature.java b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/feature/AbstractDataFormatFeature.java index c535b88b9f8..bb755bb2503 100644 --- a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/feature/AbstractDataFormatFeature.java +++ b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/feature/AbstractDataFormatFeature.java @@ -50,26 +50,38 @@ public abstract class AbstractDataFormatFeature extends AbstractFeature { protected void removeInterceptorWhichIsOutThePhases( List<Interceptor<? extends Message>> interceptors, String[] phaseNames, Set<String> needToBeKept) { for (Interceptor<? extends Message> i : interceptors) { - boolean outside = false; - if (i instanceof PhaseInterceptor) { - PhaseInterceptor<? extends Message> p = (PhaseInterceptor<? extends Message>) i; - for (String phaseName : phaseNames) { - if (p.getPhase().equals(phaseName)) { - outside = true; - break; - } - } - if (!outside) { - // To support the old API - if (needToBeKept == null) { - getLogger().info("removing the interceptor {}", p); - interceptors.remove(p); - } else if (!needToBeKept.contains(p.getClass().getName())) { - getLogger().info("removing the interceptor {}", p); - interceptors.remove(p); - } + tryRemove(interceptors, phaseNames, needToBeKept, i); + } + } + + private void tryRemove( + List<Interceptor<? extends Message>> interceptors, String[] phaseNames, Set<String> needToBeKept, + Interceptor<? extends Message> i) { + boolean outside = false; + if (i instanceof PhaseInterceptor) { + PhaseInterceptor<? extends Message> p = (PhaseInterceptor<? extends Message>) i; + for (String phaseName : phaseNames) { + if (p.getPhase().equals(phaseName)) { + outside = true; + break; } } + if (!outside) { + doRemove(interceptors, needToBeKept, p); + } + } + } + + private void doRemove( + List<Interceptor<? extends Message>> interceptors, Set<String> needToBeKept, + PhaseInterceptor<? extends Message> p) { + // To support the old API + if (needToBeKept == null) { + getLogger().info("removing the interceptor {}", p); + interceptors.remove(p); + } else if (!needToBeKept.contains(p.getClass().getName())) { + getLogger().info("removing the interceptor {}", p); + interceptors.remove(p); } } diff --git a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/interceptors/RawMessageContentRedirectInterceptor.java b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/interceptors/RawMessageContentRedirectInterceptor.java index 43215f25b05..98ebe67309c 100644 --- a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/interceptors/RawMessageContentRedirectInterceptor.java +++ b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/interceptors/RawMessageContentRedirectInterceptor.java @@ -41,38 +41,47 @@ public class RawMessageContentRedirectInterceptor extends AbstractPhaseIntercept // check the fault from the message Throwable ex = message.getContent(Throwable.class); if (ex != null) { - if (ex instanceof Fault) { - throw (Fault) ex; - } else { - throw new Fault(ex); - } + throwFault(ex); } List<?> params = message.getContent(List.class); if (null != params) { - InputStream is = (InputStream) params.get(0); - OutputStream os = message.getContent(OutputStream.class); - Writer writer = message.getContent(Writer.class); + final OutputStream os = message.getContent(OutputStream.class); + final Writer writer = message.getContent(Writer.class); if (os == null && writer == null) { //InOny return; } - try { - if (os == null && writer != null) { - IOUtils.copyAndCloseInput(new InputStreamReader(is), writer); + + final InputStream is = (InputStream) params.get(0); + tryIO(os, writer, is); + } + } + + private static void tryIO(OutputStream os, Writer writer, InputStream is) { + try { + if (os == null && writer != null) { + IOUtils.copyAndCloseInput(new InputStreamReader(is), writer); + } else { + if (is instanceof StreamCache) { + ((StreamCache) is).writeTo(os); } else { - if (is instanceof StreamCache) { - ((StreamCache) is).writeTo(os); - } else { - IOUtils.copy(is, os); - } + IOUtils.copy(is, os); } - } catch (Exception e) { - throw new Fault(e); - } finally { - IOHelper.close(is, "input stream", null); - // Should not close the output stream as the interceptor chain will close it } + } catch (Exception e) { + throw new Fault(e); + } finally { + IOHelper.close(is, "input stream", null); + // Should not close the output stream as the interceptor chain will close it + } + } + + private static void throwFault(Throwable ex) { + if (ex instanceof Fault) { + throw (Fault) ex; + } else { + throw new Fault(ex); } } } diff --git a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfComponent.java b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfComponent.java index db04fb573cf..0342e0c7afa 100644 --- a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfComponent.java +++ b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfComponent.java @@ -44,7 +44,7 @@ public class CxfComponent extends HeaderFilterStrategyComponent implements SSLCo @Metadata(label = "security", defaultValue = "false") private boolean useGlobalSslContextParameters; - private Map<String, BeanCacheEntry> beanCache = new HashMap<>(); + private final Map<String, BeanCacheEntry> beanCache = new HashMap<>(); public CxfComponent() { } @@ -86,8 +86,6 @@ public class CxfComponent extends HeaderFilterStrategyComponent implements SSLCo @Override protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { - CxfEndpoint result; - Object value = parameters.remove("setDefaultBus"); if (value != null) { LOG.warn("The option setDefaultBus is @deprecated, use name defaultBus instead"); @@ -100,36 +98,8 @@ public class CxfComponent extends HeaderFilterStrategyComponent implements SSLCo parameters.put("allowStreaming", Boolean.toString(allowStreaming)); } - if (remaining.startsWith(CxfConstants.SPRING_CONTEXT_ENDPOINT)) { - // Get the bean from the Spring context - String beanId = remaining.substring(CxfConstants.SPRING_CONTEXT_ENDPOINT.length()); - if (beanId.startsWith("//")) { - beanId = beanId.substring(2); - } + final CxfEndpoint result = createCxfEndpoint(remaining, parameters); - result = createCxfSpringEndpoint(beanId); - result.setBeanId(beanId); - if (beanCache.containsKey(beanId)) { - BeanCacheEntry entry = beanCache.get(beanId); - if (entry.cxfEndpoint == result - && !entry.parameters.equals(parameters)) { - /*different URI refer to the same CxfEndpoint Bean instance - but with different parameters. This can make stateful bean's - behavior uncertainty. This can be addressed by using proper - bean scope, such as "prototype" in Spring or "Session" in CDI - */ - throw new RuntimeException( - "Different URI refer to the same CxfEndpoint Bean instance" - + " with ID : " + beanId - + " but with different parameters. Please use the proper Bean scope "); - } - } else { - beanCache.put(beanId, new BeanCacheEntry(result, new HashMap<>(parameters))); - } - } else { - // endpoint URI does not specify a bean - result = createCxfEndpoint(remaining); - } result.setComponent(this); result.setCamelContext(getCamelContext()); setEndpointHeaderFilterStrategy(result); @@ -147,6 +117,47 @@ public class CxfComponent extends HeaderFilterStrategyComponent implements SSLCo return result; } + private CxfEndpoint createCxfEndpoint(String remaining, Map<String, Object> parameters) { + CxfEndpoint result; + if (remaining.startsWith(CxfConstants.SPRING_CONTEXT_ENDPOINT)) { + result = createSpringContextEndpoint(remaining, parameters); + } else { + // endpoint URI does not specify a bean + result = createCxfEndpoint(remaining); + } + return result; + } + + private CxfEndpoint createSpringContextEndpoint(String remaining, Map<String, Object> parameters) { + CxfEndpoint result; + // Get the bean from the Spring context + String beanId = remaining.substring(CxfConstants.SPRING_CONTEXT_ENDPOINT.length()); + if (beanId.startsWith("//")) { + beanId = beanId.substring(2); + } + + result = createCxfSpringEndpoint(beanId); + result.setBeanId(beanId); + if (beanCache.containsKey(beanId)) { + BeanCacheEntry entry = beanCache.get(beanId); + if (entry.cxfEndpoint == result + && !entry.parameters.equals(parameters)) { + /*different URI refer to the same CxfEndpoint Bean instance + but with different parameters. This can make stateful bean's + behavior uncertainty. This can be addressed by using proper + bean scope, such as "prototype" in Spring or "Session" in CDI + */ + throw new RuntimeException( + "Different URI refer to the same CxfEndpoint Bean instance" + + " with ID : " + beanId + + " but with different parameters. Please use the proper Bean scope "); + } + } else { + beanCache.put(beanId, new BeanCacheEntry(result, new HashMap<>(parameters))); + } + return result; + } + protected CxfEndpoint createCxfSpringEndpoint(String beanId) { return CamelContextHelper.mandatoryLookup(getCamelContext(), beanId, CxfEndpoint.class); } diff --git a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfConsumer.java b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfConsumer.java index e02943bc9e9..b805d4a09e0 100644 --- a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfConsumer.java +++ b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfConsumer.java @@ -332,51 +332,73 @@ public class CxfConsumer extends DefaultConsumer implements Suspendable { } private void checkFailure(org.apache.camel.Exchange camelExchange, Exchange cxfExchange) throws Fault { - Throwable t = camelExchange.getException(); - if (t == null) { - // SOAP faults can be stored as exceptions as message body (to be backwards compatible) - Object body = camelExchange.getMessage().getBody(); - if (body instanceof Throwable) { - t = (Throwable) body; - } - } + final Throwable t = extractThrowable(camelExchange); if (t != null) { cxfExchange.getInMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT); if (t instanceof Fault) { - cxfExchange.getInMessage().put(FaultMode.class, FaultMode.CHECKED_APPLICATION_FAULT); - throw (Fault) t; + handleFault(cxfExchange, (Fault) t); } else { // This is not a CXF Fault. Build the CXF Fault manually. - Fault fault = new Fault(t); - if (fault.getMessage() == null) { - // The Fault has no Message. This is the case if it has - // no message, for example was a NullPointerException. - fault.setMessage(t.getClass().getSimpleName()); - } - WebFault faultAnnotation = t.getClass().getAnnotation(WebFault.class); - Object faultInfo = null; - try { - Method method = t.getClass().getMethod("getFaultInfo"); - faultInfo = method.invoke(t, new Object[0]); - } catch (Exception e) { - // do nothing here - } - if (faultAnnotation != null && faultInfo == null) { - // t has a JAX-WS WebFault annotation, which describes - // in detail the Web Service Fault that should be thrown. Add the - // detail. - Element detail = fault.getOrCreateDetail(); - Element faultDetails = detail.getOwnerDocument() - .createElementNS(faultAnnotation.targetNamespace(), faultAnnotation.name()); - detail.appendChild(faultDetails); - } - - throw fault; + buildFaultFromThrowable(t); } } } + private static void buildFaultFromThrowable(Throwable t) { + Fault fault = new Fault(t); + if (fault.getMessage() == null) { + // The Fault has no Message. This is the case if it has + // no message, for example was a NullPointerException. + fault.setMessage(t.getClass().getSimpleName()); + } + WebFault faultAnnotation = t.getClass().getAnnotation(WebFault.class); + Object faultInfo = null; + try { + Method method = t.getClass().getMethod("getFaultInfo"); + faultInfo = method.invoke(t, new Object[0]); + } catch (Exception e) { + // do nothing here + } + if (faultAnnotation != null && faultInfo == null) { + // t has a JAX-WS WebFault annotation, which describes + // in detail the Web Service Fault that should be thrown. Add the + // detail. + handleFaultAnnotation(fault, faultAnnotation); + } + + throw fault; + } + + private static void handleFaultAnnotation(Fault fault, WebFault faultAnnotation) { + Element detail = fault.getOrCreateDetail(); + Element faultDetails = detail.getOwnerDocument() + .createElementNS(faultAnnotation.targetNamespace(), faultAnnotation.name()); + detail.appendChild(faultDetails); + } + + private static void handleFault(Exchange cxfExchange, Fault t) { + cxfExchange.getInMessage().put(FaultMode.class, FaultMode.CHECKED_APPLICATION_FAULT); + throw t; + } + + private static Throwable extractThrowable(org.apache.camel.Exchange camelExchange) { + Throwable t = camelExchange.getException(); + if (t == null) { + // SOAP faults can be stored as exceptions as message body (to be backwards compatible) + t = extractFromBody(camelExchange, t); + } + return t; + } + + private static Throwable extractFromBody(org.apache.camel.Exchange camelExchange, Throwable t) { + Object body = camelExchange.getMessage().getBody(); + if (body instanceof Throwable) { + t = (Throwable) body; + } + return t; + } + } } diff --git a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfEndpoint.java b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfEndpoint.java index 6c1f946d091..4824143f558 100644 --- a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfEndpoint.java +++ b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfEndpoint.java @@ -322,32 +322,13 @@ public class CxfEndpoint extends DefaultEndpoint implements AsyncEndpoint, Heade // apply feature here if (!CxfEndpointUtils.hasAnnotation(cls, WebServiceProvider.class)) { - if (getDataFormat() == DataFormat.PAYLOAD) { - sfb.getFeatures().add(new PayLoadDataFormatFeature(allowStreaming)); - } else if (getDataFormat().dealias() == DataFormat.CXF_MESSAGE) { - sfb.getFeatures().add(new CXFMessageDataFormatFeature()); - sfb.setDataBinding(new SourceDataBinding()); - } else if (getDataFormat().dealias() == DataFormat.RAW) { - RAWDataFormatFeature feature = new RAWDataFormatFeature(); - if (this.getExchangePattern().equals(ExchangePattern.InOnly)) { - //if DataFormat is RAW|MESSAGE, can't read message so can't - //determine it's oneway so need get the MEP from URI explicitly - feature.setOneway(true); - } - feature.addInIntercepters(getInInterceptors()); - feature.addOutInterceptors(getOutInterceptors()); - sfb.getFeatures().add(feature); - } + applyFeatures(sfb); } else { LOG.debug("Ignore DataFormat mode {} since SEI class is annotated with WebServiceProvider", getDataFormat()); } if (isLoggingFeatureEnabled()) { - LoggingFeature loggingFeature = new LoggingFeature(); - if (getLoggingSizeLimit() >= -1) { - loggingFeature.setLimit(getLoggingSizeLimit()); - } - sfb.getFeatures().add(loggingFeature); + enableLoggingFeature(sfb); } if (getDataFormat() == DataFormat.PAYLOAD) { @@ -361,33 +342,18 @@ public class CxfEndpoint extends DefaultEndpoint implements AsyncEndpoint, Heade // any optional properties if (getProperties() != null) { - if (sfb.getProperties() != null) { - // add to existing properties - sfb.getProperties().putAll(getProperties()); - } else { - sfb.setProperties(getProperties()); - } - LOG.debug("ServerFactoryBean: {} added properties: {}", sfb, getProperties()); + applyOptionalProperties(sfb); } if (this.isSkipPayloadMessagePartCheck()) { - if (sfb.getProperties() == null) { - sfb.setProperties(new HashMap<>()); - } - sfb.getProperties().put("soap.no.validate.parts", Boolean.TRUE); + applySkipPayloadMessagePartCheck(sfb); } if (this.isSkipFaultLogging()) { - if (sfb.getProperties() == null) { - sfb.setProperties(new HashMap<>()); - } - sfb.getProperties().put(FaultListener.class.getName(), new NullFaultListener()); + applySkipFaultLogging(sfb); } if (this.getSchemaValidationEnabled() != null) { - if (sfb.getProperties() == null) { - sfb.setProperties(new HashMap<>()); - } - sfb.getProperties().put(Message.SCHEMA_VALIDATION_ENABLED, schemaValidationEnabled); + applySchemaValidation(sfb); } sfb.setBus(getBus()); @@ -395,6 +361,76 @@ public class CxfEndpoint extends DefaultEndpoint implements AsyncEndpoint, Heade getNullSafeCxfConfigurer().configure(sfb); } + private static void applySkipPayloadMessagePartCheck(ServerFactoryBean sfb) { + if (sfb.getProperties() == null) { + sfb.setProperties(new HashMap<>()); + } + sfb.getProperties().put("soap.no.validate.parts", Boolean.TRUE); + } + + private void applySchemaValidation(ServerFactoryBean sfb) { + if (sfb.getProperties() == null) { + sfb.setProperties(new HashMap<>()); + } + sfb.getProperties().put(Message.SCHEMA_VALIDATION_ENABLED, schemaValidationEnabled); + } + + private static void applySkipFaultLogging(ServerFactoryBean sfb) { + if (sfb.getProperties() == null) { + sfb.setProperties(new HashMap<>()); + } + sfb.getProperties().put(FaultListener.class.getName(), new NullFaultListener()); + } + + private void applyOptionalProperties(ServerFactoryBean sfb) { + if (sfb.getProperties() != null) { + // add to existing properties + sfb.getProperties().putAll(getProperties()); + } else { + sfb.setProperties(getProperties()); + } + LOG.debug("ServerFactoryBean: {} added properties: {}", sfb, getProperties()); + } + + private void enableLoggingFeature(ServerFactoryBean sfb) { + LoggingFeature loggingFeature = new LoggingFeature(); + if (getLoggingSizeLimit() >= -1) { + loggingFeature.setLimit(getLoggingSizeLimit()); + } + sfb.getFeatures().add(loggingFeature); + } + + private void applyFeatures(ServerFactoryBean sfb) { + if (getDataFormat() == DataFormat.PAYLOAD) { + applyPayload(sfb); + } else if (getDataFormat().dealias() == DataFormat.CXF_MESSAGE) { + applyCXFMessage(sfb); + } else if (getDataFormat().dealias() == DataFormat.RAW) { + applyRaw(sfb); + } + } + + private void applyPayload(ServerFactoryBean sfb) { + sfb.getFeatures().add(new PayLoadDataFormatFeature(allowStreaming)); + } + + private static void applyCXFMessage(ServerFactoryBean sfb) { + sfb.getFeatures().add(new CXFMessageDataFormatFeature()); + sfb.setDataBinding(new SourceDataBinding()); + } + + private void applyRaw(ServerFactoryBean sfb) { + RAWDataFormatFeature feature = new RAWDataFormatFeature(); + if (this.getExchangePattern().equals(ExchangePattern.InOnly)) { + //if DataFormat is RAW|MESSAGE, can't read message so can't + //determine it's oneway so need get the MEP from URI explicitly + feature.setOneway(true); + } + feature.addInIntercepters(getInInterceptors()); + feature.addOutInterceptors(getOutInterceptors()); + sfb.getFeatures().add(feature); + } + /** * Create a client factory bean object. Notice that the serviceClass <b>must</b> be an interface. */ @@ -1236,50 +1272,54 @@ public class CxfEndpoint extends DefaultEndpoint implements AsyncEndpoint, Heade // as the setParameter will be called more than once when using the fail over feature if (DataFormat.PAYLOAD == message.get(DataFormat.class) && params[0] instanceof CxfPayload) { - CxfPayload<?> payload = (CxfPayload<?>) params[0]; - List<Source> elements = payload.getBodySources(); + setParametersViaPayload(params, message); + } else { + super.setParameters(params, message); + } - BindingOperationInfo boi = message.get(BindingOperationInfo.class); - MessageContentsList content = new MessageContentsList(); - int i = 0; + message.remove(DataFormat.class.getName()); + } + + private void setParametersViaPayload(Object[] params, Message message) { + CxfPayload<?> payload = (CxfPayload<?>) params[0]; + List<Source> elements = payload.getBodySources(); - for (MessagePartInfo partInfo : boi.getInput().getMessageParts()) { - if (elements.size() > i) { - if (isSkipPayloadMessagePartCheck()) { + BindingOperationInfo boi = message.get(BindingOperationInfo.class); + MessageContentsList content = new MessageContentsList(); + int i = 0; + + for (MessagePartInfo partInfo : boi.getInput().getMessageParts()) { + if (elements.size() > i) { + if (isSkipPayloadMessagePartCheck()) { + content.put(partInfo, elements.get(i++)); + } else { + String name = findName(elements, i); + if (partInfo.getConcreteName().getLocalPart().equals(name)) { content.put(partInfo, elements.get(i++)); - } else { - String name = findName(elements, i); - if (partInfo.getConcreteName().getLocalPart().equals(name)) { - content.put(partInfo, elements.get(i++)); - } } } } + } - if (elements != null && content.size() < elements.size()) { - throw new IllegalArgumentException( - "The PayLoad elements cannot fit with the message parts of the BindingOperation. Please check the BindingOperation and PayLoadMessage."); - } + if (elements != null && content.size() < elements.size()) { + throw new IllegalArgumentException( + "The PayLoad elements cannot fit with the message parts of the BindingOperation. Please check the BindingOperation and PayLoadMessage."); + } - message.setContent(List.class, content); - // merge header list from request context with header list from CXF payload - List<Object> headerListOfRequestContxt = (List<Object>) message.get(Header.HEADER_LIST); - List<Object> headerListOfPayload = CastUtils.cast(payload.getHeaders()); - if (headerListOfRequestContxt == headerListOfPayload) { - // == is correct, we want to compare the object instances - // nothing to do, this can happen when the CXF payload is already created in the from-cxf-endpoint and then forwarded to a to-cxf-endpoint + message.setContent(List.class, content); + // merge header list from request context with header list from CXF payload + List<Object> headerListOfRequestContxt = (List<Object>) message.get(Header.HEADER_LIST); + List<Object> headerListOfPayload = CastUtils.cast(payload.getHeaders()); + if (headerListOfRequestContxt == headerListOfPayload) { + // == is correct, we want to compare the object instances + // nothing to do, this can happen when the CXF payload is already created in the from-cxf-endpoint and then forwarded to a to-cxf-endpoint + } else { + if (headerListOfRequestContxt == null) { + message.put(Header.HEADER_LIST, payload.getHeaders()); } else { - if (headerListOfRequestContxt == null) { - message.put(Header.HEADER_LIST, payload.getHeaders()); - } else { - headerListOfRequestContxt.addAll(headerListOfPayload); - } + headerListOfRequestContxt.addAll(headerListOfPayload); } - } else { - super.setParameters(params, message); } - - message.remove(DataFormat.class.getName()); } private String findName(List<Source> sources, int i) { diff --git a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfProducer.java b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfProducer.java index fb8801cd612..ca713e0ebe9 100644 --- a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfProducer.java +++ b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/CxfProducer.java @@ -271,6 +271,26 @@ public class CxfProducer extends DefaultAsyncProducer { } private void checkParameterSize(CxfEndpoint endpoint, Exchange exchange, Object[] parameters) { + final BindingOperationInfo boi = lookupBindingOperationInfo(endpoint, exchange); + final int expectMessagePartsSize = tryGetExpectMessagePartsSize(parameters, boi); + + if (parameters.length > expectMessagePartsSize) { + // need to check the holder parameters + final int holdersSize = computeHoldersSize(parameters); + // need to check the soap header information + final int soapHeadersSize = computeSoapHeadersSize(boi); + + if (isValidSize(parameters, holdersSize, expectMessagePartsSize, soapHeadersSize)) { + throw new IllegalArgumentException( + "Get the wrong parameter size to invoke the out service, Expect size " + + (expectMessagePartsSize + holdersSize + soapHeadersSize) + + ", Parameter size " + parameters.length + + ". Please check if the message body matches the CXFEndpoint POJO Dataformat request."); + } + } + } + + private BindingOperationInfo lookupBindingOperationInfo(CxfEndpoint endpoint, Exchange exchange) { BindingOperationInfo boi = getBindingOperationInfo(exchange); if (boi == null) { throw new RuntimeCamelException("Can't find the binding operation information from camel exchange"); @@ -280,6 +300,36 @@ public class CxfProducer extends DefaultAsyncProducer { boi = boi.getUnwrappedOperation(); } } + return boi; + } + + private static int computeSoapHeadersSize(BindingOperationInfo boi) { + int soapHeadersSize = 0; + BindingMessageInfo bmi = boi.getInput(); + if (bmi != null) { + List<SoapHeaderInfo> headers = bmi.getExtensors(SoapHeaderInfo.class); + if (headers != null) { + soapHeadersSize = headers.size(); + } + } + return soapHeadersSize; + } + + private static boolean isValidSize(Object[] parameters, int holdersSize, int expectMessagePartsSize, int soapHeadersSize) { + return holdersSize + expectMessagePartsSize + soapHeadersSize < parameters.length; + } + + private static int computeHoldersSize(Object[] parameters) { + int holdersSize = 0; + for (Object parameter : parameters) { + if (parameter instanceof Holder) { + holdersSize++; + } + } + return holdersSize; + } + + private static int tryGetExpectMessagePartsSize(Object[] parameters, BindingOperationInfo boi) { int expectMessagePartsSize = boi.getInput().getMessageParts().size(); if (parameters.length < expectMessagePartsSize) { @@ -288,33 +338,7 @@ public class CxfProducer extends DefaultAsyncProducer { + expectMessagePartsSize + ", Parameter size " + parameters.length + ". Please check if the message body matches the CXFEndpoint POJO Dataformat request."); } - - if (parameters.length > expectMessagePartsSize) { - // need to check the holder parameters - int holdersSize = 0; - for (Object parameter : parameters) { - if (parameter instanceof Holder) { - holdersSize++; - } - } - // need to check the soap header information - int soapHeadersSize = 0; - BindingMessageInfo bmi = boi.getInput(); - if (bmi != null) { - List<SoapHeaderInfo> headers = bmi.getExtensors(SoapHeaderInfo.class); - if (headers != null) { - soapHeadersSize = headers.size(); - } - } - - if (holdersSize + expectMessagePartsSize + soapHeadersSize < parameters.length) { - throw new IllegalArgumentException( - "Get the wrong parameter size to invoke the out service, Expect size " - + (expectMessagePartsSize + holdersSize + soapHeadersSize) - + ", Parameter size " + parameters.length - + ". Please check if the message body matches the CXFEndpoint POJO Dataformat request."); - } - } + return expectMessagePartsSize; } /** diff --git a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/DefaultCxfBinding.java b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/DefaultCxfBinding.java index f9d35445251..326cd86d1e6 100644 --- a/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/DefaultCxfBinding.java +++ b/components/camel-cxf/camel-cxf-soap/src/main/java/org/apache/camel/component/cxf/jaxws/DefaultCxfBinding.java @@ -136,6 +136,10 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware } // propagate attachments + propagateAttachments(camelExchange, requestContext); + } + + private static void propagateAttachments(Exchange camelExchange, Map<String, Object> requestContext) { Set<Attachment> attachments = null; boolean isXop = Boolean.valueOf(camelExchange.getProperty(Message.MTOM_ENABLED, String.class)); DataFormat dataFormat = camelExchange.getProperty(CxfConstants.DATA_FORMAT_PROPERTY, @@ -144,20 +148,7 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware // already has the attachment information if (!DataFormat.CXF_MESSAGE.equals(dataFormat)) { if (camelExchange.getIn(AttachmentMessage.class).hasAttachments()) { - for (Map.Entry<String, org.apache.camel.attachment.Attachment> entry : camelExchange - .getIn(AttachmentMessage.class).getAttachmentObjects().entrySet()) { - if (attachments == null) { - attachments = new HashSet<>(); - } - AttachmentImpl attachment = new AttachmentImpl(entry.getKey()); - org.apache.camel.attachment.Attachment camelAttachment = entry.getValue(); - attachment.setDataHandler(camelAttachment.getDataHandler()); - for (String name : camelAttachment.getHeaderNames()) { - attachment.setHeader(name, camelAttachment.getHeader(name)); - } - attachment.setXOP(isXop); - attachments.add(attachment); - } + attachments = handleAttachments(camelExchange, attachments, isXop); } } @@ -166,6 +157,24 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware } } + private static Set<Attachment> handleAttachments(Exchange camelExchange, Set<Attachment> attachments, boolean isXop) { + for (Map.Entry<String, org.apache.camel.attachment.Attachment> entry : camelExchange + .getIn(AttachmentMessage.class).getAttachmentObjects().entrySet()) { + if (attachments == null) { + attachments = new HashSet<>(); + } + AttachmentImpl attachment = new AttachmentImpl(entry.getKey()); + org.apache.camel.attachment.Attachment camelAttachment = entry.getValue(); + attachment.setDataHandler(camelAttachment.getDataHandler()); + for (String name : camelAttachment.getHeaderNames()) { + attachment.setHeader(name, camelAttachment.getHeader(name)); + } + attachment.setXOP(isXop); + attachments.add(attachment); + } + return attachments; + } + /** * This method is called by {@link CxfProducer#process(Exchange)}. It propagates information from CXF Exchange to * Camel Exchange. The CXF Exchange contains a request from a CXF server. @@ -270,13 +279,7 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware BindingOperationInfo boi = camelExchange.getProperty(BindingOperationInfo.class.getName(), BindingOperationInfo.class); if (boi != null) { - Service service = cxfExchange.get(Service.class); - if (service != null) { - MethodDispatcher md = (MethodDispatcher) service.get(MethodDispatcher.class.getName()); - if (md != null) { - method = md.getMethod(boi); - } - } + method = extractMethod(cxfExchange, boi); if (boi.getOperationInfo().isOneWay()) { mep = ExchangePattern.InOnly; @@ -287,22 +290,9 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware // set operation name in header if (operationName != null) { - camelExchange.getIn().setHeader(CxfConstants.OPERATION_NAMESPACE, - boi.getName().getNamespaceURI()); - camelExchange.getIn().setHeader(CxfConstants.OPERATION_NAME, - boi.getName().getLocalPart()); - if (LOG.isTraceEnabled()) { - LOG.trace("Set IN header: {}={}", - CxfConstants.OPERATION_NAMESPACE, boi.getName().getNamespaceURI()); - LOG.trace("Set IN header: {}={}", - CxfConstants.OPERATION_NAME, boi.getName().getLocalPart()); - } + setOperationNameDirectly(camelExchange, boi); } else if (method != null) { - camelExchange.getIn().setHeader(CxfConstants.OPERATION_NAME, method.getName()); - if (LOG.isTraceEnabled()) { - LOG.trace("Set IN header: {}={}", - CxfConstants.OPERATION_NAME, method.getName()); - } + setOperationNameViaMethod(camelExchange, method); } // set message exchange pattern @@ -314,19 +304,7 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware propagateHeadersFromCxfToCamel(cxfMessage, camelExchange.getIn(), camelExchange); // propagate the security subject from CXF security context - SecurityContext securityContext = cxfMessage.get(SecurityContext.class); - if (securityContext instanceof LoginSecurityContext - && ((LoginSecurityContext) securityContext).getSubject() != null) { - camelExchange.getIn().getHeaders().put(CxfConstants.AUTHENTICATION, - ((LoginSecurityContext) securityContext).getSubject()); - } else if (securityContext != null) { - Principal user = securityContext.getUserPrincipal(); - if (user != null) { - Subject subject = new Subject(); - subject.getPrincipals().add(user); - camelExchange.getIn().getHeaders().put(CxfConstants.AUTHENTICATION, subject); - } - } + propagateSecuritySubject(camelExchange, cxfMessage); // Propagating properties from CXF Exchange to Camel Exchange has an // side effect of copying reply side stuff when the producer is retried. @@ -334,33 +312,97 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware //camelExchange.getProperties().putAll(cxfExchange); // propagate request context - Object value = cxfMessage.get(CxfConstants.REQUEST_CONTEXT); - if (value != null && !headerFilterStrategy.applyFilterToExternalHeaders( - CxfConstants.REQUEST_CONTEXT, value, camelExchange)) { - camelExchange.getIn().setHeader(CxfConstants.REQUEST_CONTEXT, value); - LOG.trace("Populate context from CXF message {} value={}", CxfConstants.REQUEST_CONTEXT, value); - } + propagateRequestContext(camelExchange, cxfMessage); // setup the charset from content-type header setCharsetWithContentType(camelExchange); // set body + setBody(camelExchange, cxfMessage); + + // propagate attachments if the data format is not POJO + if (cxfMessage.getAttachments() != null + && !camelExchange.getProperty(CxfConstants.DATA_FORMAT_PROPERTY, DataFormat.class).equals(DataFormat.POJO)) { + propagateAttachments(camelExchange, cxfMessage); + } + addAttachmentFileCloseUoW(camelExchange, cxfExchange); + } + + private static Method extractMethod(org.apache.cxf.message.Exchange cxfExchange, BindingOperationInfo boi) { + Service service = cxfExchange.get(Service.class); + if (service != null) { + MethodDispatcher md = (MethodDispatcher) service.get(MethodDispatcher.class.getName()); + if (md != null) { + return md.getMethod(boi); + } + } + return null; + } + + private void propagateAttachments(Exchange camelExchange, Message cxfMessage) { + for (Attachment attachment : cxfMessage.getAttachments()) { + camelExchange.getIn(AttachmentMessage.class).addAttachmentObject(attachment.getId(), + createCamelAttachment(attachment)); + } + } + + private static void setBody(Exchange camelExchange, Message cxfMessage) { String encoding = (String) camelExchange.getProperty(ExchangePropertyKey.CHARSET_NAME); Object body = DefaultCxfBinding.getContentFromCxf(cxfMessage, camelExchange.getProperty(CxfConstants.DATA_FORMAT_PROPERTY, DataFormat.class), encoding); if (body != null) { camelExchange.getIn().setBody(body); } + } - // propagate attachments if the data format is not POJO - if (cxfMessage.getAttachments() != null - && !camelExchange.getProperty(CxfConstants.DATA_FORMAT_PROPERTY, DataFormat.class).equals(DataFormat.POJO)) { - for (Attachment attachment : cxfMessage.getAttachments()) { - camelExchange.getIn(AttachmentMessage.class).addAttachmentObject(attachment.getId(), - createCamelAttachment(attachment)); + private void propagateRequestContext(Exchange camelExchange, Message cxfMessage) { + Object value = cxfMessage.get(CxfConstants.REQUEST_CONTEXT); + if (value != null && !headerFilterStrategy.applyFilterToExternalHeaders( + CxfConstants.REQUEST_CONTEXT, value, camelExchange)) { + camelExchange.getIn().setHeader(CxfConstants.REQUEST_CONTEXT, value); + LOG.trace("Populate context from CXF message {} value={}", CxfConstants.REQUEST_CONTEXT, value); + } + } + + private static void propagateSecuritySubject(Exchange camelExchange, Message cxfMessage) { + SecurityContext securityContext = cxfMessage.get(SecurityContext.class); + if (securityContext instanceof LoginSecurityContext + && ((LoginSecurityContext) securityContext).getSubject() != null) { + camelExchange.getIn().getHeaders().put(CxfConstants.AUTHENTICATION, + ((LoginSecurityContext) securityContext).getSubject()); + } else if (securityContext != null) { + Principal user = securityContext.getUserPrincipal(); + if (user != null) { + Subject subject = new Subject(); + subject.getPrincipals().add(user); + camelExchange.getIn().getHeaders().put(CxfConstants.AUTHENTICATION, subject); } } - addAttachmentFileCloseUoW(camelExchange, cxfExchange); + } + + private static void setOperationNameViaMethod(Exchange camelExchange, Method method) { + camelExchange.getIn().setHeader(CxfConstants.OPERATION_NAME, method.getName()); + if (LOG.isTraceEnabled()) { + LOG.trace("Set IN header: {}={}", + CxfConstants.OPERATION_NAME, method.getName()); + } + } + + private static void setOperationNameDirectly(Exchange camelExchange, BindingOperationInfo boi) { + camelExchange.getIn().setHeader(CxfConstants.OPERATION_NAMESPACE, + boi.getName().getNamespaceURI()); + camelExchange.getIn().setHeader(CxfConstants.OPERATION_NAME, + boi.getName().getLocalPart()); + if (LOG.isTraceEnabled()) { + logOperationHeaders(boi); + } + } + + private static void logOperationHeaders(BindingOperationInfo boi) { + LOG.trace("Set IN header: {}={}", + CxfConstants.OPERATION_NAMESPACE, boi.getName().getNamespaceURI()); + LOG.trace("Set IN header: {}={}", + CxfConstants.OPERATION_NAME, boi.getName().getLocalPart()); } /** @@ -378,19 +420,7 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware // create response context Map<String, Object> responseContext = new HashMap<>(); - org.apache.camel.Message response; - if (camelExchange.getPattern().isOutCapable()) { - if (camelExchange.getMessage() != null) { - response = camelExchange.getMessage(); - LOG.trace("Get the response from the out message"); - } else { // Take the in message as a fall back - response = camelExchange.getIn(); - LOG.trace("Get the response from the in message as a fallback"); - } - } else { - response = camelExchange.getIn(); - LOG.trace("Get the response from the in message"); - } + final org.apache.camel.Message response = extractResponseMessage(camelExchange); // propagate response context Map<String, Object> camelHeaders = response.getHeaders(); @@ -419,19 +449,7 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware // create response context Map<String, Object> responseContext = new HashMap<>(); - org.apache.camel.Message response; - if (camelExchange.getPattern().isOutCapable()) { - if (camelExchange.getMessage() != null) { - response = camelExchange.getMessage(); - LOG.trace("Get the response from the out message"); - } else { // Take the in message as a fall back - response = camelExchange.getIn(); - LOG.trace("Get the response from the in message as a fallback"); - } - } else { - response = camelExchange.getIn(); - LOG.trace("Get the response from the in message"); - } + final org.apache.camel.Message response = extractResponseMessage(camelExchange); // propagate response context Map<String, Object> camelHeaders = response.getHeaders(); @@ -467,30 +485,7 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware Object outBody = DefaultCxfBinding.getBodyFromCamel(response, dataFormat); if (outBody != null) { - if (dataFormat == DataFormat.PAYLOAD) { - CxfPayload<?> payload = (CxfPayload<?>) outBody; - outMessage.setContent(List.class, getResponsePayloadList(cxfExchange, payload.getBodySources())); - outMessage.put(Header.HEADER_LIST, payload.getHeaders()); - } else { - if (responseContext.get(Header.HEADER_LIST) != null) { - outMessage.put(Header.HEADER_LIST, responseContext.get(Header.HEADER_LIST)); - } - - MessageContentsList resList = null; - // Create a new MessageContentsList to avoid OOM from the HolderOutInterceptor - if (outBody instanceof List) { - resList = new MessageContentsList((List<?>) outBody); - } else if (outBody.getClass().isArray()) { - resList = new MessageContentsList((Object[]) outBody); - } else { - resList = new MessageContentsList(outBody); - } - - if (resList != null) { - outMessage.setContent(List.class, resList); - LOG.trace("Set Out CXF message content = {}", resList); - } - } + populateOutBody(cxfExchange, dataFormat, outBody, outMessage, responseContext); } else if (!cxfExchange.isOneWay() && cxfExchange.getInMessage() != null && PropertyUtils @@ -501,6 +496,16 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware } // propagate attachments + propagateOutAttachments(camelExchange, outMessage); + + BindingOperationInfo boi = cxfExchange.get(BindingOperationInfo.class); + if (boi != null) { + cxfExchange.put(BindingMessageInfo.class, boi.getOutput()); + } + + } + + private static void propagateOutAttachments(Exchange camelExchange, Message outMessage) { Set<Attachment> attachments = null; boolean isXop = Boolean.valueOf(camelExchange.getProperty(Message.MTOM_ENABLED, String.class)); if (camelExchange.getMessage() != null && camelExchange.getMessage(AttachmentMessage.class).hasAttachments()) { @@ -523,12 +528,52 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware if (attachments != null) { outMessage.setAttachments(attachments); } + } - BindingOperationInfo boi = cxfExchange.get(BindingOperationInfo.class); - if (boi != null) { - cxfExchange.put(BindingMessageInfo.class, boi.getOutput()); + private void populateOutBody( + org.apache.cxf.message.Exchange cxfExchange, DataFormat dataFormat, Object outBody, Message outMessage, + Map<String, Object> responseContext) { + if (dataFormat == DataFormat.PAYLOAD) { + CxfPayload<?> payload = (CxfPayload<?>) outBody; + outMessage.setContent(List.class, getResponsePayloadList(cxfExchange, payload.getBodySources())); + outMessage.put(Header.HEADER_LIST, payload.getHeaders()); + } else { + if (responseContext.get(Header.HEADER_LIST) != null) { + outMessage.put(Header.HEADER_LIST, responseContext.get(Header.HEADER_LIST)); + } + + MessageContentsList resList = null; + // Create a new MessageContentsList to avoid OOM from the HolderOutInterceptor + if (outBody instanceof List) { + resList = new MessageContentsList((List<?>) outBody); + } else if (outBody.getClass().isArray()) { + resList = new MessageContentsList((Object[]) outBody); + } else { + resList = new MessageContentsList(outBody); + } + + if (resList != null) { + outMessage.setContent(List.class, resList); + LOG.trace("Set Out CXF message content = {}", resList); + } } + } + private static org.apache.camel.Message extractResponseMessage(Exchange camelExchange) { + org.apache.camel.Message response; + if (camelExchange.getPattern().isOutCapable()) { + if (camelExchange.getMessage() != null) { + response = camelExchange.getMessage(); + LOG.trace("Get the response from the out message"); + } else { // Take the in message as a fall back + response = camelExchange.getIn(); + LOG.trace("Get the response from the in message as a fallback"); + } + } else { + response = camelExchange.getIn(); + LOG.trace("Get the response from the in message"); + } + return response; } // HeaderFilterStrategyAware Methods @@ -649,81 +694,18 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware CxfHeaderHelper.copyHttpHeadersFromCxfToCamel(headerFilterStrategy, cxfMessage, camelMessage, exchange); if (cxfHeaders != null) { - for (Map.Entry<String, List<String>> entry : cxfHeaders.entrySet()) { - if (!headerFilterStrategy.applyFilterToExternalHeaders(entry.getKey(), - entry.getValue(), exchange)) { - // We need to filter the content type with multi-part, - // as the multi-part stream is already consumed by AttachmentInInterceptor, - // it will cause some trouble when route this message to another CXF endpoint. - - if ("Content-Type".compareToIgnoreCase(entry.getKey()) == 0 - && entry.getValue().get(0) != null - && entry.getValue().get(0).startsWith("multipart/related")) { - // We need to keep the Content-Type if the data format is RAW message - DataFormat dataFormat = exchange.getProperty(CxfConstants.DATA_FORMAT_PROPERTY, DataFormat.class); - if (dataFormat.equals(DataFormat.RAW)) { - camelHeaders.put(entry.getKey(), getContentTypeString(entry.getValue())); - } else { - String contentType = replaceMultiPartContentType(entry.getValue().get(0)); - LOG.trace("Find the multi-part Conent-Type, and replace it with {}", contentType); - camelHeaders.put(entry.getKey(), contentType); - } - } else if (SoapBindingConstants.SOAP_ACTION.compareToIgnoreCase(entry.getKey()) == 0 - && entry.getValue().get(0) != null) { - String soapAction = entry.getValue().get(0); - // SOAPAction header may contain quoted value. Remove the quotes here. - soapAction = StringHelper.removeLeadingAndEndingQuotes(soapAction); - camelHeaders.put(SoapBindingConstants.SOAP_ACTION, soapAction); - } else if (entry.getKey().startsWith(":")) { - /* Ignore HTTP/2 pseudo headers such as :status */ - continue; - } else { - LOG.trace("Populate header from CXF header={} value={}", - entry.getKey(), entry.getValue()); - List<String> values = entry.getValue(); - Object evalue; - if (values.size() > 1) { - final boolean headersMerged - = exchange.getProperty(CxfConstants.CAMEL_CXF_PROTOCOL_HEADERS_MERGED, Boolean.FALSE, - Boolean.class); - if (headersMerged) { - StringBuilder sb = new StringBuilder(); - for (Iterator<String> it = values.iterator(); it.hasNext();) { - sb.append(it.next()); - if (it.hasNext()) { - sb.append(',').append(' '); - } - } - evalue = sb.toString(); - } else { - evalue = values; - } - } else if (values.size() == 1) { - evalue = values.get(0); - } else { - evalue = null; - } - if (evalue != null) { - camelHeaders.put(entry.getKey(), evalue); - } - } - } - } + propagateCXFHeaders(exchange, cxfHeaders, camelHeaders); } // propagate SOAP/protocol header list - String key = Header.HEADER_LIST; - Object value = cxfMessage.get(key); - if (value != null) { - if (!headerFilterStrategy.applyFilterToExternalHeaders(key, value, exchange)) { - camelHeaders.put(key, value); - LOG.trace("Populate header from CXF header={} value={}", key, value); - } else { - ((List<?>) value).clear(); - } - } + propagateSOAPProtocolHeaderList(cxfMessage, exchange, camelHeaders); // propagate the SOAPAction header + propagateSOAPAction(cxfMessage, exchange, camelHeaders); + + } + + private void propagateSOAPAction(Message cxfMessage, Exchange exchange, Map<String, Object> camelHeaders) { String soapAction = (String) camelHeaders.get(SoapBindingConstants.SOAP_ACTION); // Remove SOAPAction from the protocol header, as it will not be overrided if (ObjectHelper.isEmpty(soapAction) || "\"\"".equals(soapAction)) { @@ -736,7 +718,97 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware LOG.trace("Populate header from CXF header={} value={}", SoapBindingConstants.SOAP_ACTION, soapAction); } } + } + private void propagateSOAPProtocolHeaderList(Message cxfMessage, Exchange exchange, Map<String, Object> camelHeaders) { + String key = Header.HEADER_LIST; + Object value = cxfMessage.get(key); + if (value != null) { + if (!headerFilterStrategy.applyFilterToExternalHeaders(key, value, exchange)) { + camelHeaders.put(key, value); + LOG.trace("Populate header from CXF header={} value={}", key, value); + } else { + ((List<?>) value).clear(); + } + } + } + + private void propagateCXFHeaders( + Exchange exchange, Map<String, List<String>> cxfHeaders, Map<String, Object> camelHeaders) { + for (Map.Entry<String, List<String>> entry : cxfHeaders.entrySet()) { + if (!headerFilterStrategy.applyFilterToExternalHeaders(entry.getKey(), + entry.getValue(), exchange)) { + // We need to filter the content type with multi-part, + // as the multi-part stream is already consumed by AttachmentInInterceptor, + // it will cause some trouble when route this message to another CXF endpoint. + + if ("Content-Type".compareToIgnoreCase(entry.getKey()) == 0 + && entry.getValue().get(0) != null + && entry.getValue().get(0).startsWith("multipart/related")) { + propagateContentType(exchange, entry, camelHeaders); + } else if (SoapBindingConstants.SOAP_ACTION.compareToIgnoreCase(entry.getKey()) == 0 + && entry.getValue().get(0) != null) { + propagateSoapAction(entry, camelHeaders); + } else if (entry.getKey().startsWith(":")) { + /* Ignore HTTP/2 pseudo headers such as :status */ + continue; + } else { + populateFromCXFHeaders(exchange, entry, camelHeaders); + } + } + } + } + + private static void populateFromCXFHeaders( + Exchange exchange, Map.Entry<String, List<String>> entry, Map<String, Object> camelHeaders) { + LOG.trace("Populate header from CXF header={} value={}", + entry.getKey(), entry.getValue()); + List<String> values = entry.getValue(); + Object evalue; + if (values.size() > 1) { + final boolean headersMerged + = exchange.getProperty(CxfConstants.CAMEL_CXF_PROTOCOL_HEADERS_MERGED, Boolean.FALSE, + Boolean.class); + if (headersMerged) { + StringBuilder sb = new StringBuilder(); + for (Iterator<String> it = values.iterator(); it.hasNext();) { + sb.append(it.next()); + if (it.hasNext()) { + sb.append(',').append(' '); + } + } + evalue = sb.toString(); + } else { + evalue = values; + } + } else if (values.size() == 1) { + evalue = values.get(0); + } else { + evalue = null; + } + if (evalue != null) { + camelHeaders.put(entry.getKey(), evalue); + } + } + + private static void propagateSoapAction(Map.Entry<String, List<String>> entry, Map<String, Object> camelHeaders) { + String soapAction = entry.getValue().get(0); + // SOAPAction header may contain quoted value. Remove the quotes here. + soapAction = StringHelper.removeLeadingAndEndingQuotes(soapAction); + camelHeaders.put(SoapBindingConstants.SOAP_ACTION, soapAction); + } + + private void propagateContentType( + Exchange exchange, Map.Entry<String, List<String>> entry, Map<String, Object> camelHeaders) { + // We need to keep the Content-Type if the data format is RAW message + DataFormat dataFormat = exchange.getProperty(CxfConstants.DATA_FORMAT_PROPERTY, DataFormat.class); + if (dataFormat.equals(DataFormat.RAW)) { + camelHeaders.put(entry.getKey(), getContentTypeString(entry.getValue())); + } else { + String contentType = replaceMultiPartContentType(entry.getValue().get(0)); + LOG.trace("Find the multi-part Conent-Type, and replace it with {}", contentType); + camelHeaders.put(entry.getKey(), contentType); + } } // replace the multi-part content-type @@ -872,48 +944,23 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware Set<Class<?>> contentFormats = message.getContentFormats(); Object answer = null; if (contentFormats != null) { - if (LOG.isTraceEnabled()) { - for (Class<?> contentFormat : contentFormats) { - LOG.trace("Content format={} value={}", - contentFormat, message.getContent(contentFormat)); - } + logContentFormats(message, contentFormats); } if (dataFormat == DataFormat.POJO) { - List<?> pojoMessageList = message.getContent(List.class); - if (pojoMessageList != null && !pojoMessageList.isEmpty()) { - answer = pojoMessageList; - } - if (answer == null) { - answer = message.getContent(Object.class); - if (answer != null) { - answer = new MessageContentsList(answer); - } - } + answer = getContentFromCXFViaPojo(message, answer); } else if (dataFormat == DataFormat.PAYLOAD) { - List<SoapHeader> headers = CastUtils.cast((List<?>) message.get(Header.HEADER_LIST)); - Map<String, String> nsMap = new HashMap<>(); - answer = new CxfPayload<>(headers, getPayloadBodyElements(message, nsMap), nsMap); + answer = getContentFromCXFViaPayload(message); } else if (dataFormat.dealias() == DataFormat.RAW) { - answer = message.getContent(InputStream.class); - if (answer == null) { - answer = message.getContent(Reader.class); - if (answer != null) { - if (encoding == null) { - encoding = "UTF-8"; - } - LOG.trace("file encoding is = {}", encoding); - answer = new ReaderInputStream((Reader) answer, Charset.forName(encoding)); - } - } + answer = getContentFromCXFViaRAW(message, encoding); } else if (dataFormat.dealias() == DataFormat.CXF_MESSAGE && message.getContent(List.class) != null) { // CAMEL-6404 added check point of message content // The message content of list could be null if there is a fault message is received - answer = message.getContent(List.class).get(0); + answer = getContentFromCXFViaList(message); } LOG.trace("Extracted body from CXF message = {}", answer); @@ -921,6 +968,57 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware return answer; } + private static Object getContentFromCXFViaList(Message message) { + Object answer; + answer = message.getContent(List.class).get(0); + return answer; + } + + private static Object getContentFromCXFViaRAW(Message message, String encoding) { + Object answer; + answer = message.getContent(InputStream.class); + if (answer == null) { + answer = message.getContent(Reader.class); + if (answer != null) { + if (encoding == null) { + encoding = "UTF-8"; + } + LOG.trace("file encoding is = {}", encoding); + answer = new ReaderInputStream((Reader) answer, Charset.forName(encoding)); + } + } + return answer; + } + + private static Object getContentFromCXFViaPayload(Message message) { + Object answer; + List<SoapHeader> headers = CastUtils.cast((List<?>) message.get(Header.HEADER_LIST)); + Map<String, String> nsMap = new HashMap<>(); + answer = new CxfPayload<>(headers, getPayloadBodyElements(message, nsMap), nsMap); + return answer; + } + + private static Object getContentFromCXFViaPojo(Message message, Object answer) { + List<?> pojoMessageList = message.getContent(List.class); + if (pojoMessageList != null && !pojoMessageList.isEmpty()) { + answer = pojoMessageList; + } + if (answer == null) { + answer = message.getContent(Object.class); + if (answer != null) { + answer = new MessageContentsList(answer); + } + } + return answer; + } + + private static void logContentFormats(Message message, Set<Class<?>> contentFormats) { + for (Class<?> contentFormat : contentFormats) { + LOG.trace("Content format={} value={}", + contentFormat, message.getContent(contentFormat)); + } + } + protected static void addNamespace(Element element, Map<String, String> nsMap) { for (Map.Entry<String, String> ns : nsMap.entrySet()) { // We should not override the namespace setting of the element @@ -968,22 +1066,9 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware org.apache.cxf.message.Exchange exchange = message.getExchange(); BindingOperationInfo boi = exchange.getBindingOperationInfo(); - OperationInfo op = boi.getOperationInfo(); - - if (boi.isUnwrapped()) { - op = boi.getWrappedOperation().getOperationInfo(); - } + final OperationInfo op = getOperationInfo(boi); - List<MessagePartInfo> partInfos = null; - boolean client = Boolean.TRUE.equals(message.get(Message.REQUESTOR_ROLE)); - if (client) { - // it is a response - partInfos = op.getOutput().getMessageParts(); - - } else { - // it is a request - partInfos = op.getInput().getMessageParts(); - } + final List<MessagePartInfo> partInfos = getMessagePartInfos(message, op); List<Source> answer = new ArrayList<>(); @@ -1028,6 +1113,29 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware return answer; } + private static OperationInfo getOperationInfo(BindingOperationInfo boi) { + OperationInfo op = boi.getOperationInfo(); + + if (boi.isUnwrapped()) { + op = boi.getWrappedOperation().getOperationInfo(); + } + return op; + } + + private static List<MessagePartInfo> getMessagePartInfos(Message message, OperationInfo op) { + List<MessagePartInfo> partInfos = null; + boolean client = Boolean.TRUE.equals(message.get(Message.REQUESTOR_ROLE)); + if (client) { + // it is a response + partInfos = op.getOutput().getMessageParts(); + + } else { + // it is a request + partInfos = op.getInput().getMessageParts(); + } + return partInfos; + } + private static String getXMLString(Element el) { try { return StaxUtils.toString(el); diff --git a/components/camel-cxf/camel-cxf-soap/src/test/java/org/apache/camel/component/cxf/jaxws/CxfConsumerStreamCacheTest.java b/components/camel-cxf/camel-cxf-soap/src/test/java/org/apache/camel/component/cxf/jaxws/CxfConsumerStreamCacheTest.java index a13988a03cb..df353f55efd 100644 --- a/components/camel-cxf/camel-cxf-soap/src/test/java/org/apache/camel/component/cxf/jaxws/CxfConsumerStreamCacheTest.java +++ b/components/camel-cxf/camel-cxf-soap/src/test/java/org/apache/camel/component/cxf/jaxws/CxfConsumerStreamCacheTest.java @@ -16,6 +16,8 @@ */ package org.apache.camel.component.cxf.jaxws; +import java.nio.charset.StandardCharsets; + import org.w3c.dom.Node; import org.apache.camel.Exchange; @@ -68,7 +70,7 @@ public class CxfConsumerStreamCacheTest extends CamelTestSupport { Node node = in.getBody(Node.class); assertNotNull(node); CachedOutputStream cos = new CachedOutputStream(exchange); - cos.write(RESPONSE.getBytes("UTF-8")); + cos.write(RESPONSE.getBytes(StandardCharsets.UTF_8)); cos.close(); exchange.getMessage().setBody(cos.newStreamCache()); diff --git a/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/CxfDispatchMessageTest.java b/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/CxfDispatchMessageTest.java index 8155a0c055f..32786d1d8fb 100644 --- a/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/CxfDispatchMessageTest.java +++ b/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/CxfDispatchMessageTest.java @@ -18,6 +18,7 @@ package org.apache.camel.component.cxf; import java.io.ByteArrayInputStream; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import org.w3c.dom.Document; @@ -87,7 +88,7 @@ public class CxfDispatchMessageTest extends CxfDispatchTestSupport { String payloadstr = String.format(form, name); InputStream message = null; try { - message = new ByteArrayInputStream(payloadstr.getBytes("utf-8")); + message = new ByteArrayInputStream(payloadstr.getBytes(StandardCharsets.UTF_8)); } catch (Exception e) { // ignore and let it fail } diff --git a/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/CxfDispatchPayloadTest.java b/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/CxfDispatchPayloadTest.java index 2a6e69fa6af..5df5c4ee105 100644 --- a/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/CxfDispatchPayloadTest.java +++ b/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/CxfDispatchPayloadTest.java @@ -17,6 +17,7 @@ package org.apache.camel.component.cxf; import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -93,7 +94,7 @@ public class CxfDispatchPayloadTest extends CxfDispatchTestSupport { CxfPayload<T> payload = null; try { Document doc = getDocumentBuilderFactory().newDocumentBuilder() - .parse(new ByteArrayInputStream(payloadstr.getBytes("utf-8"))); + .parse(new ByteArrayInputStream(payloadstr.getBytes(StandardCharsets.UTF_8))); payload = CxfPayloadConverter.documentToCxfPayload(doc, exchange); } catch (Exception e) { // ignore and let it fail diff --git a/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/mtom/CxfJavaMtomProducerPayloadTest.java b/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/mtom/CxfJavaMtomProducerPayloadTest.java index 63c4f8b57d8..40f0c8347b4 100644 --- a/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/mtom/CxfJavaMtomProducerPayloadTest.java +++ b/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/mtom/CxfJavaMtomProducerPayloadTest.java @@ -17,6 +17,7 @@ package org.apache.camel.component.cxf.mtom; import java.awt.Image; +import java.nio.charset.StandardCharsets; import java.util.List; import jakarta.xml.ws.Holder; @@ -44,7 +45,7 @@ public class CxfJavaMtomProducerPayloadTest extends CxfMtomConsumerTest { return; } - final Holder<byte[]> photo = new Holder<>("RequestFromCXF".getBytes("UTF-8")); + final Holder<byte[]> photo = new Holder<>("RequestFromCXF".getBytes(StandardCharsets.UTF_8)); final Holder<Image> image = new Holder<>(getImage("/java.jpg")); Exchange exchange = context.createProducerTemplate().send(MTOM_ENDPOINT_URI_MTOM_ENABLE, new Processor() { @@ -66,7 +67,7 @@ public class CxfJavaMtomProducerPayloadTest extends CxfMtomConsumerTest { final Holder<byte[]> responsePhoto = (Holder<byte[]>) parameter.get(1); assertNotNull(responsePhoto.value, "The photo should not be null"); assertEquals("ResponseFromCamel", - new String(responsePhoto.value, "UTF-8"), "Should get the right response"); + new String(responsePhoto.value, StandardCharsets.UTF_8), "Should get the right response"); final Holder<Image> responseImage = (Holder<Image>) parameter.get(2); assertNotNull(responseImage.value, "We should get the image here"); diff --git a/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/mtom/CxfMtomConsumerTest.java b/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/mtom/CxfMtomConsumerTest.java index 0908e60e6a0..b606964545e 100644 --- a/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/mtom/CxfMtomConsumerTest.java +++ b/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/mtom/CxfMtomConsumerTest.java @@ -18,6 +18,7 @@ package org.apache.camel.component.cxf.mtom; import java.awt.Image; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.List; import jakarta.xml.ws.BindingProvider; @@ -74,8 +75,8 @@ public class CxfMtomConsumerTest extends CamelTestSupport { Holder<byte[]> photo = (Holder<byte[]>) parameter.get(0); assertNotNull(photo.value, "The photo should not be null"); assertEquals("RequestFromCXF", - new String(photo.value, "UTF-8"), "Should get the right request"); - photo.value = "ResponseFromCamel".getBytes("UTF-8"); + new String(photo.value, StandardCharsets.UTF_8), "Should get the right request"); + photo.value = "ResponseFromCamel".getBytes(StandardCharsets.UTF_8); Holder<Image> image = (Holder<Image>) parameter.get(1); assertNotNull(image.value, "We should get the image here"); // set the holder message back @@ -114,7 +115,7 @@ public class CxfMtomConsumerTest extends CamelTestSupport { return; } - Holder<byte[]> photo = new Holder<>("RequestFromCXF".getBytes("UTF-8")); + Holder<byte[]> photo = new Holder<>("RequestFromCXF".getBytes(StandardCharsets.UTF_8)); Holder<Image> image = new Holder<>(getImage("/java.jpg")); Hello port = getPort(); @@ -124,7 +125,7 @@ public class CxfMtomConsumerTest extends CamelTestSupport { port.detail(photo, image); - assertEquals("ResponseFromCamel", new String(photo.value, "UTF-8")); + assertEquals("ResponseFromCamel", new String(photo.value, StandardCharsets.UTF_8)); assertNotNull(image.value); } diff --git a/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/mtom/CxfMtomProducerPayloadModeTest.java b/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/mtom/CxfMtomProducerPayloadModeTest.java index ea2e8cda47a..7b374eedac1 100644 --- a/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/mtom/CxfMtomProducerPayloadModeTest.java +++ b/components/camel-cxf/camel-cxf-spring-soap/src/test/java/org/apache/camel/component/cxf/mtom/CxfMtomProducerPayloadModeTest.java @@ -19,6 +19,7 @@ package org.apache.camel.component.cxf.mtom; import java.awt.image.BufferedImage; import java.io.StringReader; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -157,7 +158,7 @@ public class CxfMtomProducerPayloadModeTest { // CXF encoding the XOP reference since 3.0.1 private String decodingReference(String reference) throws UnsupportedEncodingException { - return java.net.URLDecoder.decode(reference, "UTF-8"); + return java.net.URLDecoder.decode(reference, StandardCharsets.UTF_8); } protected boolean isMtomEnabled() { diff --git a/components/camel-cxf/camel-cxf-spring-transport/src/test/java/org/apache/camel/component/cxf/transport/CamelDestinationTest.java b/components/camel-cxf/camel-cxf-spring-transport/src/test/java/org/apache/camel/component/cxf/transport/CamelDestinationTest.java index 806ed3f5c94..1013ca0bf0e 100644 --- a/components/camel-cxf/camel-cxf-spring-transport/src/test/java/org/apache/camel/component/cxf/transport/CamelDestinationTest.java +++ b/components/camel-cxf/camel-cxf-spring-transport/src/test/java/org/apache/camel/component/cxf/transport/CamelDestinationTest.java @@ -153,7 +153,7 @@ public class CamelDestinationTest extends CamelTransportTestSupport { private void verifyReceivedMessage(Message inMessage, String content) throws IOException { InputStream bis = inMessage.getContent(InputStream.class); - byte bytes[] = new byte[bis.available()]; + byte[] bytes = new byte[bis.available()]; bis.read(bytes); String reponse = new String(bytes); assertEquals(content, reponse, "The reponse date should be equals"); diff --git a/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelConduit.java b/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelConduit.java index fb6fb16dd71..013d6351482 100644 --- a/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelConduit.java +++ b/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelConduit.java @@ -44,12 +44,12 @@ public class CamelConduit extends AbstractConduit implements Configurable { private static final java.util.logging.Logger JUL_LOG = LogUtils.getL7dLogger(CamelConduit.class); private CamelContext camelContext; - private EndpointInfo endpointInfo; + private final EndpointInfo endpointInfo; private String targetCamelEndpointUri; - private Producer producer; + private final Producer producer; private ProducerTemplate camelTemplate; - private Bus bus; - private HeaderFilterStrategy headerFilterStrategy; + private final Bus bus; + private final HeaderFilterStrategy headerFilterStrategy; public CamelConduit(CamelContext context, Bus b, EndpointInfo endpointInfo) { this(context, b, endpointInfo, null); diff --git a/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelDestination.java b/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelDestination.java index a7f92dda5a2..c595124d5c4 100644 --- a/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelDestination.java +++ b/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelDestination.java @@ -62,7 +62,7 @@ public class CamelDestination extends AbstractDestination implements Configurabl String camelDestinationUri; private Endpoint destinationEndpoint; - private HeaderFilterStrategy headerFilterStrategy; + private final HeaderFilterStrategy headerFilterStrategy; private boolean checkException; public CamelDestination(CamelContext camelContext, Bus bus, ConduitInitiator ci, EndpointInfo info) { @@ -270,7 +270,7 @@ public class CamelDestination extends AbstractDestination implements Configurabl * Receives a response from CXF and forwards it to the camel route the request came in from */ private class CamelOutputStream extends CachedOutputStream { - private Message outMessage; + private final Message outMessage; CamelOutputStream(Message m) { outMessage = m; diff --git a/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelOutputStream.java b/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelOutputStream.java index 97d29649493..7ef6612ce1b 100644 --- a/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelOutputStream.java +++ b/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelOutputStream.java @@ -45,10 +45,10 @@ class CamelOutputStream extends CachedOutputStream { */ private final Message outMessage; private boolean isOneWay; - private String targetCamelEndpointUri; - private Producer producer; - private HeaderFilterStrategy headerFilterStrategy; - private MessageObserver observer; + private final String targetCamelEndpointUri; + private final Producer producer; + private final HeaderFilterStrategy headerFilterStrategy; + private final MessageObserver observer; private boolean hasLoggedAsyncWarning; CamelOutputStream(String targetCamelEndpointUri, Producer producer, diff --git a/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelTransportFactory.java b/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelTransportFactory.java index 69cf01088c7..02d5b223f4d 100644 --- a/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelTransportFactory.java +++ b/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/CamelTransportFactory.java @@ -165,26 +165,34 @@ public class CamelTransportFactory extends AbstractTransportFactory } DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class); if (null != dfm && getTransportIds() != null) { - for (String ns : getTransportIds()) { - try { - if (dfm.getDestinationFactory(ns) == this) { - dfm.deregisterDestinationFactory(ns); - } - } catch (BusException e) { - //ignore - } - } + unregisterDestinationFactories(dfm); } ConduitInitiatorManager cim = bus.getExtension(ConduitInitiatorManager.class); if (cim != null && getTransportIds() != null) { - for (String ns : getTransportIds()) { - try { - if (cim.getConduitInitiator(ns) == this) { - cim.deregisterConduitInitiator(ns); - } - } catch (BusException e) { - //ignore + unregisterConduitInitiators(cim); + } + } + + private void unregisterConduitInitiators(ConduitInitiatorManager cim) { + for (String ns : getTransportIds()) { + try { + if (cim.getConduitInitiator(ns) == this) { + cim.deregisterConduitInitiator(ns); + } + } catch (BusException e) { + //ignore + } + } + } + + private void unregisterDestinationFactories(DestinationFactoryManager dfm) { + for (String ns : getTransportIds()) { + try { + if (dfm.getDestinationFactory(ns) == this) { + dfm.deregisterDestinationFactory(ns); } + } catch (BusException e) { + //ignore } } } diff --git a/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/header/CxfHeaderFilterStrategy.java b/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/header/CxfHeaderFilterStrategy.java index f3b93c2deec..538e14dc584 100644 --- a/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/header/CxfHeaderFilterStrategy.java +++ b/components/camel-cxf/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/transport/header/CxfHeaderFilterStrategy.java @@ -130,7 +130,7 @@ public class CxfHeaderFilterStrategy extends DefaultHeaderFilterStrategy { messageHeaderfilter.filter(direction, (List<Header>) value); } catch (Exception t) { if (LOG.isDebugEnabled()) { - LOG.debug("Failed to cast value to Header<List> due to {}", t.toString(), t); + LOG.debug("Failed to cast value to Header<List> due to {}", t.getMessage(), t); } }