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.handlers.addressing;
018    
019    import java.util.Iterator;
020    import java.util.Map;
021    
022    import javax.xml.namespace.QName;
023    
024    import org.apache.servicemix.id.IdGenerator;
025    import org.apache.servicemix.jbi.jaxp.SourceTransformer;
026    import org.apache.servicemix.jbi.resolver.URIResolver;
027    import org.apache.servicemix.jbi.util.DOMUtil;
028    import org.apache.servicemix.jbi.util.WSAddressingConstants;
029    import org.apache.servicemix.soap.Context;
030    import org.apache.servicemix.soap.SoapFault;
031    import org.apache.servicemix.soap.handlers.AbstractHandler;
032    import org.apache.servicemix.soap.marshalers.SoapMessage;
033    import org.w3c.dom.Document;
034    import org.w3c.dom.DocumentFragment;
035    import org.w3c.dom.Element;
036    
037    /**
038     * 
039     * @author Guillaume Nodet
040     * @version $Revision: 1.5 $
041     * @since 3.0
042     * 
043     * @org.apache.xbean.XBean element="ws-addressing"
044     */
045    public class AddressingHandler extends AbstractHandler {
046    
047        protected final SourceTransformer sourceTransformer = new SourceTransformer();
048        protected final IdGenerator idGenerator = new IdGenerator();
049        
050            public void onReceive(Context context) throws Exception {
051                    SoapMessage message = context.getInMessage();
052            String action = null;
053            String to = null;
054            String nsUri = null;
055            Map headers = message.getHeaders();
056            if (headers != null) {
057                    for (Iterator it = headers.keySet().iterator(); it.hasNext();) {
058                            QName qname = (QName) it.next();
059                            Object value = headers.get(qname);
060                    if (isWSANamespace(qname.getNamespaceURI())) {
061                                    if (nsUri == null) {
062                                            nsUri = qname.getNamespaceURI();
063                                    } else if (!nsUri.equals(qname.getNamespaceURI())) {
064                                            throw new SoapFault(SoapFault.SENDER, "Inconsistent use of wsa namespaces");
065                                    }
066                                    if (WSAddressingConstants.EL_ACTION.equals(qname.getLocalPart())) {
067                                            action = getHeaderText(value);
068                                            String[] parts = URIResolver.split3(action);
069                                            context.setProperty(Context.INTERFACE, new QName(parts[0], parts[1]));
070                                            context.setProperty(Context.OPERATION, new QName(parts[0], parts[2]));
071                                    } else if (WSAddressingConstants.EL_TO.equals(qname.getLocalPart())) {
072                            to = getHeaderText(value);
073                                            String[] parts = URIResolver.split3(to);
074                                            context.setProperty(Context.SERVICE, new QName(parts[0], parts[1]));
075                                            context.setProperty(Context.ENDPOINT, parts[2]);
076                                    } else {
077                                            // TODO: what ?
078                                    }
079                            }
080                    }
081            }
082            }
083        
084        public void onReply(Context context) throws Exception {
085            SoapMessage in = context.getInMessage();
086            SoapMessage out = context.getOutMessage();
087            Map headers = in.getHeaders();
088            if (headers != null) {
089                for (Iterator it = headers.keySet().iterator(); it.hasNext();) {
090                    QName qname = (QName) it.next();
091                    Object value = headers.get(qname);
092                    if (isWSANamespace(qname.getNamespaceURI())) {
093                        if (WSAddressingConstants.EL_MESSAGE_ID.equals(qname.getLocalPart())) {
094                            QName name = new QName(qname.getNamespaceURI(), WSAddressingConstants.EL_MESSAGE_ID, qname.getPrefix() != null ? qname.getPrefix() : WSAddressingConstants.WSA_PREFIX);
095                            DocumentFragment df = createHeader(name, idGenerator.generateSanitizedId());
096                            out.addHeader(name, df);
097                            name = new QName(qname.getNamespaceURI(), WSAddressingConstants.EL_RELATES_TO, qname.getPrefix() != null ? qname.getPrefix() : WSAddressingConstants.WSA_PREFIX);
098                            df = createHeader(name, getHeaderText(value));
099                            out.addHeader(name, df);
100                        }
101                    }
102                }
103            }
104        }
105        
106        protected boolean isWSANamespace(String ns) {
107            return WSAddressingConstants.WSA_NAMESPACE_200303.equals(ns) ||
108                   WSAddressingConstants.WSA_NAMESPACE_200403.equals(ns) ||
109                   WSAddressingConstants.WSA_NAMESPACE_200408.equals(ns) ||
110                   WSAddressingConstants.WSA_NAMESPACE_200508.equals(ns);
111        }
112        
113        protected String getHeaderText(Object header) {
114            Element el = (Element) ((DocumentFragment) header).getFirstChild();
115            return DOMUtil.getElementText(el);
116        }
117        
118        protected DocumentFragment createHeader(QName name, String value) throws Exception {
119            Document doc = new SourceTransformer().createDocument();
120            DocumentFragment df = doc.createDocumentFragment();
121            Element el = doc.createElementNS(name.getNamespaceURI(), name.getPrefix() + ":" + name.getLocalPart());
122            el.appendChild(doc.createTextNode(value));
123            df.appendChild(el);
124            return df;
125        }
126        
127    }