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.common.util.DOMUtil;
026 import org.apache.servicemix.common.util.URIResolver;
027 import org.apache.servicemix.common.util.WSAddressingConstants;
028 import org.apache.servicemix.jbi.jaxp.SourceTransformer;
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(), getQualifiedName(name));
122 el.appendChild(doc.createTextNode(value));
123 df.appendChild(el);
124 return df;
125 }
126
127 /**
128 * Gets the QName prefix. If the QName has no set prefix, the specified default prefix will be used.
129 */
130 protected String getPrefix(QName qname, String defaultPrefix) {
131 String prefix = qname.getPrefix();
132 if(null == prefix || "".equals(prefix)) {
133 prefix = defaultPrefix;
134 }
135
136 return prefix;
137 }
138
139 protected String getQualifiedName(QName qname) {
140 String name = qname.getLocalPart();
141
142 String prefix = qname.getPrefix();
143 if(null != prefix && (!"".equals(prefix))) {
144 name = prefix + ":" + name;
145 }
146
147 return name;
148 }
149
150 }