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_NAMESPACE_200508 );
72 if( wsaNameSpace != null )
73 {
74 wsaVns = WsaUtils.WS_A_NAMESPACE_200508;
75 }
76 else
77 {
78 wsaNameSpace = XmlUtils.findPrefixForNamespace( hdr, WsaUtils.WS_A_NAMESPACE_200408 );
79 if( wsaNameSpace != null )
80 {
81 wsaVns = WsaUtils.WS_A_NAMESPACE_200408;
82 }
83 else
84 {
85 wsaNameSpace = XmlUtils.findPrefixForNamespace( envelope, WsaUtils.WS_A_NAMESPACE_200508 );
86 if( wsaNameSpace != null )
87 {
88 wsaVns = WsaUtils.WS_A_NAMESPACE_200508;
89 }
90 else
91 {
92 wsaNameSpace = XmlUtils.findPrefixForNamespace( envelope, WsaUtils.WS_A_NAMESPACE_200408 );
93 if( wsaNameSpace != null )
94 {
95 wsaVns = WsaUtils.WS_A_NAMESPACE_200408;
96 }
97 else
98 {
99 return null;
100 }
101 }
102 }
103 }
104 }
105 catch( XmlException e )
106 {
107 SoapUI.logError( e );
108 }
109 return wsaVns;
110 }
111
112 private void validateWsAddressingCommon( String content )
113 {
114 if( wsaAssertionConfiguration.isAssertTo() )
115 {
116 Element toNode;
117 if( wsaVersionNameSpace != null )
118 {
119 toNode = XmlUtils.getFirstChildElementNS( header, wsaVersionNameSpace, "To" );
120 parseToNode( toNode );
121 }
122 else
123 {
124 toNode = XmlUtils.getFirstChildElementNS( header, WsaUtils.WS_A_NAMESPACE_200508, "To" );
125 if( toNode == null )
126 {
127 toNode = XmlUtils.getFirstChildElementNS( header, WsaUtils.WS_A_NAMESPACE_200408, "To" );
128 }
129 parseToNode( toNode );
130 }
131 }
132
133
134 Element faultToNode = XmlUtils.getFirstChildElementNS( header, wsaVersionNameSpace, "FaultTo" );
135 if( faultToNode != null )
136 {
137 Element addressNode = XmlUtils.getFirstChildElementNS( faultToNode, wsaVersionNameSpace, "Address" );
138 if( addressNode != null )
139 {
140 String faultToAddressValue = XmlUtils.getElementText( addressNode );
141 if( !StringUtils.isNullOrEmpty( faultToAddressValue ) )
142 {
143
144 if( AnonymousTypeConfig.PROHIBITED.toString().equals( messageExchange.getOperation().getAnonymous() )
145 && WsaUtils.isAnonymousAddress( faultToAddressValue, wsaVersionNameSpace ) )
146 {
147 cumulativeErrorMsg
148 .append( "WS-A InvalidAddressingHeader FaultTo , Anonymous addresses are prohibited. " );
149 }
150 else if( AnonymousTypeConfig.REQUIRED.toString().equals(
151 ( ( WsdlMessageExchange )messageExchange ).getOperation().getAnonymous() )
152 && !( WsaUtils.isAnonymousAddress( faultToAddressValue, wsaVersionNameSpace ) || WsaUtils
153 .isNoneAddress( faultToAddressValue, wsaVersionNameSpace ) ) )
154 {
155 cumulativeErrorMsg
156 .append( "WS-A InvalidAddressingHeader FaultTo , Anonymous addresses are required. " );
157 }
158 }
159 }
160 }
161
162 }
163
164 private void parseToNode( Element toNode )
165 {
166 if( toNode == null )
167 {
168 cumulativeErrorMsg.append( "WS-A To property is not specified. " );
169 }
170 else
171 {
172 String toAddressValue = XmlUtils.getElementText( toNode );
173 if( StringUtils.isNullOrEmpty( toAddressValue ) )
174 {
175 cumulativeErrorMsg.append( "WS-A To property is empty. " );
176 }
177 else
178 {
179
180 if( AnonymousTypeConfig.PROHIBITED.toString().equals( messageExchange.getOperation().getAnonymous() )
181 && WsaUtils.isAnonymousAddress( toAddressValue, wsaVersionNameSpace ) )
182 {
183 cumulativeErrorMsg.append( "WS-A InvalidAddressingHeader To , Anonymous addresses are prohibited. " );
184 }
185 }
186 }
187 }
188
189 public void validateWsAddressingRequest() throws AssertionException, XmlException
190 {
191 String content = messageExchange.getRequestContent();
192 SoapVersion soapVersion = messageExchange.getOperation().getInterface().getSoapVersion();
193
194 XmlObject xmlObject = XmlObject.Factory.parse( content );
195 header = ( Element )SoapUtils.getHeaderElement( xmlObject, soapVersion, true ).getDomNode();
196
197 wsaVersionNameSpace = getWsaVersion( xmlObject, soapVersion );
198
199
200
201
202
203
204
205
206 WsdlOperation operation = messageExchange.getOperation();
207
208 if( wsaAssertionConfiguration.isAssertAction() )
209 {
210 assertProperty( "Wsa:Action", "Action" );
211 }
212 validateWsAddressingCommon( content );
213 if( operation.isRequestResponse() )
214 {
215 if( wsaAssertionConfiguration.isAssertMessageId() )
216 {
217
218 assertProperty( "Wsa:MessageId", "MessageId" );
219 }
220 if( wsaAssertionConfiguration.isAssertReplyTo() )
221 {
222
223 Element replyToNode;
224 String currentTagWsaNs;
225 if( !StringUtils.isNullOrEmpty( wsaVersionNameSpace ) )
226 {
227 replyToNode = XmlUtils.getFirstChildElementNS( header, wsaVersionNameSpace, "ReplyTo" );
228 parseReplyToNode( replyToNode, wsaVersionNameSpace );
229 }
230 else
231 {
232 replyToNode = XmlUtils.getFirstChildElementNS( header, WsaUtils.WS_A_NAMESPACE_200508, "ReplyTo" );
233 currentTagWsaNs = WsaUtils.WS_A_NAMESPACE_200508;
234 if( replyToNode == null )
235 {
236 replyToNode = XmlUtils.getFirstChildElementNS( header, WsaUtils.WS_A_NAMESPACE_200408, "ReplyTo" );
237 currentTagWsaNs = WsaUtils.WS_A_NAMESPACE_200408;
238 }
239 parseReplyToNode( replyToNode, currentTagWsaNs );
240 }
241 }
242 }
243 String cumulativeError = cumulativeErrorMsg.toString();
244 if( !StringUtils.isNullOrEmpty( cumulativeError ) )
245 {
246 throw new AssertionException( new AssertionError( cumulativeError ) );
247 }
248 }
249
250 private void parseReplyToNode( Element replyToNode, String wsaNsStr )
251 {
252 if( replyToNode == null )
253 {
254 cumulativeErrorMsg.append( "WS-A ReplyTo property is not specified. " );
255 }
256 else
257 {
258 Element addressNode = XmlUtils.getFirstChildElementNS( replyToNode, wsaNsStr, "Address" );
259 if( addressNode == null )
260 {
261 cumulativeErrorMsg.append( "WS-A ReplyTo Address property is not specified. " );
262 }
263 else
264 {
265 String replyToAddressValue = XmlUtils.getElementText( addressNode );
266 if( StringUtils.isNullOrEmpty( replyToAddressValue ) )
267 {
268 cumulativeErrorMsg.append( "WS-A ReplyTo Address property is empty. " );
269 }
270 else
271 {
272
273 if( AnonymousTypeConfig.PROHIBITED.toString().equals(
274 ( ( WsdlMessageExchange )messageExchange ).getOperation().getAnonymous() )
275 && WsaUtils.isAnonymousAddress( replyToAddressValue, wsaNsStr ) )
276 {
277 cumulativeErrorMsg
278 .append( "WS-A InvalidAddressingHeader ReplyTo , Anonymous addresses are prohibited. " );
279 }
280 else if( AnonymousTypeConfig.REQUIRED.toString().equals(
281 ( ( WsdlMessageExchange )messageExchange ).getOperation().getAnonymous() )
282 && !( WsaUtils.isAnonymousAddress( replyToAddressValue, wsaNsStr ) || WsaUtils.isNoneAddress(
283 replyToAddressValue, wsaNsStr ) ) )
284 {
285 cumulativeErrorMsg
286 .append( "WS-A InvalidAddressingHeader ReplyTo , Anonymous addresses are required. " );
287 }
288 }
289 }
290 }
291 }
292
293 public void validateWsAddressingResponse() throws AssertionException, XmlException
294 {
295 String content = messageExchange.getResponseContent();
296 SoapVersion soapVersion = messageExchange.getOperation().getInterface().getSoapVersion();
297
298 XmlObject requestXmlObject = XmlObject.Factory.parse( messageExchange.getRequestContent() );
299 XmlObject xmlObject = XmlObject.Factory.parse( content );
300 header = ( Element )SoapUtils.getHeaderElement( xmlObject, soapVersion, true ).getDomNode();
301
302 wsaVersionNameSpace = getWsaVersion( xmlObject, soapVersion );
303
304 if( wsaAssertionConfiguration.isAssertAction() )
305 {
306 String defaultWsdlAction = WsdlUtils.getDefaultWsaAction( messageExchange.getOperation(), true );
307
308 assertProperty( "Wsa:Action", "Action", defaultWsdlAction );
309 }
310 validateWsAddressingCommon( content );
311
312 if( wsaAssertionConfiguration.isAssertRelatesTo() )
313 {
314
315 Element relatesToNode;
316 if( !StringUtils.isNullOrEmpty( wsaVersionNameSpace ) )
317 {
318 relatesToNode = XmlUtils.getFirstChildElementNS( header, wsaVersionNameSpace, "RelatesTo" );
319 parseRelatesToNode( soapVersion, requestXmlObject, relatesToNode );
320 }
321 else
322 {
323 relatesToNode = XmlUtils.getFirstChildElementNS( header, WsaUtils.WS_A_NAMESPACE_200508, "RelatesTo" );
324 if( relatesToNode == null )
325 {
326 relatesToNode = XmlUtils.getFirstChildElementNS( header, WsaUtils.WS_A_NAMESPACE_200408, "RelatesTo" );
327 }
328 parseRelatesToNode( soapVersion, requestXmlObject, relatesToNode );
329 }
330 }
331
332 Element replyToNode = XmlUtils.getFirstChildElementNS( header, wsaVersionNameSpace, "ReplyTo" );
333 if( replyToNode != null )
334 {
335 Element addressNode = XmlUtils.getFirstChildElementNS( replyToNode, wsaVersionNameSpace, "Address" );
336 if( addressNode != null )
337 {
338 String replyToAddressValue = XmlUtils.getElementText( addressNode );
339 if( !StringUtils.isNullOrEmpty( replyToAddressValue ) )
340 {
341
342 if( AnonymousTypeConfig.PROHIBITED.toString().equals(
343 ( ( WsdlMessageExchange )messageExchange ).getOperation().getAnonymous() )
344 && WsaUtils.isAnonymousAddress( replyToAddressValue, wsaVersionNameSpace ) )
345 {
346 cumulativeErrorMsg
347 .append( "WS-A InvalidAddressingHeader ReplyTo , Anonymous addresses are prohibited. " );
348 }
349 else if( AnonymousTypeConfig.REQUIRED.toString().equals(
350 ( ( WsdlMessageExchange )messageExchange ).getOperation().getAnonymous() )
351 && !( WsaUtils.isAnonymousAddress( replyToAddressValue, wsaVersionNameSpace ) || WsaUtils
352 .isNoneAddress( replyToAddressValue, wsaVersionNameSpace ) ) )
353 {
354 cumulativeErrorMsg
355 .append( "WS-A InvalidAddressingHeader ReplyTo , Anonymous addresses are required. " );
356 }
357 }
358 }
359 }
360 if( wsaAssertionConfiguration.isAssertReplyToRefParams() )
361 {
362
363
364 NodeList requestReplyToRefProps = WsdlUtils.getRequestReplyToRefProps( messageExchange, getWsaVersion(
365 requestXmlObject, soapVersion ) );
366 for( int i = 0; i < requestReplyToRefProps.getLength(); i++ )
367 {
368 Node refProp = requestReplyToRefProps.item( i );
369 String refPropName = refProp.getNodeName();
370 NodeList existingResponseRefs = XmlUtils.getChildElementsByTagName( header, refPropName );
371 if( existingResponseRefs != null && existingResponseRefs.getLength() > 0 )
372 {
373
374 continue;
375 }
376 else
377 {
378 cumulativeErrorMsg.append( "Response does not have request ReferenceProperty " + refPropName + ". " );
379 }
380
381 }
382 }
383 if( wsaAssertionConfiguration.isAssertFaultToRefParams() )
384 {
385
386
387 NodeList requestFaultToRefProps = WsdlUtils.getRequestFaultToRefProps( messageExchange, getWsaVersion(
388 requestXmlObject, soapVersion ) );
389 for( int i = 0; i < requestFaultToRefProps.getLength(); i++ )
390 {
391 Node refProp = requestFaultToRefProps.item( i );
392 String refPropName = refProp.getNodeName();
393 NodeList existingResponseRefs = XmlUtils.getChildElementsByTagName( header, refPropName );
394 if( existingResponseRefs != null && existingResponseRefs.getLength() > 0 )
395 {
396 continue;
397 }
398 else
399 {
400 cumulativeErrorMsg.append( "Response does not have request ReferenceProperty " + refPropName + ". " );
401 }
402
403 }
404 }
405 String cumulativeError = cumulativeErrorMsg.toString();
406 if( !StringUtils.isNullOrEmpty( cumulativeError ) )
407 {
408 throw new AssertionException( new AssertionError( cumulativeError ) );
409 }
410 }
411
412 private void parseRelatesToNode( SoapVersion soapVersion, XmlObject requestXmlObject, Element relatesToNode )
413 {
414 if( relatesToNode == null )
415 {
416 cumulativeErrorMsg.append( "WS-A RelatesTo property is not specified. " );
417 }
418 else
419 {
420 String relatesToValue = XmlUtils.getElementText( relatesToNode );
421 if( StringUtils.isNullOrEmpty( relatesToValue ) )
422 {
423 cumulativeErrorMsg.append( "WS-A RelatesTo property is empty. " );
424 }
425 else
426 {
427 String requestMsgId = WsdlUtils.getRequestWsaMessageId( messageExchange, getWsaVersion( requestXmlObject,
428 soapVersion ) );
429 if( !relatesToValue.equals( requestMsgId ) )
430 {
431 cumulativeErrorMsg.append( "WS-A RelatesTo property is not equal to request wsa:MessageId. " );
432 }
433 }
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458 }
459 }
460
461
462
463
464 private void assertProperty( String propertyName, String wsaProperty, String expectedValue )
465 {
466 Element propertyNode;
467
468 if( wsaVersionNameSpace != null )
469 {
470 propertyNode = XmlUtils.getFirstChildElementNS( header, wsaVersionNameSpace, wsaProperty );
471 parsePropertyNode( propertyName, propertyNode, expectedValue );
472 }
473 else
474 {
475 propertyNode = XmlUtils.getFirstChildElementNS( header, WsaUtils.WS_A_NAMESPACE_200508, wsaProperty );
476 if( propertyNode == null )
477 {
478 propertyNode = XmlUtils.getFirstChildElementNS( header, WsaUtils.WS_A_NAMESPACE_200408, wsaProperty );
479 }
480 parsePropertyNode( propertyName, propertyNode, expectedValue );
481 }
482 }
483
484 private void assertProperty( String propertyName, String wsaProperty )
485 {
486 assertProperty( propertyName, wsaProperty, null );
487 }
488
489 private void parsePropertyNode( String propertyName, Element propertyNode, String expectedValue )
490 {
491 if( propertyNode == null )
492 {
493 cumulativeErrorMsg.append( propertyName + " property is not specified. " );
494 }
495 else
496 {
497 String actionValue = XmlUtils.getElementText( propertyNode );
498 if( StringUtils.isNullOrEmpty( actionValue ) )
499 {
500 cumulativeErrorMsg.append( propertyName + " property is empty. " );
501 }
502 else if( !StringUtils.isNullOrEmpty( expectedValue ) )
503 {
504 if( !actionValue.equals( expectedValue ) )
505 {
506 cumulativeErrorMsg.append( propertyName + " expecting [" + expectedValue + "], actual value is ["
507 + actionValue + "]." );
508 }
509 }
510 }
511 }
512 }