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.util.HashMap;
020    import java.util.Iterator;
021    import java.util.Map;
022    import javax.xml.namespace.QName;
023    import javax.xml.transform.Source;
024    
025    import org.apache.camel.Endpoint;
026    import org.apache.camel.Exchange;
027    import org.apache.camel.ExchangePattern;
028    import org.apache.camel.Message;
029    import org.apache.camel.Processor;
030    import org.apache.camel.converter.jaxp.XmlConverter;
031    import org.apache.camel.impl.DefaultConsumer;
032    import org.apache.camel.impl.DefaultExchange;
033    import org.springframework.ws.WebServiceMessage;
034    import org.springframework.ws.context.MessageContext;
035    import org.springframework.ws.server.endpoint.MessageEndpoint;
036    import org.springframework.ws.soap.SoapHeader;
037    import org.springframework.ws.soap.SoapHeaderElement;
038    import org.springframework.ws.soap.SoapMessage;
039    
040    public class SpringWebserviceConsumer extends DefaultConsumer implements MessageEndpoint {
041    
042        private SpringWebserviceEndpoint endpoint;
043        private SpringWebserviceConfiguration configuration;
044    
045        public SpringWebserviceConsumer(Endpoint endpoint, Processor processor) {
046            super(endpoint, processor);
047            this.endpoint = (SpringWebserviceEndpoint) endpoint;
048            this.configuration = this.endpoint.getConfiguration();
049        }
050    
051        /**
052         * Invoked by Spring-WS when a {@link WebServiceMessage} is received
053         */
054        public void invoke(MessageContext messageContext) throws Exception {
055            Exchange exchange = new DefaultExchange(endpoint.getCamelContext(), ExchangePattern.InOptionalOut);
056            populateExchangeFromMessageContext(messageContext, exchange);
057    
058            // start message processing
059            getProcessor().process(exchange);
060    
061            // create webservice response from output body
062            if (exchange.getPattern().isOutCapable()) {
063                Message responseMessage = exchange.getOut(Message.class);
064                if (responseMessage != null) {
065                    Source responseBody = responseMessage.getBody(Source.class);
066                    WebServiceMessage response = messageContext.getResponse();
067                    XmlConverter xmlConverter = configuration.getXmlConverter();
068                    xmlConverter.toResult(responseBody, response.getPayloadResult());
069                }
070            }
071        }
072    
073        private void populateExchangeFromMessageContext(MessageContext messageContext, Exchange exchange) {
074            populateExchangeWithPropertiesFromMessageContext(messageContext, exchange);
075    
076            // create inbound message
077            WebServiceMessage request = messageContext.getRequest();
078            SpringWebserviceMessage inMessage = new SpringWebserviceMessage(request);
079            inMessage.setHeaders(extractSoapHeadersFromWebServiceMessage(request));
080            exchange.setIn(inMessage);
081        }
082    
083        private void populateExchangeWithPropertiesFromMessageContext(MessageContext messageContext, Exchange exchange) {
084            // convert WebserviceMessage properties (added through interceptors) to
085            // Camel exchange properties
086            String[] propertyNames = messageContext.getPropertyNames();
087            if (propertyNames != null) {
088                for (String propertyName : propertyNames) {
089                    exchange.setProperty(propertyName, messageContext.getProperty(propertyName));
090                }
091            }
092        }
093    
094        private Map<String, Object> extractSoapHeadersFromWebServiceMessage(WebServiceMessage request) {
095            Map<String, Object> headers = new HashMap<String, Object>();
096            if (request instanceof SoapMessage) {
097                SoapMessage soapMessage = (SoapMessage) request;
098                SoapHeader soapHeader = soapMessage.getSoapHeader();
099                if (soapHeader != null) {
100                    Iterator<?> attibutesIterator = soapHeader.getAllAttributes();
101                    while (attibutesIterator.hasNext()) {
102                        QName name = (QName) attibutesIterator.next();
103                        headers.put(name.toString(), soapHeader.getAttributeValue(name));
104                    }
105                    Iterator<?> elementIter = soapHeader.examineAllHeaderElements();
106                    while (elementIter.hasNext()) {
107                        Object element = elementIter.next();
108                        if (element instanceof SoapHeaderElement) {
109                            QName name = ((SoapHeaderElement) element).getName();
110                            headers.put(name.toString(), element);
111                        }
112                    }
113                }
114            }
115            return headers;
116        }
117    
118        @Override
119        protected void doStop() throws Exception {
120            if (configuration.getEndpointMapping() != null) {
121                configuration.getEndpointMapping().removeConsumer(configuration.getEndpointMappingKey());
122            }
123            super.doStop();
124        }
125    
126        @Override
127        protected void doStart() throws Exception {
128            if (configuration.getEndpointMapping() != null) {
129                configuration.getEndpointMapping().addConsumer(configuration.getEndpointMappingKey(), this);
130            }
131            super.doStart();
132        }
133    
134    }