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