001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.component.spring.ws;
018    
019    import java.io.IOException;
020    import java.net.URI;
021    import javax.xml.transform.Source;
022    import javax.xml.transform.TransformerException;
023    
024    import org.apache.camel.Endpoint;
025    import org.apache.camel.Exchange;
026    import org.apache.camel.TypeConverter;
027    import org.apache.camel.impl.DefaultProducer;
028    import org.springframework.ws.WebServiceMessage;
029    import org.springframework.ws.client.core.SourceExtractor;
030    import org.springframework.ws.client.core.WebServiceMessageCallback;
031    import org.springframework.ws.soap.addressing.client.ActionCallback;
032    import org.springframework.ws.soap.client.core.SoapActionCallback;
033    
034    public class SpringWebserviceProducer extends DefaultProducer {
035    
036        private static final SourceExtractor SOURCE_EXTRACTOR = new NoopSourceExtractor();
037        private SpringWebserviceEndpoint endpoint;
038    
039        public SpringWebserviceProducer(Endpoint endpoint) {
040            super(endpoint);
041            this.endpoint = (SpringWebserviceEndpoint) endpoint;
042        }
043    
044        public void process(Exchange exchange) throws Exception {
045            // Let Camel TypeConverter hierarchy handle the conversion of XML messages to Source objects
046            Source sourcePayload = exchange.getIn().getMandatoryBody(Source.class);
047    
048            // Extract optional headers
049            String endpointUri = exchange.getIn().getHeader(SpringWebserviceConstants.SPRING_WS_ENDPOINT_URI, String.class);
050            String soapAction = exchange.getIn().getHeader(SpringWebserviceConstants.SPRING_WS_SOAP_ACTION, String.class);
051            URI wsAddressingAction = exchange.getIn().getHeader(SpringWebserviceConstants.SPRING_WS_ADDRESSING_ACTION, URI.class);
052    
053            WebServiceMessageCallback callback = new DefaultWebserviceMessageCallback(soapAction, wsAddressingAction);
054            Object body = null;
055            if (endpointUri != null) {
056                body = endpoint.getConfiguration().getWebServiceTemplate().sendSourceAndReceive(endpointUri, sourcePayload, callback, SOURCE_EXTRACTOR);
057            } else {
058                body = endpoint.getConfiguration().getWebServiceTemplate().sendSourceAndReceive(sourcePayload, callback, SOURCE_EXTRACTOR);
059            }
060            exchange.getOut().setBody(body);
061        }
062    
063        protected class DefaultWebserviceMessageCallback implements WebServiceMessageCallback {
064            private String soapActionHeader;
065            private URI wsAddressingActionHeader;
066    
067            public DefaultWebserviceMessageCallback(String soapAction, URI wsAddressingAction) {
068                this.soapActionHeader = soapAction;
069                this.wsAddressingActionHeader = wsAddressingAction;
070            }
071    
072            public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
073                // Add SoapAction to webservice request. Note that exchange header
074                // takes precedence over endpoint option
075                String soapAction = soapActionHeader != null ? soapActionHeader : endpoint.getConfiguration().getSoapAction();
076                if (soapAction != null) {
077                    new SoapActionCallback(soapAction).doWithMessage(message);
078                }
079                // Add WS-Addressing Action to webservice request (the WS-Addressing
080                // 'to' header will default to the URL of the connection).
081                // Note that exchange header takes precedence over endpoint option
082                URI wsAddressingAction = wsAddressingActionHeader != null ? wsAddressingActionHeader : endpoint.getConfiguration().getWsAddressingAction();
083                if (wsAddressingAction != null) {
084                    new ActionCallback(wsAddressingAction).doWithMessage(message);
085                }
086            }
087        }
088    
089        /**
090         * A {@link SourceExtractor} that performs no conversion, instead conversion
091         * is handled by Camel's {@link TypeConverter} hierarchy.
092         */
093        private static class NoopSourceExtractor implements SourceExtractor {
094            public Object extractData(Source source) throws IOException, TransformerException {
095                return source;
096            }
097        }
098    }