1
2
3
4
5
6
7
8
9
10
11
12 package com.eviware.soapui.impl.wsdl.support.wsa;
13
14 import org.apache.xmlbeans.XmlException;
15 import org.apache.xmlbeans.XmlObject;
16 import org.w3c.dom.Element;
17 import org.w3c.dom.Node;
18 import org.w3c.dom.NodeList;
19
20 import com.eviware.soapui.SoapUI;
21 import com.eviware.soapui.config.AnonymousTypeConfig;
22 import com.eviware.soapui.impl.wsdl.WsdlOperation;
23 import com.eviware.soapui.impl.wsdl.panels.teststeps.support.WsaAssertionConfiguration;
24 import com.eviware.soapui.impl.wsdl.submit.WsdlMessageExchange;
25 import com.eviware.soapui.impl.wsdl.support.soap.SoapUtils;
26 import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
27 import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
28 import com.eviware.soapui.model.testsuite.AssertionError;
29 import com.eviware.soapui.model.testsuite.AssertionException;
30 import com.eviware.soapui.support.StringUtils;
31 import com.eviware.soapui.support.xml.XmlUtils;
32
33 /***
34 * Validating class for WS Addressing implemented according to WSDL 1.1
35 * specification
36 *
37 * @author dragica.soldo
38 * @see {@link}http://www.w3.org/TR/2006/WD-ws-addr-wsdl-20060216/#WSDL11MEPS
39 */
40 public class WsaValidator
41 {
42 WsdlMessageExchange messageExchange;
43 Element header;
44 String wsaVersionNameSpace;
45 StringBuilder cumulativeErrorMsg;
46 WsaAssertionConfiguration wsaAssertionConfiguration;
47
48 public WsaValidator(WsdlMessageExchange messageExchange, WsaAssertionConfiguration wsaAssertionConfiguration)
49 {
50 this.messageExchange = messageExchange;
51 this.wsaAssertionConfiguration = wsaAssertionConfiguration;
52 cumulativeErrorMsg = new StringBuilder();
53 }
54
55 public static String getWsaVersion(XmlObject contentObject, SoapVersion soapVersion)
56 {
57 String wsaVns = null;
58 try
59 {
60
61 XmlObject[] envS = contentObject.selectChildren( soapVersion.getEnvelopeQName() );
62 Element envelope = (Element) envS[0].getDomNode();
63
64 Element hdr = (Element) SoapUtils.getHeaderElement( contentObject, soapVersion, true ).getDomNode();
65
66 if( !hdr.hasChildNodes() )
67 {
68 return null;
69 }
70
71 String wsaNameSpace = XmlUtils.findPrefixForNamespace(hdr, WsaUtils.WS_A_VERSION_200508 );
72 if (wsaNameSpace != null)
73 {
74 wsaVns = WsaUtils.WS_A_VERSION_200508;
75 } else {
76 wsaNameSpace = XmlUtils.findPrefixForNamespace(hdr, WsaUtils.WS_A_VERSION_200408 );
77 if (wsaNameSpace != null)
78 {
79 wsaVns = WsaUtils.WS_A_VERSION_200408;
80 } else {
81 wsaNameSpace = XmlUtils.findPrefixForNamespace(envelope, WsaUtils.WS_A_VERSION_200508 );
82 if (wsaNameSpace != null)
83 {
84 wsaVns = WsaUtils.WS_A_VERSION_200508;
85 } else {
86 wsaNameSpace = XmlUtils.findPrefixForNamespace(envelope, WsaUtils.WS_A_VERSION_200408 );
87 if (wsaNameSpace != null)
88 {
89 wsaVns = WsaUtils.WS_A_VERSION_200408;
90 } else {
91 return null;
92 }
93 }
94 }
95 }
96 }
97 catch (XmlException e)
98 {
99 SoapUI.logError(e);
100 }
101 return wsaVns;
102 }
103 private void validateWsAddressingCommon( String content )
104 {
105 if (wsaAssertionConfiguration.isAssertTo())
106 {
107 Element toNode;
108 if (wsaVersionNameSpace != null) {
109 toNode = XmlUtils.getFirstChildElementNS(header, wsaVersionNameSpace, "To");
110 parseToNode(toNode);
111 } else {
112 toNode = XmlUtils.getFirstChildElementNS(header, WsaUtils.WS_A_VERSION_200508, "To");
113 if (toNode == null) {
114 toNode = XmlUtils.getFirstChildElementNS(header, WsaUtils.WS_A_VERSION_200408, "To");
115 }
116 parseToNode(toNode);
117 }
118 }
119
120 Element faultToNode = XmlUtils.getFirstChildElementNS( header, wsaVersionNameSpace, "FaultTo" );
121 if( faultToNode != null )
122 {
123 Element addressNode = XmlUtils.getFirstChildElementNS( faultToNode, wsaVersionNameSpace, "Address" );
124 if( addressNode != null )
125 {
126 String faultToAddressValue = XmlUtils.getElementText( addressNode );
127 if( !StringUtils.isNullOrEmpty( faultToAddressValue ) )
128 {
129
130 if( AnonymousTypeConfig.PROHIBITED.toString().equals( messageExchange.getOperation().getAnonymous() )
131 && WsaUtils.isAnonymousAddress(faultToAddressValue,wsaVersionNameSpace) )
132 {
133 cumulativeErrorMsg.append("WS-A InvalidAddressingHeader FaultTo , Anonymous addresses are prohibited. ");
134 } else if (AnonymousTypeConfig.REQUIRED.toString().equals( ((WsdlMessageExchange) messageExchange).getOperation().getAnonymous() )
135 && !(WsaUtils.isAnonymousAddress(faultToAddressValue,wsaVersionNameSpace) || WsaUtils.isNoneAddress(faultToAddressValue,wsaVersionNameSpace)))
136 {
137 cumulativeErrorMsg.append("WS-A InvalidAddressingHeader FaultTo , Anonymous addresses are required. ");
138 }
139 }
140 }
141 }
142
143 }
144
145 private void parseToNode(Element toNode) {
146 if (toNode == null)
147 {
148 cumulativeErrorMsg.append("WS-A To property is not specified. ");
149 }
150 else
151 {
152 String toAddressValue = XmlUtils.getElementText(toNode);
153 if (StringUtils.isNullOrEmpty(toAddressValue))
154 {
155 cumulativeErrorMsg.append("WS-A To property is empty. ");
156 }
157 else
158 {
159
160 if (AnonymousTypeConfig.PROHIBITED.toString().equals(messageExchange.getOperation().getAnonymous())
161 && WsaUtils.isAnonymousAddress(toAddressValue, wsaVersionNameSpace))
162 {
163 cumulativeErrorMsg
164 .append("WS-A InvalidAddressingHeader To , Anonymous addresses are prohibited. ");
165 }
166 }
167 }
168 }
169
170
171 public void validateWsAddressingRequest() throws AssertionException, XmlException
172 {
173 String content = messageExchange.getRequestContent();
174 SoapVersion soapVersion = messageExchange.getOperation().getInterface()
175 .getSoapVersion();
176
177 XmlObject xmlObject = XmlObject.Factory.parse( content );
178 header = (Element) SoapUtils.getHeaderElement( xmlObject, soapVersion, true ).getDomNode();
179
180 wsaVersionNameSpace = getWsaVersion(xmlObject, soapVersion);
181
182
183
184
185
186
187 WsdlOperation operation = messageExchange.getOperation();
188
189 if (wsaAssertionConfiguration.isAssertAction())
190 {
191 assertProperty("Wsa:Action", "Action");
192 }
193 validateWsAddressingCommon(content);
194 if (operation.isRequestResponse())
195 {
196 if (wsaAssertionConfiguration.isAssertMessageId()) {
197
198 assertProperty("Wsa:MessageId", "MessageId");
199 }
200 if (wsaAssertionConfiguration.isAssertReplyTo()) {
201
202 Element replyToNode;
203 String currentTagWsaNs;
204 if (!StringUtils.isNullOrEmpty(wsaVersionNameSpace)) {
205 replyToNode = XmlUtils.getFirstChildElementNS(header, wsaVersionNameSpace, "ReplyTo");
206 parseReplyToNode(replyToNode, wsaVersionNameSpace);
207 } else {
208 replyToNode = XmlUtils.getFirstChildElementNS(header, WsaUtils.WS_A_VERSION_200508, "ReplyTo");
209 currentTagWsaNs = WsaUtils.WS_A_VERSION_200508;
210 if (replyToNode == null) {
211 replyToNode = XmlUtils.getFirstChildElementNS(header, WsaUtils.WS_A_VERSION_200408, "ReplyTo");
212 currentTagWsaNs = WsaUtils.WS_A_VERSION_200408;
213 }
214 parseReplyToNode(replyToNode, currentTagWsaNs);
215 }
216 }
217 }
218 String cumulativeError = cumulativeErrorMsg.toString();
219 if (!StringUtils.isNullOrEmpty(cumulativeError))
220 {
221 throw new AssertionException(new AssertionError(cumulativeError));
222 }
223 }
224
225 private void parseReplyToNode(Element replyToNode, String wsaNsStr) {
226 if (replyToNode == null) {
227 cumulativeErrorMsg
228 .append("WS-A ReplyTo property is not specified. ");
229 } else {
230 Element addressNode = XmlUtils.getFirstChildElementNS(
231 replyToNode, wsaNsStr, "Address");
232 if (addressNode == null) {
233 cumulativeErrorMsg
234 .append("WS-A ReplyTo Address property is not specified. ");
235 } else {
236 String replyToAddressValue = XmlUtils
237 .getElementText(addressNode);
238 if (StringUtils.isNullOrEmpty(replyToAddressValue)) {
239 cumulativeErrorMsg
240 .append("WS-A ReplyTo Address property is empty. ");
241 } else {
242
243 if (AnonymousTypeConfig.PROHIBITED.toString().equals(
244 ((WsdlMessageExchange) messageExchange)
245 .getOperation().getAnonymous())
246 && WsaUtils.isAnonymousAddress(replyToAddressValue,
247 wsaNsStr)) {
248 cumulativeErrorMsg
249 .append("WS-A InvalidAddressingHeader ReplyTo , Anonymous addresses are prohibited. ");
250 } else if (AnonymousTypeConfig.REQUIRED.toString().equals(
251 ((WsdlMessageExchange) messageExchange)
252 .getOperation().getAnonymous())
253 && !(WsaUtils.isAnonymousAddress(
254 replyToAddressValue, wsaNsStr) || WsaUtils
255 .isNoneAddress(replyToAddressValue,
256 wsaNsStr))) {
257 cumulativeErrorMsg
258 .append("WS-A InvalidAddressingHeader ReplyTo , Anonymous addresses are required. ");
259 }
260 }
261 }
262 }
263 }
264
265 private void parseMessageIdNode(Element msgNode) {
266 if (msgNode == null) {
267 cumulativeErrorMsg
268 .append("WS-A MessageID property is not specified. ");
269 } else {
270 String msgValue = XmlUtils.getElementText(msgNode);
271 if (StringUtils.isNullOrEmpty(msgValue)) {
272 cumulativeErrorMsg
273 .append("WS-A MessageID property is empty");
274 }
275 }
276 }
277
278 public void validateWsAddressingResponse() throws AssertionException, XmlException
279 {
280 String content = messageExchange.getResponseContent();
281 SoapVersion soapVersion = messageExchange.getOperation().getInterface()
282 .getSoapVersion();
283
284 XmlObject requestXmlObject = XmlObject.Factory.parse( messageExchange.getRequestContent() );
285 XmlObject xmlObject = XmlObject.Factory.parse( content );
286 header = (Element) SoapUtils.getHeaderElement( xmlObject, soapVersion, true ).getDomNode();
287
288 wsaVersionNameSpace = getWsaVersion(xmlObject, soapVersion);
289
290
291
292
293
294
295
296
297 if (wsaAssertionConfiguration.isAssertAction())
298 {
299 String defaultWsdlAction = WsdlUtils.getDefaultWsaAction(messageExchange.getOperation(), true);
300
301 assertProperty("Wsa:Action", "Action", defaultWsdlAction);
302 }
303 validateWsAddressingCommon(content);
304
305 if (wsaAssertionConfiguration.isAssertRelatesTo())
306 {
307
308 Element relatesToNode;
309 if (!StringUtils.isNullOrEmpty(wsaVersionNameSpace)) {
310 relatesToNode = XmlUtils.getFirstChildElementNS(header, wsaVersionNameSpace, "RelatesTo");
311 parseRelatesToNode(soapVersion, requestXmlObject, relatesToNode);
312 } else{
313 relatesToNode = XmlUtils.getFirstChildElementNS(header, WsaUtils.WS_A_VERSION_200508, "RelatesTo");
314 if (relatesToNode == null) {
315 relatesToNode = XmlUtils.getFirstChildElementNS(header, WsaUtils.WS_A_VERSION_200408, "RelatesTo");
316 }
317 parseRelatesToNode(soapVersion, requestXmlObject, relatesToNode);
318 }
319 }
320
321 Element replyToNode = XmlUtils.getFirstChildElementNS( header, wsaVersionNameSpace, "ReplyTo" );
322 if( replyToNode != null )
323 {
324 Element addressNode = XmlUtils.getFirstChildElementNS( replyToNode, wsaVersionNameSpace, "Address" );
325 if( addressNode != null )
326 {
327 String replyToAddressValue = XmlUtils.getElementText( addressNode );
328 if( !StringUtils.isNullOrEmpty( replyToAddressValue ) )
329 {
330
331 if( AnonymousTypeConfig.PROHIBITED.toString().equals( ((WsdlMessageExchange) messageExchange).getOperation().getAnonymous() )
332 && WsaUtils.isAnonymousAddress(replyToAddressValue,wsaVersionNameSpace) )
333 {
334 cumulativeErrorMsg.append("WS-A InvalidAddressingHeader ReplyTo , Anonymous addresses are prohibited. ");
335 } else if (AnonymousTypeConfig.REQUIRED.toString().equals( ((WsdlMessageExchange) messageExchange).getOperation().getAnonymous() )
336 && !(WsaUtils.isAnonymousAddress(replyToAddressValue,wsaVersionNameSpace) || WsaUtils.isNoneAddress(replyToAddressValue,wsaVersionNameSpace)))
337 {
338 cumulativeErrorMsg.append("WS-A InvalidAddressingHeader ReplyTo , Anonymous addresses are required. ");
339 }
340 }
341 }
342 }
343 if (wsaAssertionConfiguration.isAssertReplyToRefParams()) {
344
345 NodeList requestReplyToRefProps = WsdlUtils.getRequestReplyToRefProps(
346 messageExchange, getWsaVersion(requestXmlObject, soapVersion));
347 for (int i = 0; i < requestReplyToRefProps.getLength(); i++) {
348 Node refProp = requestReplyToRefProps.item(i);
349 String refPropName = refProp.getNodeName();
350 NodeList existingResponseRefs = XmlUtils.getChildElementsByTagName(header, refPropName);
351 if (existingResponseRefs != null
352 && existingResponseRefs.getLength() > 0) {
353 continue;
354 } else {
355 cumulativeErrorMsg.append("Response does not have request ReferenceProperty "+ refPropName + ". ");
356 }
357
358 }
359 }
360 if (wsaAssertionConfiguration.isAssertFaultToRefParams()) {
361
362 NodeList requestFaultToRefProps = WsdlUtils.getRequestFaultToRefProps(
363 messageExchange, getWsaVersion(requestXmlObject, soapVersion));
364 for (int i = 0; i < requestFaultToRefProps.getLength(); i++) {
365 Node refProp = requestFaultToRefProps.item(i);
366 String refPropName = refProp.getNodeName();
367 NodeList existingResponseRefs = XmlUtils.getChildElementsByTagName(header, refPropName);
368 if (existingResponseRefs != null
369 && existingResponseRefs.getLength() > 0) {
370 continue;
371 } else {
372 cumulativeErrorMsg.append("Response does not have request ReferenceProperty "+ refPropName + ". ");
373 }
374
375 }
376 }
377 String cumulativeError = cumulativeErrorMsg.toString();
378 if (!StringUtils.isNullOrEmpty(cumulativeError))
379 {
380 throw new AssertionException(new AssertionError(cumulativeError));
381 }
382 }
383
384 private void parseRelatesToNode(SoapVersion soapVersion,
385 XmlObject requestXmlObject, Element relatesToNode) {
386 if (relatesToNode == null) {
387 cumulativeErrorMsg
388 .append("WS-A RelatesTo property is not specified. ");
389 } else {
390 String relatesToValue = XmlUtils
391 .getElementText(relatesToNode);
392 if (StringUtils.isNullOrEmpty(relatesToValue)) {
393 cumulativeErrorMsg
394 .append("WS-A RelatesTo property is empty. ");
395 } else {
396 String requestMsgId = WsdlUtils.getRequestWsaMessageId(
397 messageExchange, getWsaVersion(
398 requestXmlObject, soapVersion));
399 if (!relatesToValue.equals(requestMsgId)) {
400 cumulativeErrorMsg
401 .append("WS-A RelatesTo property is not equal to request wsa:MessageId. ");
402 }
403 }
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422 }
423 }
424
425
426
427
428 private void assertProperty(String propertyName, String wsaProperty, String expectedValue) {
429 Element propertyNode;
430
431 if (wsaVersionNameSpace != null) {
432 propertyNode = XmlUtils.getFirstChildElementNS(header,
433 wsaVersionNameSpace, wsaProperty);
434 parsePropertyNode(propertyName, propertyNode, expectedValue);
435 } else {
436 propertyNode = XmlUtils.getFirstChildElementNS(header, WsaUtils.WS_A_VERSION_200508, wsaProperty);
437 if (propertyNode == null) {
438 propertyNode = XmlUtils.getFirstChildElementNS(header, WsaUtils.WS_A_VERSION_200408, wsaProperty);
439 }
440 parsePropertyNode(propertyName, propertyNode, expectedValue);
441 }
442 }
443 private void assertProperty(String propertyName, String wsaProperty) {
444 assertProperty(propertyName, wsaProperty, null);
445 }
446
447 private void parsePropertyNode(String propertyName, Element propertyNode, String expectedValue) {
448 if (propertyNode == null) {
449 cumulativeErrorMsg
450 .append( propertyName + " property is not specified. ");
451 } else {
452 String actionValue = XmlUtils.getElementText(propertyNode);
453 if (StringUtils.isNullOrEmpty(actionValue)) {
454 cumulativeErrorMsg
455 .append( propertyName + " property is empty. ");
456 } else if (!StringUtils.isNullOrEmpty(expectedValue)) {
457
458
459
460 if (!actionValue.equals(expectedValue)) {
461 cumulativeErrorMsg
462 .append(propertyName + " property should be "
463 + expectedValue + ". ");
464 }
465 }
466 }
467 }
468 }