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.cxfbc.interceptors;
018
019 import java.util.ArrayList;
020 import java.util.Iterator;
021 import java.util.List;
022
023 import javax.xml.stream.XMLStreamException;
024 import javax.xml.stream.XMLStreamWriter;
025 import javax.xml.transform.Source;
026
027 import org.w3c.dom.Element;
028 import org.w3c.dom.Node;
029 import org.w3c.dom.NodeList;
030
031 import org.apache.cxf.binding.soap.SoapMessage;
032 import org.apache.cxf.binding.soap.SoapVersion;
033 import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
034 import org.apache.cxf.binding.soap.model.SoapBindingInfo;
035 import org.apache.cxf.binding.soap.model.SoapHeaderInfo;
036 import org.apache.cxf.endpoint.Endpoint;
037 import org.apache.cxf.headers.Header;
038 import org.apache.cxf.helpers.NSStack;
039 import org.apache.cxf.helpers.XMLUtils;
040 import org.apache.cxf.interceptor.Fault;
041 import org.apache.cxf.phase.Phase;
042 import org.apache.cxf.service.model.BindingMessageInfo;
043 import org.apache.cxf.service.model.BindingOperationInfo;
044 import org.apache.cxf.service.model.MessagePartInfo;
045 import org.apache.cxf.staxutils.StaxUtils;
046 import org.apache.servicemix.jbi.jaxp.SourceTransformer;
047 import org.apache.servicemix.soap.interceptors.jbi.JbiConstants;
048 import org.apache.servicemix.soap.util.DomUtil;
049 import org.apache.servicemix.soap.util.QNameUtil;
050
051 /**
052 * @author <a href="mailto:gnodet [at] gmail.com">Guillaume Nodet</a>
053 */
054 public class JbiOutWsdl1Interceptor extends AbstractSoapInterceptor {
055
056 private boolean useJBIWrapper = true;
057 private boolean useSOAPWrapper = true;
058
059 public JbiOutWsdl1Interceptor(boolean useJBIWrapper, boolean useSOAPWrapper) {
060 super(Phase.MARSHAL);
061 this.useJBIWrapper = useJBIWrapper;
062 this.useSOAPWrapper = useSOAPWrapper;
063 }
064
065 public void handleMessage(SoapMessage message) {
066 try {
067 Source source = message.getContent(Source.class);
068 if (source == null) {
069 return;
070 }
071
072 Element element = new SourceTransformer().toDOMElement(source);
073 XMLStreamWriter xmlWriter = message
074 .getContent(XMLStreamWriter.class);
075
076 if (!useJBIWrapper) {
077 SoapVersion soapVersion = message.getVersion();
078 if (element != null) {
079 // if this message is coming from the CxfBCConsumer
080 Element bodyElement = null;
081 if (useSOAPWrapper) {
082 bodyElement = (Element) element.getElementsByTagNameNS(
083 element.getNamespaceURI(),
084 soapVersion.getBody().getLocalPart()).item(0);
085 }
086 if (bodyElement != null) {
087 StaxUtils.writeElement(DomUtil.getFirstChildElement(bodyElement), xmlWriter, true);
088 } else {
089 // if this message is coming from the CxfBCProvider
090 StaxUtils.writeElement(element, xmlWriter, true);
091 }
092 }
093 return;
094 }
095
096 if (!JbiConstants.WSDL11_WRAPPER_NAMESPACE.equals(element
097 .getNamespaceURI())
098 || !JbiConstants.WSDL11_WRAPPER_MESSAGE_LOCALNAME
099 .equals(element.getLocalName())) {
100 throw new Fault(new Exception("Message wrapper element is '"
101 + QNameUtil.toString(element) + "' but expected '{"
102 + JbiConstants.WSDL11_WRAPPER_NAMESPACE + "}message'"));
103 }
104 BindingOperationInfo bop = message.getExchange().get(
105 BindingOperationInfo.class);
106 if (bop == null) {
107 throw new Fault(
108 new Exception("Operation not bound on this message"));
109 }
110 BindingMessageInfo msg = isRequestor(message) ? bop.getInput()
111 : bop.getOutput();
112
113
114 SoapBindingInfo binding = (SoapBindingInfo) message.getExchange()
115 .get(Endpoint.class).getEndpointInfo().getBinding();
116 String style = binding.getStyle(bop.getOperationInfo());
117 if (style == null) {
118 style = binding.getStyle();
119 }
120
121 if ("rpc".equals(style)) {
122 addOperationNode(message, xmlWriter);
123 getRPCPartWrapper(msg, element, message, xmlWriter);
124 } else {
125 Element partWrapper = DomUtil.getFirstChildElement(element);
126 while (partWrapper != null) {
127 List<NodeList> partsContent = getPartsContent(message, element, partWrapper, msg);
128 for (NodeList nl : partsContent) {
129 for (int i = 0; i < nl.getLength(); i++) {
130 Node n = nl.item(i);
131 StaxUtils.writeNode(n, xmlWriter, true);
132 }
133 }
134 partWrapper = DomUtil.getNextSiblingElement(partWrapper);
135 }
136 }
137
138 if ("rpc".equals(style)) {
139 xmlWriter.writeEndElement();
140 }
141 } catch (Fault e) {
142 throw e;
143 } catch (Exception e) {
144 throw new Fault(e);
145 }
146 }
147
148
149 private void getRPCPartWrapper(BindingMessageInfo msg,
150 Element element,
151 SoapMessage message,
152 XMLStreamWriter xmlWriter) {
153 try {
154 List<MessagePartInfo> parts = msg.getMessageParts();
155 Iterator iter = parts.iterator();
156 Element partWrapper = DomUtil.getFirstChildElement(element);
157 while (partWrapper != null) {
158 MessagePartInfo msgPart = (MessagePartInfo) iter.next();
159 String prefix = msgPart.getName().getPrefix();
160 String name = msgPart.getName().getLocalPart();
161 StaxUtils.writeStartElement(xmlWriter, prefix, name, "");
162 List<NodeList> partsContent = getPartsContent(message, element,
163 partWrapper, msg);
164 for (NodeList nl : partsContent) {
165 for (int i = 0; i < nl.getLength(); i++) {
166 Node n = nl.item(i);
167 StaxUtils.writeNode(n, xmlWriter, true);
168 }
169 }
170 xmlWriter.writeEndElement();
171 partWrapper = DomUtil.getNextSiblingElement(partWrapper);
172 }
173 } catch (Fault e) {
174 throw e;
175 } catch (Exception e) {
176 throw new Fault(e);
177 }
178 }
179
180 // Get each parts content
181 private List<NodeList> getPartsContent(SoapMessage message,
182 Element element,
183 Element partWrapper,
184 BindingMessageInfo msg) {
185 List<NodeList> partsContent = new ArrayList<NodeList>();
186 if (partWrapper != null) {
187 if (!JbiConstants.WSDL11_WRAPPER_NAMESPACE.equals(element.getNamespaceURI())
188 || !JbiConstants.WSDL11_WRAPPER_PART_LOCALNAME
189 .equals(partWrapper.getLocalName())) {
190 throw new Fault(new Exception(
191 "Unexpected part wrapper element '"
192 + QNameUtil.toString(element)
193 + "' expected '{"
194 + JbiConstants.WSDL11_WRAPPER_NAMESPACE
195 + "}part'"));
196 }
197 NodeList nodes = partWrapper.getChildNodes();
198 partsContent.add(nodes);
199 }
200
201 List<Header> headerList = message.getHeaders();
202 List<SoapHeaderInfo> headers = msg.getExtensors(SoapHeaderInfo.class);
203 for (SoapHeaderInfo header : headers) {
204 if (partsContent.size() == 0) {
205 break;
206 }
207
208 NodeList nl = partsContent.get(0);
209 if (header.getPart().getConcreteName().getNamespaceURI().equals(nl.item(0).getNamespaceURI())
210 && header.getPart().getConcreteName().getLocalPart().equals(nl.item(0).getLocalName())) {
211 headerList.add(new Header(header.getPart().getConcreteName(),
212 nl.item(0)));
213 partsContent.remove(0);
214 }
215
216 }
217
218 return partsContent;
219 }
220
221
222 protected String addOperationNode(SoapMessage message, XMLStreamWriter xmlWriter)
223 throws XMLStreamException {
224 String responseSuffix = !isRequestor(message) ? "Response" : "";
225 BindingOperationInfo boi = message.getExchange().get(
226 BindingOperationInfo.class);
227 String ns = boi.getName().getNamespaceURI();
228 NSStack nsStack = new NSStack();
229 nsStack.push();
230 nsStack.add(ns);
231 String prefix = nsStack.getPrefix(ns);
232 StaxUtils.writeStartElement(xmlWriter, prefix, boi.getName()
233 .getLocalPart()
234 + responseSuffix, ns);
235 return ns;
236 }
237
238 }