Author: ningjiang Date: Thu Oct 25 12:17:11 2012 New Revision: 1402124 URL: http://svn.apache.org/viewvc?rev=1402124&view=rev Log: CAMEL-5724 Applied patch with thanks to Andrej
Added: camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/ camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/MessageFilter.java camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/impl/ camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/impl/BasicFilterStrategy.java Modified: camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceComponent.java camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceConfiguration.java camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceConsumer.java camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceProducer.java Modified: camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceComponent.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceComponent.java?rev=1402124&r1=1402123&r2=1402124&view=diff ============================================================================== --- camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceComponent.java (original) +++ camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceComponent.java Thu Oct 25 12:17:11 2012 @@ -19,6 +19,7 @@ package org.apache.camel.component.sprin import java.net.URI; import java.net.URISyntaxException; import java.util.Map; + import javax.xml.transform.TransformerFactory; import org.apache.camel.CamelContext; @@ -26,11 +27,13 @@ import org.apache.camel.Endpoint; import org.apache.camel.RuntimeCamelException; import org.apache.camel.component.spring.ws.bean.CamelEndpointDispatcher; import org.apache.camel.component.spring.ws.bean.CamelEndpointMapping; +import org.apache.camel.component.spring.ws.filter.MessageFilter; import org.apache.camel.component.spring.ws.type.EndpointMappingKey; import org.apache.camel.component.spring.ws.type.EndpointMappingType; import org.apache.camel.converter.jaxp.XmlConverter; import org.apache.camel.impl.DefaultComponent; import org.apache.camel.util.CamelContextHelper; +import org.apache.camel.util.EndpointHelper; import org.apache.camel.util.UnsafeUriCharactersEncoder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,6 +69,7 @@ public class SpringWebserviceComponent e addProducerConfiguration(remaining, parameters, configuration); addXmlConverterToConfiguration(parameters, configuration); setProperties(configuration, parameters); + configureMessageFilter(parameters, configuration); return new SpringWebserviceEndpoint(this, uri, configuration); } @@ -153,4 +157,25 @@ public class SpringWebserviceComponent e } configuration.setXmlConverter(xmlConverter); } + + + /** + * Configures the messageFilter's factory. The factory is looked up in the endpoint's URI and then in the Spring's context. + * The bean search mechanism looks for a bean with the name messageFilter. + * The endpoint's URI search mechanism looks for the URI's key parameter name messageFilter, for instance like this: + * spring-ws:http://yourdomain.com?messageFilter=<beanName> + * + * @param parameters + * @param configuration + */ + private void configureMessageFilter(Map<String, Object> parameters, SpringWebserviceConfiguration configuration) { + + final MessageFilter globalMessageFilter = EndpointHelper.resolveReferenceParameter( + getCamelContext(), "messageFilter", MessageFilter.class, false /*not mandatory*/); + final MessageFilter messageFilter = resolveAndRemoveReferenceParameter( + parameters, "messageFilter", MessageFilter.class, globalMessageFilter); + + configuration.setMessageFilter(messageFilter); + } + } Modified: camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceConfiguration.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceConfiguration.java?rev=1402124&r1=1402123&r2=1402124&view=diff ============================================================================== --- camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceConfiguration.java (original) +++ camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceConfiguration.java Thu Oct 25 12:17:11 2012 @@ -21,6 +21,8 @@ import java.net.URISyntaxException; import org.apache.camel.component.spring.ws.bean.CamelEndpointDispatcher; import org.apache.camel.component.spring.ws.bean.CamelEndpointMapping; +import org.apache.camel.component.spring.ws.filter.MessageFilter; +import org.apache.camel.component.spring.ws.filter.impl.BasicFilterStrategy; import org.apache.camel.component.spring.ws.type.EndpointMappingKey; import org.apache.camel.converter.jaxp.XmlConverter; import org.apache.camel.util.jsse.SSLContextParameters; @@ -41,6 +43,7 @@ public class SpringWebserviceConfigurati private SSLContextParameters sslContextParameters; private XmlConverter xmlConverter; + private MessageFilter messageFilter; public WebServiceTemplate getWebServiceTemplate() { return webServiceTemplate; @@ -137,4 +140,29 @@ public class SpringWebserviceConfigurati int i = uri.lastIndexOf(')'); return i == -1 ? uri : (uri.subSequence(0, i) + "}" + uri.substring(i + 1)).replaceFirst("\\(", "{"); } + + + /** + * Default setter to override failsafe message filter. + * + * @param messageFilter non-default MessageFilter + */ + public void setMessageFilter(MessageFilter messageFilter) { + this.messageFilter = messageFilter; + + } + + /** + * Gets the configured MessageFilter. + * + * Note: The only place that sets fail safe strategy. + * + * @return instance of MessageFilter that is never null; + */ + public MessageFilter getMessageFilter() { + if (this.messageFilter == null) { + this.messageFilter = new BasicFilterStrategy(); + } + return this.messageFilter; + } } Modified: camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceConsumer.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceConsumer.java?rev=1402124&r1=1402123&r2=1402124&view=diff ============================================================================== --- camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceConsumer.java (original) +++ camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceConsumer.java Thu Oct 25 12:17:11 2012 @@ -19,6 +19,7 @@ package org.apache.camel.component.sprin import java.util.HashMap; import java.util.Iterator; import java.util.Map; + import javax.xml.namespace.QName; import javax.xml.transform.Source; @@ -65,6 +66,9 @@ public class SpringWebserviceConsumer ex if (responseMessage != null) { Source responseBody = responseMessage.getBody(Source.class); WebServiceMessage response = messageContext.getResponse(); + + configuration.getMessageFilter().filterConsumer(exchange, response); + XmlConverter xmlConverter = configuration.getXmlConverter(); xmlConverter.toResult(responseBody, response.getPayloadResult()); } Modified: camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceProducer.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceProducer.java?rev=1402124&r1=1402123&r2=1402124&view=diff ============================================================================== --- camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceProducer.java (original) +++ camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/SpringWebserviceProducer.java Thu Oct 25 12:17:11 2012 @@ -32,10 +32,8 @@ import org.apache.camel.RuntimeCamelExce import org.apache.camel.TypeConverter; import org.apache.camel.impl.DefaultProducer; import org.apache.camel.util.ExchangeHelper; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.ws.WebServiceMessage; import org.springframework.ws.client.core.SourceExtractor; import org.springframework.ws.client.core.WebServiceMessageCallback; @@ -73,7 +71,7 @@ public class SpringWebserviceProducer ex String soapAction = exchange.getIn().getHeader(SpringWebserviceConstants.SPRING_WS_SOAP_ACTION, String.class); URI wsAddressingAction = exchange.getIn().getHeader(SpringWebserviceConstants.SPRING_WS_ADDRESSING_ACTION, URI.class); - WebServiceMessageCallback callback = new DefaultWebserviceMessageCallback(soapAction, wsAddressingAction, getEndpoint().getConfiguration()); + WebServiceMessageCallback callback = new DefaultWebserviceMessageCallback(soapAction, wsAddressingAction, getEndpoint().getConfiguration(), exchange); Object body = null; if (endpointUri != null) { body = getEndpoint().getConfiguration().getWebServiceTemplate().sendSourceAndReceive(endpointUri, sourcePayload, callback, SOURCE_EXTRACTOR); @@ -197,11 +195,13 @@ public class SpringWebserviceProducer ex private final String soapActionHeader; private final URI wsAddressingActionHeader; private final SpringWebserviceConfiguration configuration; + private final Exchange exchange; - public DefaultWebserviceMessageCallback(String soapAction, URI wsAddressingAction, SpringWebserviceConfiguration configuration) { + public DefaultWebserviceMessageCallback(String soapAction, URI wsAddressingAction, SpringWebserviceConfiguration configuration, Exchange exchange) { this.soapActionHeader = soapAction; this.wsAddressingActionHeader = wsAddressingAction; this.configuration = configuration; + this.exchange = exchange; } public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException { @@ -218,6 +218,8 @@ public class SpringWebserviceProducer ex if (wsAddressingAction != null) { new ActionCallback(wsAddressingAction).doWithMessage(message); } + + configuration.getMessageFilter().filterProducer(exchange, message); } } Added: camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/MessageFilter.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/MessageFilter.java?rev=1402124&view=auto ============================================================================== --- camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/MessageFilter.java (added) +++ camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/MessageFilter.java Thu Oct 25 12:17:11 2012 @@ -0,0 +1,47 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.spring.ws.filter; + +import org.apache.camel.Exchange; +import org.springframework.ws.WebServiceMessage; + +/** + * A strategy instance that filters a WebServiceMessage response. + * + * This class provides an additional configuration that can be managed in your Spring's context. + * + * + */ +public interface MessageFilter { + + /** + * Calls filter for a producer + * + * @param exchange + * @param response provided by the producer + */ + void filterProducer(Exchange exchange, WebServiceMessage produceRresponse); + + /** + * Calls filter for a consumer + * + * @param exchange + * @param response provided by the consumer + */ + void filterConsumer(Exchange exchange, WebServiceMessage consumerResponse); + +} Added: camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/impl/BasicFilterStrategy.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/impl/BasicFilterStrategy.java?rev=1402124&view=auto ============================================================================== --- camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/impl/BasicFilterStrategy.java (added) +++ camel/trunk/components/camel-spring-ws/src/main/java/org/apache/camel/component/spring/ws/filter/impl/BasicFilterStrategy.java Thu Oct 25 12:17:11 2012 @@ -0,0 +1,134 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.spring.ws.filter.impl; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.activation.DataHandler; +import javax.xml.namespace.QName; + +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.component.spring.ws.SpringWebserviceConstants; +import org.apache.camel.component.spring.ws.filter.MessageFilter; +import org.springframework.ws.WebServiceMessage; +import org.springframework.ws.soap.SoapHeader; +import org.springframework.ws.soap.SoapMessage; + +/** + * This class populates a SOAP header and attachments + * + * + */ +public class BasicFilterStrategy implements MessageFilter { + private static final String BREADCRUMB_ID = "breadcrumbId"; + + @Override + public void filterProducer(Exchange exchange, WebServiceMessage response) { + if (exchange != null) { + processHeaderAndAttachemtns(exchange.getIn(), response); + } + } + + @Override + public void filterConsumer(Exchange exchange, WebServiceMessage response) { + if (exchange != null) { + processHeaderAndAttachemtns(exchange.getOut(), response); + } + } + + /** + * If applicable this method adds a SOAP header and attachments. + * + * @param inOrOut + * @param response + */ + protected void processHeaderAndAttachemtns(Message inOrOut, WebServiceMessage response) { + + if (response instanceof SoapMessage) { + SoapMessage soapMessage = (SoapMessage)response; + processHeader(inOrOut, soapMessage); + processAttachements(inOrOut, soapMessage); + } + } + + /** + * The SOAP header is populated from exchange.getOut().getHeaders() if this + * class is used by the consumer or exchange.getIn().getHeaders() if this + * class is used by the producer. + * + * If .getHeaders() contains under a certain key a value with the QName + * object, it is directly added as a new header element. If it contains only + * a String value, it is transformed into a header attribute. + * + * Following headers are excluded: {@code BREADCRUMB_ID} + * + * @see SpringWebserviceConstants.SPRING_WS_SOAP_ACTION, @see + * SpringWebserviceConstants.SPRING_WS_ADDRESSING_ACTION), @see + * SpringWebserviceConstants.SPRING_WS_ENDPOINT_URI + * + * @param inOrOut + * @param soapMessage + */ + protected void processHeader(Message inOrOut, SoapMessage soapMessage) { + boolean isHeaderAvailable = inOrOut != null && inOrOut.getHeaders() != null + && !inOrOut.getHeaders().isEmpty(); + + if (isHeaderAvailable) { + SoapHeader soapHeader = soapMessage.getSoapHeader(); + + Map<String, Object> headers = inOrOut.getHeaders(); + + Set<String> headerKeySet = new HashSet<String>(headers.keySet()); + + headerKeySet.remove(SpringWebserviceConstants.SPRING_WS_SOAP_ACTION); + headerKeySet.remove(SpringWebserviceConstants.SPRING_WS_ADDRESSING_ACTION); + headerKeySet.remove(SpringWebserviceConstants.SPRING_WS_ENDPOINT_URI); + headerKeySet.remove(BREADCRUMB_ID); + + for (String name : headerKeySet) { + Object value = headers.get(name); + + if (value instanceof QName) { + soapHeader.addHeaderElement((QName)value); + } else { + if (value instanceof String) { + soapHeader.addAttribute(new QName(name), value + ""); + } + } + } + } + } + + /** + * Populate SOAP attachments from in or out exchange message. + * + * @param inOrOut + * @param response + */ + protected void processAttachements(Message inOrOut, SoapMessage response) { + Map<String, DataHandler> attachments = inOrOut.getAttachments(); + + Set<String> keySet = new HashSet<String>(attachments.keySet()); + for (String key : keySet) { + response.addAttachment(key, attachments.get(key)); + } + } + +}