View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.support.wsa;
14  
15  import java.io.IOException;
16  import java.util.ArrayList;
17  import java.util.UUID;
18  
19  import org.apache.xmlbeans.XmlException;
20  import org.apache.xmlbeans.XmlObject;
21  import org.w3c.dom.DOMException;
22  import org.w3c.dom.Document;
23  import org.w3c.dom.Element;
24  import org.w3c.dom.Node;
25  import org.w3c.dom.NodeList;
26  import org.w3c.dom.Text;
27  
28  import com.eviware.soapui.SoapUI;
29  import com.eviware.soapui.config.AnonymousTypeConfig;
30  import com.eviware.soapui.config.MustUnderstandTypeConfig;
31  import com.eviware.soapui.config.WsaVersionTypeConfig;
32  import com.eviware.soapui.impl.wsdl.WsdlOperation;
33  import com.eviware.soapui.impl.wsdl.mock.WsdlMockRequest;
34  import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse;
35  import com.eviware.soapui.impl.wsdl.submit.transports.http.ExtendedHttpMethod;
36  import com.eviware.soapui.impl.wsdl.support.soap.SoapUtils;
37  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
38  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
39  import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
40  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
41  import com.eviware.soapui.settings.WsaSettings;
42  import com.eviware.soapui.support.StringUtils;
43  import com.eviware.soapui.support.xml.XmlUtils;
44  
45  /***
46   * WS Addressing-related utility-methods..
47   * 
48   * ws-a Action element is created according to rules specified at {@link}
49   * http://www.w3.org/TR/2007/REC-ws-addr-metadata-20070904/#actioninwsdl {@link}
50   * http://www.w3.org/TR/2006/WD-ws-addr-wsdl-20060216/#actioninwsdl for
51   * explicitly using soap action check Global WS-A settings Soap action
52   * overides...
53   * 
54   * @author dragica.soldo
55   */
56  
57  public class WsaUtils
58  {
59  
60  	public static final String WS_A_NAMESPACE_200508 = "http://www.w3.org/2005/08/addressing";
61  	public static final String WS_A_NAMESPACE_200408 = "http://schemas.xmlsoap.org/ws/2004/08/addressing";
62  	/*
63  	 * see http://www.w3.org/TR/2006/WD-ws-addr-wsdl-20060216/#actioninwsdl
64  	 */
65  	public static final String WS_A_NAMESPACE_200602 = "http://www.w3.org/2006/02/addressing/wsdl";
66  	public static final String WS_A_NAMESPACE_200605 = "http://www.w3.org/2006/05/addressing/wsdl";
67  	/*
68  	 * see http://www.w3.org/TR/2007/REC-ws-addr-metadata-20070904/#actioninwsdl
69  	 */
70  	public static final String WS_A_NAMESPACE_200705 = "http://www.w3.org/2007/05/addressing/metadata";
71  
72  	public static final String[] wsaNamespaces = { WS_A_NAMESPACE_200705, WS_A_NAMESPACE_200508, WS_A_NAMESPACE_200408,
73  			WS_A_NAMESPACE_200605, WS_A_NAMESPACE_200602 };
74  
75  	SoapVersion soapVersion;
76  	WsdlOperation operation;
77  	WsaBuilder builder;
78  	XmlObject xmlContentObject;
79  	// element to add every property to
80  	Element envelopeElement;
81  	String wsaVersionNameSpace;
82  
83  	String wsaPrefix = null;
84  	String wsaVersionNamespaceOld = null;
85  
86  	String anonymousType;
87  	String anonymousAddress;
88  	String noneAddress;
89  	String relationshipTypeReply;
90  	// used for mock response relates to if request.messageId not specified
91  	String unspecifiedMessage;
92  	String content;
93  	// needed for checking if ws-a already applied before
94  	XmlObject xmlHeaderObject;
95  	ArrayList<Node> headerWsaElementList;
96  	private final PropertyExpansionContext context;
97  
98  	public WsaUtils( String content, SoapVersion soapVersion, WsdlOperation operation, PropertyExpansionContext context )
99  	{
100 		this.soapVersion = soapVersion;
101 		this.operation = operation;
102 		this.content = content;
103 		this.context = context;
104 		try
105 		{
106 			xmlContentObject = XmlObject.Factory.parse( content );
107 		}
108 		catch( Exception e )
109 		{
110 			SoapUI.logError( e );
111 		}
112 	}
113 
114 	private Element getHeader( WsaContainer wsaContainer ) throws XmlException
115 	{
116 
117 		// version="2005/08" is default
118 		wsaVersionNameSpace = WS_A_NAMESPACE_200508;
119 		if( wsaContainer.getWsaConfig().getVersion().equals( WsaVersionTypeConfig.X_200408.toString() ) )
120 		{
121 			wsaVersionNameSpace = WS_A_NAMESPACE_200408;
122 		}
123 		anonymousAddress = wsaVersionNameSpace + "/anonymous";
124 		noneAddress = wsaVersionNameSpace + "/none";
125 		relationshipTypeReply = wsaVersionNameSpace + "/reply";
126 		unspecifiedMessage = wsaVersionNameSpace + "/unspecified";
127 
128 		anonymousType = wsaContainer.getOperation().getAnonymous();
129 		// if optional at operation level, check policy specification on
130 		// interface
131 		// level
132 		if( anonymousType.equals( AnonymousTypeConfig.OPTIONAL.toString() ) )
133 		{
134 			anonymousType = wsaContainer.getOperation().getInterface().getAnonymous();
135 		}
136 
137 		Element header = ( Element )SoapUtils.getHeaderElement( xmlContentObject, soapVersion, true ).getDomNode();
138 
139 		wsaPrefix = XmlUtils.findPrefixForNamespace( header, WsaUtils.WS_A_NAMESPACE_200508 );
140 		if( wsaPrefix != null )
141 		{
142 			wsaVersionNamespaceOld = WsaUtils.WS_A_NAMESPACE_200508;
143 		}
144 		else
145 		{
146 			wsaPrefix = XmlUtils.findPrefixForNamespace( header, WsaUtils.WS_A_NAMESPACE_200408 );
147 			if( wsaPrefix != null )
148 			{
149 				wsaVersionNamespaceOld = WsaUtils.WS_A_NAMESPACE_200408;
150 			}
151 			else
152 			{
153 				wsaPrefix = XmlUtils.findPrefixForNamespace( header, WsaUtils.WS_A_NAMESPACE_200508 );
154 				if( wsaPrefix != null )
155 				{
156 					wsaVersionNamespaceOld = WsaUtils.WS_A_NAMESPACE_200508;
157 				}
158 				else
159 				{
160 					wsaPrefix = XmlUtils.findPrefixForNamespace( header, WsaUtils.WS_A_NAMESPACE_200408 );
161 					if( wsaPrefix != null )
162 					{
163 						wsaVersionNamespaceOld = WsaUtils.WS_A_NAMESPACE_200408;
164 					}
165 					else
166 					{
167 						wsaPrefix = "wsa";
168 					}
169 				}
170 			}
171 		}
172 		XmlObject[] envelope = xmlContentObject.selectChildren( soapVersion.getEnvelopeQName() );
173 		envelopeElement = ( Element )envelope[0].getDomNode();
174 
175 		Boolean mustUnderstand = null;
176 		if( wsaContainer.getWsaConfig().getMustUnderstand().equals( MustUnderstandTypeConfig.FALSE.toString() ) )
177 		{
178 			mustUnderstand = false;
179 		}
180 		else if( wsaContainer.getWsaConfig().getMustUnderstand().equals( MustUnderstandTypeConfig.TRUE.toString() ) )
181 		{
182 			mustUnderstand = true;
183 		}
184 
185 		builder = new WsaBuilder( wsaVersionNameSpace, mustUnderstand );
186 
187 		return header;
188 
189 	}
190 
191 	private Node getWsaProperty( Element header, String elementLocalName )
192 	{
193 		NodeList elmList = header.getElementsByTagName( elementLocalName );
194 		// NodeList elmList = header.getElementsByTagNameNS(namespaceURI,
195 		// localName);
196 		Node elm = null;
197 		if( elmList.getLength() > 0 )
198 		{
199 			elm = elmList.item( 0 );
200 		}
201 		return elm;
202 
203 	}
204 
205 	private Element removeWsaProperty( boolean overrideExisting, Element header, String elementLocalName )
206 	{
207 		if( overrideExisting )
208 		{
209 			NodeList elmList = header.getElementsByTagName( elementLocalName );
210 			Node elm = null;
211 			if( elmList.getLength() > 0 )
212 			{
213 				elm = elmList.item( 0 );
214 			}
215 			if( elm != null )
216 			{
217 				header.removeChild( elm );
218 			}
219 		}
220 		return header;
221 	}
222 
223 	/***
224 	 * Processing ws-a property
225 	 * 
226 	 * @param header
227 	 *           - header element to add wsa to
228 	 * @param override
229 	 *           - indicates if existing parameters should be overriden with new
230 	 *           values
231 	 * @param elementLocalName
232 	 *           - property string to add, for instance: any:Action, or
233 	 *           any:ReplyTo
234 	 * @param wsaPropValue
235 	 *           - wsa property value, inserted in input box, or default
236 	 *           generated
237 	 * @param address
238 	 *           - indicates if property is an endpoint reference, i.e. if it has
239 	 *           <address> tag inside itself
240 	 * @param refParamsContent
241 	 *           - the content of ReferenceParameters for specific endpoint
242 	 *           reference, null if property is an absolute IRI
243 	 */
244 	private Element processWsaProperty( Element header, boolean override, String elementLocalName, String wsaPropValue,
245 			boolean address, String refParamsContent )
246 	{
247 		boolean existsWsa = getWsaProperty( header, elementLocalName ) != null ? true : false;
248 		if( override )
249 		{
250 			if( existsWsa )
251 			{
252 				header = removeWsaProperty( override, header, elementLocalName );
253 			}
254 			if( address )
255 			{
256 				header.appendChild( builder.createWsaAddressChildElement( elementLocalName, envelopeElement, wsaPropValue,
257 						refParamsContent ) );
258 			}
259 			else
260 			{
261 				header.appendChild( builder.createWsaChildElement( elementLocalName, envelopeElement, wsaPropValue ) );
262 			}
263 
264 		}
265 		else if( !existsWsa )
266 		{
267 			if( address )
268 			{
269 				header.appendChild( builder.createWsaAddressChildElement( elementLocalName, envelopeElement, wsaPropValue,
270 						refParamsContent ) );
271 			}
272 			else
273 			{
274 				header.appendChild( builder.createWsaChildElement( elementLocalName, envelopeElement, wsaPropValue ) );
275 			}
276 		}
277 		return header;
278 	}
279 
280 	private Element processWsaProperty( Element header, boolean override, String elementLocalName, String wsaPropValue,
281 			boolean address )
282 	{
283 		return processWsaProperty( header, override, elementLocalName, wsaPropValue, address, null );
284 	}
285 
286 	private Element processWsaRelatesToProperty( Element header, boolean override, String elementLocalName,
287 			String relationshipType, String relatesTo )
288 	{
289 		boolean existsWsa = getWsaProperty( header, elementLocalName ) != null ? true : false;
290 		if( override )
291 		{
292 			if( existsWsa )
293 			{
294 				header = removeWsaProperty( override, header, elementLocalName );
295 			}
296 			header.appendChild( builder.createRelatesToElement( wsaPrefix + ":RelatesTo", envelopeElement,
297 					relationshipType, relatesTo ) );
298 		}
299 		else if( !existsWsa )
300 		{
301 			header.appendChild( builder.createRelatesToElement( wsaPrefix + ":RelatesTo", envelopeElement,
302 					relationshipType, relatesTo ) );
303 		}
304 		return header;
305 	}
306 
307 	public String removeWSAddressing( WsaContainer wsaContainer )
308 	{
309 		try
310 		{
311 			Element header = getHeader( wsaContainer );
312 			NodeList headerProps = XmlUtils.getChildElements( header );
313 			for( int i = 0; i < headerProps.getLength(); i++ )
314 			{
315 				Node headerChild = headerProps.item( i );
316 				if( headerChild.getNamespaceURI().equals( wsaVersionNameSpace ) )
317 				{
318 					header.removeChild( headerChild );
319 				}
320 			}
321 			content = xmlContentObject.xmlText();
322 		}
323 		catch( XmlException e )
324 		{
325 			SoapUI.logError( e );
326 		}
327 		return content;
328 	}
329 
330 	public String addWSAddressingRequest( WsaContainer wsaContainer )
331 	{
332 		return addWSAddressingRequest( wsaContainer, null );
333 	}
334 
335 	public String addWSAddressingRequest( WsaContainer wsaContainer, ExtendedHttpMethod httpMethod )
336 	{
337 		return createNewWSAddressingRequest( wsaContainer, httpMethod, SoapUI.getSettings().getBoolean(
338 				WsaSettings.OVERRIDE_EXISTING_HEADERS ) );
339 	}
340 
341 	private String createNewWSAddressingRequest( WsaContainer wsaContainer, ExtendedHttpMethod httpMethod,
342 			boolean override )
343 	{
344 		try
345 		{
346 			Element header = getHeader( wsaContainer );
347 
348 			if( override || wsaVersionNamespaceOld == null )
349 			{
350 				header.setAttribute( "xmlns:" + wsaPrefix, wsaVersionNameSpace );
351 			}
352 
353 			String action = null;
354 			if( wsaContainer.getWsaConfig().isAddDefaultAction() )
355 			{
356 				action = WsdlUtils.getDefaultWsaAction( wsaContainer.getOperation(), false );
357 			}
358 			else
359 			{
360 				action = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getAction() );
361 			}
362 			if( !StringUtils.isNullOrEmpty( action ) )
363 			{
364 				header = processWsaProperty( header, override, wsaPrefix + ":Action", action, false );
365 			}
366 
367 			String replyTo = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getReplyTo() );
368 			String replyToRefParams = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig()
369 					.getReplyToRefParams() );
370 			if( AnonymousTypeConfig.REQUIRED.toString().equals( anonymousType ) )
371 			// TODO check if WsaSettings.USE_DEFAULT_REPLYTO is needed
372 			// considering
373 			// anonymous added
374 			// &&
375 			// SoapUI.getSettings().getBoolean(WsaSettings.USE_DEFAULT_REPLYTO))
376 			{
377 				header = processWsaProperty( header, override, wsaPrefix + ":ReplyTo", anonymousAddress, true,
378 						replyToRefParams );
379 			}
380 			else if( !StringUtils.isNullOrEmpty( replyTo ) )
381 			{
382 				if( !( AnonymousTypeConfig.PROHIBITED.toString().equals( anonymousType ) && isAnonymousAddress( replyTo,
383 						wsaVersionNameSpace ) ) )
384 				{
385 					header = processWsaProperty( header, override, wsaPrefix + ":ReplyTo", replyTo, true, replyToRefParams );
386 				}
387 			}
388 			// TODO removed option for the purpose of wstf testing(echo 1.6 for
389 			// instance needs to have faultTo and no replyTo)
390 			// see how to handle this if needed (commented by Dragica 20.10.08.)
391 			// else if (operation.isRequestResponse())
392 			// {
393 			// //for request-response replyTo is mandatory, set it to none if
394 			// anonymous prohibited
395 			// if
396 			// (!AnonymousTypeConfig.PROHIBITED.toString().equals(anonymousType))
397 			// {
398 			// header = processWsaProperty(header, override, wsaPrefix +
399 			// ":ReplyTo", anonymousAddress, true, replyToRefParams);
400 			// } else {
401 			// header = processWsaProperty(header, override, wsaPrefix +
402 			// ":ReplyTo", noneAddress, true, replyToRefParams);
403 			// }
404 			// }
405 
406 			String from = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getFrom() );
407 			if( !StringUtils.isNullOrEmpty( from ) )
408 			{
409 				header = processWsaProperty( header, override, wsaPrefix + ":From", from, true );
410 			}
411 			String faultTo = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getFaultTo() );
412 			String faultToRefParams = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig()
413 					.getFaultToRefParams() );
414 			if( !StringUtils.isNullOrEmpty( faultTo ) )
415 			{
416 				header = processWsaProperty( header, override, wsaPrefix + ":FaultTo", faultTo, true, faultToRefParams );
417 			}
418 
419 			String relatesTo = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getRelatesTo() );
420 			String relationshipType = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig()
421 					.getRelationshipType() );
422 			if( !StringUtils.isNullOrEmpty( relationshipType ) && !StringUtils.isNullOrEmpty( relatesTo ) )
423 			{
424 				header = processWsaRelatesToProperty( header, override, wsaPrefix + ":RelatesTo", relationshipType,
425 						relatesTo );
426 			}
427 
428 			if( wsaContainer.getWsaConfig().isGenerateMessageId() )
429 			{
430 				String generatedMessageId = "uuid:" + UUID.randomUUID().toString();
431 				header = processWsaProperty( header, override, wsaPrefix + ":MessageID", generatedMessageId, false );
432 			}
433 			else
434 			{
435 				String msgId = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getMessageID() );
436 				if( !StringUtils.isNullOrEmpty( msgId ) )
437 				{
438 					header = processWsaProperty( header, override, wsaPrefix + ":MessageID", msgId, false );
439 				}
440 			}
441 
442 			if( httpMethod != null && wsaContainer.getWsaConfig().isAddDefaultTo() )
443 			{
444 				String defaultTo = httpMethod.getURI().toString();
445 				header = processWsaProperty( header, override, wsaPrefix + ":To", defaultTo, false );
446 			}
447 			else
448 			{
449 				String to = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getTo() );
450 				if( !StringUtils.isNullOrEmpty( to ) )
451 				{
452 					header = processWsaProperty( header, override, wsaPrefix + ":To", to, false );
453 				}
454 			}
455 			content = xmlContentObject.xmlText();
456 		}
457 		catch( Exception e )
458 		{
459 			SoapUI.logError( e );
460 		}
461 
462 		return content;
463 	}
464 
465 	/***
466 	 * Adds ws-a headers to mock response from editor-menu in this case there is
467 	 * no request included and only values from ws-a inspector, if any, are used
468 	 * 
469 	 * @param wsaContainer
470 	 * @return
471 	 */
472 	public String addWSAddressingMockResponse( WsaContainer wsaContainer )
473 	{
474 		return addWSAddressingMockResponse( wsaContainer, null );
475 	}
476 
477 	public String addWSAddressingMockResponse( WsaContainer wsaContainer, WsdlMockRequest request )
478 	{
479 		return createWSAddressingMockResponse( wsaContainer, request, SoapUI.getSettings().getBoolean(
480 				WsaSettings.OVERRIDE_EXISTING_HEADERS ) );
481 	}
482 
483 	private String createWSAddressingMockResponse( WsaContainer wsaContainer, WsdlMockRequest request, boolean override )
484 	{
485 		try
486 		{
487 			Element header = getHeader( wsaContainer );
488 
489 			if( override || wsaVersionNamespaceOld == null )
490 			{
491 				header.setAttribute( "xmlns:" + wsaPrefix, wsaVersionNameSpace );
492 			}
493 
494 			String action = null;
495 			if( wsaContainer.getWsaConfig().isAddDefaultAction() )
496 			{
497 				action = WsdlUtils.getDefaultWsaAction( wsaContainer.getOperation(), true );
498 			}
499 			else
500 			{
501 				action = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getAction() );
502 			}
503 			if( !StringUtils.isNullOrEmpty( action ) )
504 			{
505 				header = processWsaProperty( header, override, wsaPrefix + ":Action", action, false );
506 			}
507 
508 			if( AnonymousTypeConfig.REQUIRED.toString().equals( anonymousType ) )
509 			{
510 				header = processWsaProperty( header, override, wsaPrefix + ":ReplyTo", anonymousAddress, true );
511 			}
512 			else
513 			{
514 				String replyTo = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getReplyTo() );
515 				String replyToRefParams = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig()
516 						.getReplyToRefParams() );
517 				if( !StringUtils.isNullOrEmpty( replyTo ) )
518 				{
519 					header = processWsaProperty( header, override, wsaPrefix + ":ReplyTo", replyTo, true, replyToRefParams );
520 				}
521 			}
522 
523 			Element requestHeader = null;
524 			if( request != null )
525 			{
526 				XmlObject requestXmlObject = request.getRequestXmlObject();
527 
528 				String requestWsaVersionNameSpace = WsaValidator.getWsaVersion( requestXmlObject, request.getSoapVersion() );
529 
530 				requestHeader = ( Element )SoapUtils.getHeaderElement( requestXmlObject, request.getSoapVersion(), true )
531 						.getDomNode();
532 
533 				// request.messageId = mockResponse.relatesTo so get it
534 				Element msgNode = XmlUtils.getFirstChildElementNS( requestHeader, requestWsaVersionNameSpace, "MessageID" );
535 				String requestMessageId = null;
536 				if( msgNode != null )
537 				{
538 					requestMessageId = XmlUtils.getElementText( msgNode );
539 				}
540 
541 				String from = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getFrom() );
542 				if( !StringUtils.isNullOrEmpty( from ) )
543 				{
544 					header = processWsaProperty( header, override, wsaPrefix + ":From", from, true );
545 				}
546 				String faultTo = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getFaultTo() );
547 				String faultToRefParams = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig()
548 						.getFaultToRefParams() );
549 				if( !StringUtils.isNullOrEmpty( faultTo ) )
550 				{
551 					header = processWsaProperty( header, override, wsaPrefix + ":FaultTo", faultTo, true, faultToRefParams );
552 				}
553 
554 				String relationshipType = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig()
555 						.getRelationshipType() );
556 				if( !StringUtils.isNullOrEmpty( relationshipType ) )
557 				{
558 					if( !StringUtils.isNullOrEmpty( requestMessageId ) )
559 					{
560 						header = processWsaRelatesToProperty( header, override, wsaPrefix + ":RelatesTo", relationshipType,
561 								requestMessageId );
562 					}
563 					else if( SoapUI.getSettings().getBoolean( WsaSettings.USE_DEFAULT_RELATES_TO ) )
564 					{
565 						// if request.messageId not specified use
566 						// unspecifiedMessage
567 						header = processWsaRelatesToProperty( header, override, wsaPrefix + ":RelatesTo", relationshipType,
568 								unspecifiedMessage );
569 					}
570 				}
571 				else if( wsaContainer instanceof WsdlMockResponse )
572 				{
573 					if( SoapUI.getSettings().getBoolean( WsaSettings.USE_DEFAULT_RELATIONSHIP_TYPE ) )
574 					{
575 						if( !StringUtils.isNullOrEmpty( requestMessageId ) )
576 						{
577 							header = processWsaRelatesToProperty( header, override, wsaPrefix + ":RelatesTo",
578 									relationshipTypeReply, requestMessageId );
579 						}
580 						else if( SoapUI.getSettings().getBoolean( WsaSettings.USE_DEFAULT_RELATES_TO ) )
581 						{
582 							// if request.messageId not specified use
583 							// unspecifiedMessage
584 							header = processWsaRelatesToProperty( header, override, wsaPrefix + ":RelatesTo",
585 									relationshipTypeReply, unspecifiedMessage );
586 						}
587 					}
588 				}
589 
590 				// request.replyTo = mockResponse.to so get it
591 				Element replyToNode = XmlUtils
592 						.getFirstChildElementNS( requestHeader, requestWsaVersionNameSpace, "ReplyTo" );
593 				String requestReplyToValue = null;
594 				if( replyToNode != null )
595 				{
596 					Element replyToAddresseNode = XmlUtils.getFirstChildElementNS( replyToNode, requestWsaVersionNameSpace,
597 							"Address" );
598 					if( replyToAddresseNode != null )
599 					{
600 						requestReplyToValue = XmlUtils.getElementText( replyToAddresseNode );
601 					}
602 				}
603 
604 				String to = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getTo() );
605 				if( !StringUtils.isNullOrEmpty( to ) )
606 				{
607 					if( !( AnonymousTypeConfig.PROHIBITED.toString().equals( anonymousType ) && isAnonymousAddress( to,
608 							wsaVersionNameSpace ) ) )
609 					{
610 						header = processWsaProperty( header, override, wsaPrefix + ":To", to, false );
611 					}
612 				}
613 				else
614 				{
615 					// if to not specified but wsa:to mandatory get default
616 					// value
617 					if( !StringUtils.isNullOrEmpty( requestReplyToValue ) )
618 					{
619 						// if anonymous prohibited than default anonymous should
620 						// not
621 						// be added
622 						if( !( AnonymousTypeConfig.PROHIBITED.toString().equals( anonymousType ) && isAnonymousAddress(
623 								requestReplyToValue, wsaVersionNameSpace ) ) )
624 						{
625 							header = processWsaProperty( header, override, wsaPrefix + ":To", requestReplyToValue, false );
626 						}
627 					}
628 				}
629 			}
630 			else
631 			{
632 				String to = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getTo() );
633 				if( !StringUtils.isNullOrEmpty( to ) )
634 				{
635 					// header = removeWsaProperty(override, header, wsaPrefix +
636 					// ":To");
637 					// header.appendChild(builder.createWsaAddressChildElement(wsaPrefix
638 					// + ":To", envelopeElement, to));
639 					header = processWsaProperty( header, override, wsaPrefix + ":To", to, false );
640 				}
641 
642 				String relationshipType = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig()
643 						.getRelationshipType() );
644 				String relatesTo = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getRelatesTo() );
645 				if( !StringUtils.isNullOrEmpty( relationshipType ) && !StringUtils.isNullOrEmpty( relatesTo ) )
646 				{
647 					header = processWsaRelatesToProperty( header, override, wsaPrefix + ":RelatesTo", relationshipType,
648 							relatesTo );
649 				}
650 				else if( wsaContainer instanceof WsdlMockResponse )
651 				{
652 					if( SoapUI.getSettings().getBoolean( WsaSettings.USE_DEFAULT_RELATIONSHIP_TYPE ) )
653 					{
654 						if( !StringUtils.isNullOrEmpty( relatesTo ) )
655 						{
656 							header = processWsaRelatesToProperty( header, override, wsaPrefix + ":RelatesTo",
657 									relationshipTypeReply, relatesTo );
658 						}
659 						else if( SoapUI.getSettings().getBoolean( WsaSettings.USE_DEFAULT_RELATES_TO ) )
660 						{
661 							header = processWsaRelatesToProperty( header, override, wsaPrefix + ":RelatesTo",
662 									relationshipTypeReply, unspecifiedMessage );
663 						}
664 					}
665 				}
666 
667 			}
668 
669 			if( wsaContainer.getWsaConfig().isGenerateMessageId() )
670 			{
671 				String generatedMessageId = "uuid:" + UUID.randomUUID().toString();
672 				header = processWsaProperty( header, override, wsaPrefix + ":MessageID", generatedMessageId, false );
673 			}
674 			else
675 			{
676 				String msgId = PropertyExpander.expandProperties( context, wsaContainer.getWsaConfig().getMessageID() );
677 				if( !StringUtils.isNullOrEmpty( msgId ) )
678 				{
679 					header = processWsaProperty( header, override, wsaPrefix + ":MessageID", msgId, false );
680 				}
681 			}
682 
683 			content = xmlContentObject.xmlText();
684 		}
685 		catch( XmlException e )
686 		{
687 			SoapUI.logError( e );
688 		}
689 
690 		return content;
691 	}
692 
693 	public class WsaBuilder
694 	{
695 		private final String wsaVersionNameSpace;
696 		private final Boolean mustUnderstand;
697 
698 		public WsaBuilder( String wsaVersionNameSpace, Boolean mustUnderstand )
699 		{
700 			// TODO Auto-generated constructor stub
701 			this.wsaVersionNameSpace = wsaVersionNameSpace;
702 			this.mustUnderstand = mustUnderstand;
703 		}
704 
705 		public Element createWsaChildElement( String elementName, Element addToElement, String wsaProperty )
706 		{
707 			Element wsaElm = addToElement.getOwnerDocument().createElementNS( wsaVersionNameSpace, elementName );
708 			Text txtElm = addToElement.getOwnerDocument().createTextNode( wsaProperty );
709 			if( mustUnderstand != null )
710 			{
711 				wsaElm.setAttributeNS( soapVersion.getEnvelopeNamespace(), "mustUnderstand", mustUnderstand ? "1" : "0" );
712 			}
713 			wsaElm.appendChild( txtElm );
714 			return wsaElm;
715 		}
716 
717 		public Element createWsaAddressChildElement( String elementName, Element addToElement, String wsaProperty,
718 				String refParamsContent )
719 		{
720 			Document document = addToElement.getOwnerDocument();
721 			Element wsAddressElm = document.createElementNS( wsaVersionNameSpace, wsaPrefix + ":Address" );
722 			Element wsaElm = document.createElementNS( wsaVersionNameSpace, elementName );
723 			Text propertyContent = document.createTextNode( wsaProperty );
724 			if( mustUnderstand != null )
725 			{
726 				wsaElm.setAttributeNS( soapVersion.getEnvelopeNamespace(), "mustUnderstand", mustUnderstand ? "1" : "0" );
727 			}
728 			wsAddressElm.appendChild( propertyContent );
729 			wsaElm.appendChild( wsAddressElm );
730 
731 			try
732 			{
733 				if( refParamsContent != null )
734 				{
735 					// Text propertyRefParamsContent =
736 					// document.createTextNode(refParamsContent);
737 					Element refParamsElm = document
738 							.createElementNS( wsaVersionNameSpace, wsaPrefix + ":ReferenceParameters" );
739 					refParamsContent = "<dummy>" + refParamsContent + "</dummy>";
740 					Node xx = document.importNode( XmlUtils.parseXml( refParamsContent ).getDocumentElement(), true );
741 					NodeList xxList = xx.getChildNodes();
742 
743 					// refParamsElm.appendChild(propertyRefParamsContent);
744 					for( int i = 0; i < xxList.getLength(); i++ )
745 					{
746 						refParamsElm.appendChild( xxList.item( i ) );
747 					}
748 					wsaElm.appendChild( refParamsElm );
749 				}
750 			}
751 			catch( DOMException e )
752 			{
753 				// TODO Auto-generated catch block
754 				e.printStackTrace();
755 			}
756 			catch( IOException e )
757 			{
758 				// TODO Auto-generated catch block
759 				e.printStackTrace();
760 			}
761 			return wsaElm;
762 		}
763 
764 		public Element createRelatesToElement( String elementName, Element addToElement, String relationshipType,
765 				String relatesTo )
766 		{
767 			Element wsaElm = addToElement.getOwnerDocument().createElementNS( wsaVersionNameSpace, elementName );
768 			wsaElm.setAttribute( "RelationshipType", relationshipType );
769 			Text txtElm = addToElement.getOwnerDocument().createTextNode( relatesTo );
770 			if( mustUnderstand != null )
771 			{
772 				wsaElm.setAttributeNS( soapVersion.getEnvelopeNamespace(), "mustUnderstand", mustUnderstand ? "1" : "0" );
773 			}
774 			wsaElm.appendChild( txtElm );
775 			return wsaElm;
776 		}
777 	}
778 
779 	public static boolean isAnonymousAddress( String address, String wsaVersionNamespace )
780 	{
781 		return ( address.equals( wsaVersionNamespace + "/anonymous" ) ) ? true : false;
782 	}
783 
784 	public static boolean isNoneAddress( String address, String wsaVersionNamespace )
785 	{
786 		return ( address.equals( wsaVersionNamespace + "/none" ) ) ? true : false;
787 	}
788 
789 	public static String getNamespace( String Version )
790 	{
791 		if( Version.equals( WsaVersionTypeConfig.X_200408.toString() ) )
792 		{
793 			return WS_A_NAMESPACE_200408;
794 		}
795 		return WS_A_NAMESPACE_200508;
796 	}
797 }