1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.support;
14
15 import java.io.StringWriter;
16 import java.util.Map;
17
18 import javax.wsdl.BindingOperation;
19 import javax.wsdl.Part;
20 import javax.wsdl.extensions.ExtensibilityElement;
21 import javax.wsdl.extensions.soap.SOAPBody;
22 import javax.wsdl.extensions.soap.SOAPHeader;
23 import javax.xml.namespace.QName;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.xmlbeans.SchemaGlobalElement;
28 import org.apache.xmlbeans.SchemaType;
29 import org.apache.xmlbeans.XmlCursor;
30 import org.apache.xmlbeans.XmlObject;
31
32 import com.eviware.soapui.impl.wsdl.WsdlInterface;
33 import com.eviware.soapui.model.iface.Interface;
34 import com.eviware.soapui.model.iface.Operation;
35 import com.eviware.soapui.model.iface.Request;
36 import com.eviware.soapui.model.iface.RequestBuilder;
37 import com.eviware.soapui.support.XmlUtils;
38
39 /***
40 * Builds SOAP requests according to WSDL/XSD definitions
41 *
42 * @author Ole.Matzura
43 */
44
45 public class SoapRequestBuilder implements RequestBuilder
46 {
47 private final static Log log = LogFactory.getLog( SoapRequestBuilder.class );
48
49 private final QName envelopeQName = new QName("http://schemas.xmlsoap.org/soap/envelope/", "Envelope");
50
51 private final QName bodyQName = new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body");
52
53 private final QName headerQName = new QName("http://schemas.xmlsoap.org/soap/envelope/", "Header");
54
55 private WsdlContext wsdlContext;
56
57 private WsdlInterface iface;
58
59 public SoapRequestBuilder(WsdlInterface iface) throws Exception
60 {
61 this.iface = iface;
62 this.wsdlContext = iface.getWsdlContext();
63 }
64
65 public SoapRequestBuilder(WsdlContext wsdlContext)
66 {
67 this.wsdlContext = wsdlContext;
68 }
69
70 public Interface getInterface()
71 {
72 return iface;
73 }
74
75 public Request buildRequest(Operation operation, Map params)
76 {
77 return null;
78 }
79
80 public String buildSoapRequest(BindingOperation bindingOperation, boolean buildOptional ) throws Exception
81 {
82 boolean inputSoapEncoded = WsdlUtils.isInputSoapEncoded( bindingOperation );
83 SampleXmlUtil xmlGenerator = new SampleXmlUtil(inputSoapEncoded);
84 xmlGenerator.setIgnoreOptional( !buildOptional );
85
86 XmlObject object = XmlObject.Factory.newInstance();
87 XmlCursor cursor = object.newCursor();
88 cursor.toNextToken();
89 cursor.beginElement(envelopeQName);
90
91 if( inputSoapEncoded )
92 {
93 cursor.insertNamespace( "xsi", "http://www.w3.org/2001/XMLSchema-instance" );
94 cursor.insertNamespace( "xsd", "http://www.w3.org/2001/XMLSchema" );
95 }
96
97 cursor.toFirstChild();
98
99 cursor.beginElement(bodyQName);
100 cursor.toFirstChild();
101
102 if( WsdlUtils.isRpc( wsdlContext.getDefinition(), bindingOperation ))
103 {
104 buildRpcRequest( bindingOperation, cursor, xmlGenerator );
105 }
106 else
107 {
108 buildDocumentRequest( bindingOperation, cursor, xmlGenerator );
109 }
110
111 addHeaders(bindingOperation, cursor, xmlGenerator);
112 cursor.dispose();
113
114 try
115 {
116 StringWriter writer = new StringWriter();
117 XmlUtils.serializePretty( object, writer );
118 return writer.toString();
119 }
120 catch( Exception e )
121 {
122 e.printStackTrace();
123 return object.xmlText();
124 }
125 }
126
127 private void addHeaders(BindingOperation bindingOperation, XmlCursor cursor, SampleXmlUtil xmlGenerator) throws Exception
128 {
129 ExtensibilityElement[] headers = WsdlUtils.getExtensiblityElements(bindingOperation.getBindingInput()
130 .getExtensibilityElements(), SOAPHeader.class);
131 if (headers.length > 0)
132 {
133
134 cursor.toStartDoc();
135 cursor.toChild(envelopeQName);
136 cursor.toFirstChild();
137
138 cursor.beginElement(headerQName);
139 cursor.toFirstChild();
140
141 for (int i = 0; i < headers.length; i++)
142 {
143 SOAPHeader header = (SOAPHeader) headers[i];
144
145
146
147 Part part = wsdlContext.getDefinition().getMessage( header.getMessage() ).getPart( header.getPart() );
148
149
150
151 if( part != null )
152 createElementForPart( part, cursor, xmlGenerator );
153 else
154 log.error( "Missing part for header; " + header.getPart() );
155 }
156 }
157 }
158
159 private void createElementForPart(Part part, XmlCursor cursor, SampleXmlUtil xmlGenerator ) throws Exception
160 {
161 QName elementName = part.getElementName();
162 QName typeName = part.getTypeName();
163
164 if( elementName != null )
165 {
166 cursor.beginElement(elementName);
167
168 if( wsdlContext.hasSchemaTypes() )
169 {
170 SchemaGlobalElement elm = wsdlContext.getSchemaTypes().findElement(elementName);
171 if( elm != null )
172 {
173 cursor.toFirstChild();
174 xmlGenerator.createSampleForType(elm.getType(), cursor);
175 cursor.toParent();
176 }
177 }
178 }
179 else
180 {
181 cursor.beginElement( new QName( wsdlContext.getDefinition().getTargetNamespace(), part.getName() ));
182 if( typeName != null && wsdlContext.hasSchemaTypes() )
183 {
184 SchemaType type = wsdlContext.getSchemaTypes().findType( typeName );
185
186 if( type != null )
187 {
188 cursor.toFirstChild();
189 xmlGenerator.createSampleForType( type, cursor );
190 }
191 else log.error( "Could not find type [" + typeName + "] specified in part [" + part.getName() + "]" );
192 }
193 }
194 }
195
196 private void buildDocumentRequest(BindingOperation bindingOperation, XmlCursor cursor, SampleXmlUtil xmlGenerator) throws Exception
197 {
198 Part[] parts = WsdlUtils.getInputParts( bindingOperation );
199 if( parts.length > 1 )
200 log.warn( "document style operation should not have more than one part" );
201
202 for (int i = 0; i < parts.length; i++)
203 {
204 XmlCursor c = cursor.newCursor();
205 c.toLastChild();
206 createElementForPart( parts[i], c, xmlGenerator );
207 c.dispose();
208 }
209 }
210
211 private void buildRpcRequest(BindingOperation bindingOperation, XmlCursor cursor, SampleXmlUtil xmlGenerator) throws Exception
212 {
213
214 SOAPBody body = (SOAPBody) WsdlUtils.getExtensiblityElement(bindingOperation.getBindingInput()
215 .getExtensibilityElements(), SOAPBody.class);
216
217 String ns = wsdlContext.getDefinition().getTargetNamespace();
218 if( body != null && body.getNamespaceURI() != null )
219 ns = body.getNamespaceURI();
220
221 cursor.beginElement( new QName( ns, bindingOperation.getName() ));
222 if( xmlGenerator.isSoapEnc() )
223 cursor.insertAttributeWithValue( new QName( "http://schemas.xmlsoap.org/soap/envelope/", "encodingStyle" ),
224 "http://schemas.xmlsoap.org/soap/encoding/");
225
226 Part[] inputParts = WsdlUtils.getInputParts( bindingOperation );
227 for (int i = 0; i < inputParts.length; i++)
228 {
229 Part part = inputParts[i];
230 XmlCursor c = cursor.newCursor();
231 c.toLastChild();
232 c.insertElement( part.getName() );
233 c.toPrevToken();
234
235 if( wsdlContext.hasSchemaTypes() )
236 {
237 SchemaType type = wsdlContext.findType( part.getTypeName() );
238 if( type != null )
239 xmlGenerator.createSampleForType( type, c );
240 else
241 log.error( "Failed to find type [" + part.getTypeName() + "]" );
242 }
243
244 c.dispose();
245 }
246 }
247
248 public void setWsdlContext( WsdlContext wsdlContext )
249 {
250 this.wsdlContext = wsdlContext;
251 }
252 }