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.servicemix.soap.bindings.soap.interceptors;
018    
019    import java.util.Map;
020    
021    import javax.xml.namespace.QName;
022    import javax.xml.stream.XMLStreamConstants;
023    import javax.xml.stream.XMLStreamException;
024    import javax.xml.stream.XMLStreamReader;
025    
026    import org.apache.servicemix.soap.api.Fault;
027    import org.apache.servicemix.soap.api.Message;
028    import org.apache.servicemix.soap.bindings.soap.SoapConstants;
029    import org.apache.servicemix.soap.bindings.soap.SoapFault;
030    import org.apache.servicemix.soap.bindings.soap.SoapVersion;
031    import org.apache.servicemix.soap.bindings.soap.SoapVersionFactory;
032    import org.apache.servicemix.soap.core.AbstractInterceptor;
033    import org.apache.servicemix.soap.util.stax.StaxUtil;
034    import org.w3c.dom.DocumentFragment;
035    import org.w3c.dom.Element;
036    
037    /**
038     * @author <a href="mailto:gnodet [at] gmail.com">Guillaume Nodet</a>
039     */
040    public class SoapInInterceptor extends AbstractInterceptor {
041        
042        private final SoapVersion soapVersion;
043        
044        public SoapInInterceptor() {
045            this(null);
046        }
047        
048        public SoapInInterceptor(SoapVersion soapVersion) {
049            this.soapVersion = soapVersion;
050        }
051        
052        public void handleMessage(Message message) {
053            XMLStreamReader xmlReader = message.getContent(XMLStreamReader.class);
054            if (xmlReader == null) {
055                throw new NullPointerException("No xml reader found");
056            }
057            try {
058                QName name = xmlReader.getName();
059                SoapVersion soapVersion = this.soapVersion;
060                if (soapVersion == null) {
061                    soapVersion = message.get(SoapVersion.class);
062                }
063                if (soapVersion == null) {
064                    soapVersion = SoapVersionFactory.getInstance().getSoapVersion(name);
065                } else {
066                    soapVersion = soapVersion.getDerivedVersion(name.getPrefix());
067                }
068                if (soapVersion == null) {
069                    throw new SoapFault(SoapConstants.SOAP_12_CODE_VERSIONMISMATCH, "Unrecognized namespace: "
070                                    + xmlReader.getNamespaceURI() + " at ["
071                                    + xmlReader.getLocation().getLineNumber() + ","
072                                    + xmlReader.getLocation().getColumnNumber()
073                                    + "]. Expecting a Soap 1.1 or 1.2 namespace.");
074                }
075                message.put(SoapVersion.class, soapVersion);
076                if (!name.equals(soapVersion.getEnvelope())) {
077                    if (name.getLocalPart().equals(soapVersion.getEnvelope().getLocalPart())) {
078                        throw new SoapFault(SoapConstants.SOAP_12_CODE_VERSIONMISMATCH, 
079                              "Expected a SOAP " + soapVersion.getVersion() + " request");
080                    }
081                    throw new SoapFault(SoapConstants.SOAP_12_CODE_VERSIONMISMATCH, "Unrecognized element: "
082                                    + xmlReader.getName() + " at ["
083                                    + xmlReader.getLocation().getLineNumber() + ","
084                                    + xmlReader.getLocation().getColumnNumber()
085                                    + "]. Expecting 'Envelope'.");
086                }
087                xmlReader.nextTag();
088                if (xmlReader.getName().equals(soapVersion.getHeader())) {
089                    Map<QName, DocumentFragment> headers = message.getSoapHeaders();
090                    while (xmlReader.nextTag() != XMLStreamConstants.END_ELEMENT) {
091                        QName hn = xmlReader.getName();
092                        Element e = StaxUtil.createElement(xmlReader);
093                        DocumentFragment df = headers.get(hn);
094                        if (df == null) {
095                            df = e.getOwnerDocument().createDocumentFragment();
096                        }
097                        e = (Element) df.getOwnerDocument().importNode(e, true);
098                        df.appendChild(e);
099                        headers.put(hn, df);
100                    }
101                    xmlReader.nextTag();
102                }
103                if (!xmlReader.getName().equals(soapVersion.getBody())) {
104                    throw new SoapFault(SoapFault.SENDER, "Unrecognized element: "
105                                    + xmlReader.getName() + ". Expecting 'Body'.");
106                }
107                if (xmlReader.nextTag() == XMLStreamConstants.END_ELEMENT) {
108                    // Empty body
109                    message.setContent(XMLStreamReader.class, null);
110                }
111            } catch (XMLStreamException e) {
112                throw new Fault(e);
113            }
114        }
115        
116    }