1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.support.wsa;
14
15 import com.eviware.soapui.SoapUI;
16 import com.eviware.soapui.config.AnonymousTypeConfig;
17 import com.eviware.soapui.config.MustUnderstandTypeConfig;
18 import com.eviware.soapui.config.WsaVersionTypeConfig;
19 import com.eviware.soapui.impl.wsdl.WsdlOperation;
20 import com.eviware.soapui.impl.wsdl.mock.WsdlMockRequest;
21 import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse;
22 import com.eviware.soapui.impl.wsdl.submit.transports.http.ExtendedHttpMethod;
23 import com.eviware.soapui.impl.wsdl.support.soap.SoapUtils;
24 import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
25 import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
26 import com.eviware.soapui.settings.WsaSettings;
27 import com.eviware.soapui.support.StringUtils;
28 import com.eviware.soapui.support.xml.XmlUtils;
29 import org.apache.xmlbeans.XmlException;
30 import org.apache.xmlbeans.XmlObject;
31 import org.w3c.dom.Element;
32 import org.w3c.dom.Node;
33 import org.w3c.dom.NodeList;
34 import org.w3c.dom.Text;
35
36 import java.util.ArrayList;
37 import java.util.Iterator;
38 import java.util.UUID;
39
40 /***
41 * WS Addressing-related utility-methods..
42 *
43 * @author dragica.soldo
44 */
45
46 public class WsaUtils
47 {
48 public static final String WS_A_VERSION_200508 = "http://www.w3.org/2005/08/addressing";
49 public static final String WS_A_VERSION_200408 = "http://schemas.xmlsoap.org/ws/2004/08/addressing";
50 public static final String WSAM_NAMESPACE = "http://www.w3.org/2007/05/addressing/metadata";
51
52 SoapVersion soapVersion;
53 WsdlOperation operation;
54 WsaBuilder builder;
55 XmlObject xmlContentObject;
56
57 Element envelopeElement;
58 String wsaVersionNameSpace;
59 String anonymousType;
60 String anonymousAddress;
61 String noneAddress;
62 String relationshipTypeReply;
63
64 String unspecifiedMessage;
65 String content;
66
67 XmlObject xmlHeaderObject;
68 ArrayList<Node> headerWsaElementList;
69
70 public WsaUtils(String content, SoapVersion soapVersion, WsdlOperation operation)
71 {
72 this.soapVersion = soapVersion;
73 this.operation = operation;
74 this.content = content;
75 try
76 {
77 xmlContentObject = XmlObject.Factory.parse(content);
78 }
79 catch (Exception e)
80 {
81 SoapUI.logError(e);
82 }
83 }
84
85 public Element addWsAddressingCommon(WsaContainer wsaContainer, boolean overrideExisting) throws XmlException
86 {
87
88
89 wsaVersionNameSpace = WS_A_VERSION_200508;
90 if (wsaContainer.getWsaConfig().getVersion().equals(WsaVersionTypeConfig.X_200408.toString()))
91 {
92 wsaVersionNameSpace = WS_A_VERSION_200408;
93 }
94 anonymousAddress = wsaVersionNameSpace + "/anonymous";
95 noneAddress = wsaVersionNameSpace + "/none";
96 relationshipTypeReply = wsaVersionNameSpace + "/reply";
97 unspecifiedMessage = wsaVersionNameSpace + "/unspecified";
98
99 anonymousType = wsaContainer.getOperation().getAnonymous();
100
101
102 if (anonymousType.equals(AnonymousTypeConfig.OPTIONAL.toString()))
103 {
104 anonymousType = wsaContainer.getOperation().getInterface().getAnonymous();
105 }
106
107 Element header = (Element) SoapUtils.getHeaderElement(xmlContentObject, soapVersion, true).getDomNode();
108
109 header.setAttribute("xmlns:wsa", wsaVersionNameSpace);
110
111 XmlObject[] envelope = xmlContentObject.selectChildren(soapVersion.getEnvelopeQName());
112 envelopeElement = (Element) envelope[0].getDomNode();
113
114 Boolean mustUnderstand = null;
115 if (wsaContainer.getWsaConfig().getMustUnderstand().equals(MustUnderstandTypeConfig.FALSE.toString()))
116 {
117 mustUnderstand = false;
118 }
119 else if (wsaContainer.getWsaConfig().getMustUnderstand().equals(MustUnderstandTypeConfig.TRUE.toString()))
120 {
121 mustUnderstand = true;
122 }
123
124 builder = new WsaBuilder(wsaVersionNameSpace, mustUnderstand);
125
126 String from = wsaContainer.getWsaConfig().getFrom();
127 if (!StringUtils.isNullOrEmpty(from))
128 {
129 header = processWsaProperty(header, overrideExisting, "wsa:From", from, true);
130 }
131 String faultTo = wsaContainer.getWsaConfig().getFaultTo();
132 if (!StringUtils.isNullOrEmpty(faultTo))
133 {
134 header = processWsaProperty(header, overrideExisting, "wsa:FaultTo", faultTo, true);
135 }
136 return header;
137
138 }
139
140 private Node getWsaProperty(Element header, String elementLocalName) {
141 NodeList elmList = header.getElementsByTagName(elementLocalName);
142 Node elm = null;
143 if (elmList.getLength() > 0)
144 {
145 elm = elmList.item(0);
146 }
147 return elm;
148
149 }
150 private Element removeWsaProperty(boolean overrideExisting, Element header, String elementLocalName)
151 {
152 if (overrideExisting)
153 {
154 NodeList elmList = header.getElementsByTagName(elementLocalName);
155 Node elm = null;
156 if (elmList.getLength() > 0)
157 {
158 elm = elmList.item(0);
159 }
160 if (elm != null)
161 {
162 header.removeChild(elm);
163 }
164 }
165 return header;
166 }
167 private Element processWsaProperty(Element header, boolean override, String elementLocalName, String wsaPropValue, boolean address) {
168 boolean existsWsa = getWsaProperty(header, elementLocalName)!= null ? true: false;
169 if (override)
170 {
171 if (existsWsa)
172 {
173 header = removeWsaProperty(override, header, elementLocalName);
174 }
175 if (address)
176 {
177 header.appendChild(builder.createWsaAddressChildElement(elementLocalName, envelopeElement, wsaPropValue));
178 } else {
179 header.appendChild(builder.createWsaChildElement(elementLocalName, envelopeElement, wsaPropValue));
180 }
181
182 } else if (!existsWsa)
183 {
184 if (address)
185 {
186 header.appendChild(builder.createWsaAddressChildElement(elementLocalName, envelopeElement, wsaPropValue));
187 } else {
188 header.appendChild(builder.createWsaChildElement(elementLocalName, envelopeElement, wsaPropValue));
189 }
190 }
191 return header;
192 }
193
194 private Element processWsaRelatesToProperty(Element header, boolean override, String elementLocalName, String relationshipType,
195 String relatesTo) {
196 boolean existsWsa = getWsaProperty(header, elementLocalName)!= null ? true: false;
197 if (override)
198 {
199 if (existsWsa)
200 {
201 header = removeWsaProperty(override, header, elementLocalName);
202 }
203 header.appendChild(builder.createRelatesToElement("wsa:RelatesTo", envelopeElement, relationshipType,
204 relatesTo));
205 } else if (!existsWsa)
206 {
207 header.appendChild(builder.createRelatesToElement("wsa:RelatesTo", envelopeElement, relationshipType,
208 relatesTo));
209 }
210 return header;
211 }
212
213 public String addWSAddressingRequest(WsaContainer wsaContainer)
214 {
215 return addWSAddressingRequest(wsaContainer, null);
216 }
217
218 public String addWSAddressingRequest(WsaContainer wsaContainer, ExtendedHttpMethod httpMethod)
219 {
220 return createNewWSAddressingRequest(wsaContainer, httpMethod, SoapUI.getSettings().getBoolean(WsaSettings.OVERRIDE_EXISTING_HEADERS));
221 }
222
223 private String createNewWSAddressingRequest(WsaContainer wsaContainer, ExtendedHttpMethod httpMethod, boolean override)
224 {
225 try
226 {
227 Element header = addWsAddressingCommon(wsaContainer, override);
228
229 String action = wsaContainer.getWsaConfig().getAction();
230 if (SoapUI.getSettings().getBoolean(WsaSettings.USE_DEFAULT_ACTION) && StringUtils.isNullOrEmpty(action))
231 {
232 action = WsdlUtils.getDefaultWsaAction(wsaContainer.getOperation(), false);
233 }
234
235 if (!StringUtils.isNullOrEmpty(action))
236 {
237 header = processWsaProperty(header, override, "wsa:Action", action, false);
238 }
239
240 String replyTo = wsaContainer.getWsaConfig().getReplyTo();
241 if (AnonymousTypeConfig.REQUIRED.toString().equals(anonymousType))
242
243
244
245 {
246 header = processWsaProperty(header, override, "wsa:ReplyTo", anonymousAddress, true);
247 }
248 else if (!StringUtils.isNullOrEmpty(replyTo))
249 {
250 if (!(AnonymousTypeConfig.PROHIBITED.toString().equals(anonymousType) && isAnonymousAddress(replyTo,wsaVersionNameSpace)))
251 {
252 header = processWsaProperty(header, override, "wsa:ReplyTo", replyTo, true);
253 }
254 }
255 else if (operation.isRequestResponse())
256 {
257
258 if (!AnonymousTypeConfig.PROHIBITED.toString().equals(anonymousType))
259 {
260 header = processWsaProperty(header, override, "wsa:ReplyTo", anonymousAddress, true);
261 } else {
262 header = processWsaProperty(header, override, "wsa:ReplyTo", noneAddress, true);
263 }
264 }
265
266 String relatesTo = wsaContainer.getWsaConfig().getRelatesTo();
267 String relationshipType = wsaContainer.getWsaConfig().getRelationshipType();
268 if (!StringUtils.isNullOrEmpty(relationshipType) && !StringUtils.isNullOrEmpty(relatesTo))
269 {
270 header = processWsaRelatesToProperty(header, override, "wsa:RelatesTo", relationshipType, relatesTo);
271 }
272
273 String msgId = wsaContainer.getWsaConfig().getMessageID();
274 if (!StringUtils.isNullOrEmpty(msgId))
275 {
276 header = processWsaProperty(header, override, "wsa:MessageID", msgId, false);
277 }
278 else if (operation.isRequestResponse() && SoapUI.getSettings().getBoolean(WsaSettings.GENERATE_MESSAGE_ID))
279 {
280
281 String generatedMessageId = UUID.randomUUID().toString();
282 header = processWsaProperty(header, override, "wsa:MessageID", generatedMessageId, false);
283 }
284
285 String to = wsaContainer.getWsaConfig().getTo();
286 if (!StringUtils.isNullOrEmpty(to))
287 {
288 header = processWsaProperty(header, override, "wsa:To", to, true);
289 }
290 else if (operation.isOneWay() || operation.isRequestResponse())
291 {
292 if (httpMethod != null)
293 {
294
295 String defaultTo = httpMethod.getURI().toString();
296 header = processWsaProperty(header, override, "wsa:To", defaultTo, true);
297 }
298 }
299
300 content = xmlContentObject.xmlText();
301 }
302 catch (Exception e)
303 {
304 SoapUI.logError(e);
305 }
306
307 return content;
308 }
309
310 /***
311 * Adds ws-a headers to mock response from editor-menu in this case there is
312 * no request included and only values from ws-a inspector, if any, are used
313 *
314 * @param wsaContainer
315 * @return
316 */
317 public String addWSAddressingMockResponse(WsaContainer wsaContainer)
318 {
319 return addWSAddressingMockResponse(wsaContainer, null);
320 }
321
322 public String addWSAddressingMockResponse(WsaContainer wsaContainer, WsdlMockRequest request)
323 {
324 return createWSAddressingMockResponse(wsaContainer, request, SoapUI.getSettings().getBoolean(WsaSettings.OVERRIDE_EXISTING_HEADERS));
325 }
326
327 private String createWSAddressingMockResponse(WsaContainer wsaContainer, WsdlMockRequest request, boolean override)
328 {
329 try
330 {
331 Element header = addWsAddressingCommon(wsaContainer, override);
332
333 String action = wsaContainer.getWsaConfig().getAction();
334 if (SoapUI.getSettings().getBoolean(WsaSettings.USE_DEFAULT_ACTION) && StringUtils.isNullOrEmpty(action))
335 {
336 action = WsdlUtils.getDefaultWsaAction(wsaContainer.getOperation(), true);
337 }
338 if (!StringUtils.isNullOrEmpty(action))
339 {
340 header = processWsaProperty(header, override, "wsa:Action", action, false);
341 }
342
343 if (AnonymousTypeConfig.REQUIRED.toString().equals(anonymousType))
344 {
345 header = processWsaProperty(header, override, "wsa:ReplyTo", anonymousAddress, true);
346 }
347 else
348 {
349 String replyTo = wsaContainer.getWsaConfig().getReplyTo();
350 if (!StringUtils.isNullOrEmpty(replyTo))
351 {
352 header = processWsaProperty(header, override, "wsa:ReplyTo", replyTo, true);
353 }
354 }
355
356 Element requestHeader = null;
357 if (request != null)
358 {
359 XmlObject requestXmlObject = request.getRequestXmlObject();
360 requestHeader = (Element) SoapUtils.getHeaderElement(requestXmlObject, request.getSoapVersion(), true)
361 .getDomNode();
362
363
364 Element msgNode = XmlUtils.getFirstChildElementNS(requestHeader, wsaVersionNameSpace, "MessageID");
365 String requestMessageId = null;
366 if (msgNode != null)
367 {
368 requestMessageId = XmlUtils.getElementText(msgNode);
369 }
370
371 String relationshipType = wsaContainer.getWsaConfig().getRelationshipType();
372 if (!StringUtils.isNullOrEmpty(relationshipType))
373 {
374 if (!StringUtils.isNullOrEmpty(requestMessageId))
375 {
376 header = processWsaRelatesToProperty(header, override, "wsa:RelatesTo", relationshipType, requestMessageId);
377 }
378 else if (SoapUI.getSettings().getBoolean(WsaSettings.USE_DEFAULT_RELATES_TO))
379 {
380
381 header = processWsaRelatesToProperty(header, override, "wsa:RelatesTo", relationshipType, unspecifiedMessage);
382 }
383 }
384 else if (wsaContainer instanceof WsdlMockResponse)
385 {
386 if (SoapUI.getSettings().getBoolean(WsaSettings.USE_DEFAULT_RELATIONSHIP_TYPE))
387 {
388 if (!StringUtils.isNullOrEmpty(requestMessageId))
389 {
390 header = removeWsaProperty(override, header, "wsa:RelatesTo");
391 header.appendChild(builder.createRelatesToElement("wsa:RelatesTo", envelopeElement,
392 relationshipTypeReply, requestMessageId));
393 }
394 else if (SoapUI.getSettings().getBoolean(WsaSettings.USE_DEFAULT_RELATES_TO))
395 {
396
397
398 header = processWsaRelatesToProperty(header, override, "wsa:RelatesTo", relationshipTypeReply, unspecifiedMessage);
399 }
400 }
401 }
402
403
404 Element replyToNode = XmlUtils.getFirstChildElementNS(requestHeader, wsaVersionNameSpace, "ReplyTo");
405 String requestReplyToValue = null;
406 if (replyToNode != null)
407 {
408 Element replyToAddresseNode = XmlUtils.getFirstChildElementNS(replyToNode, wsaVersionNameSpace,
409 "Address");
410 if (replyToAddresseNode != null)
411 {
412 requestReplyToValue = XmlUtils.getElementText(replyToAddresseNode);
413 }
414 }
415
416 String to = wsaContainer.getWsaConfig().getTo();
417 if (!StringUtils.isNullOrEmpty(to))
418 {
419 if (!(AnonymousTypeConfig.PROHIBITED.toString().equals(anonymousType) && isAnonymousAddress(to,wsaVersionNameSpace)))
420 {
421 header = processWsaProperty(header, override, "wsa:To", to, true);
422 }
423 }
424 else
425 {
426
427 if (!StringUtils.isNullOrEmpty(requestReplyToValue))
428 {
429
430
431 if (!(AnonymousTypeConfig.PROHIBITED.toString().equals(anonymousType) && isAnonymousAddress(requestReplyToValue,wsaVersionNameSpace)))
432 {
433 header = processWsaProperty(header, override, "wsa:To", requestReplyToValue, true);
434 }
435 }
436 }
437 }
438 else
439 {
440 String to = wsaContainer.getWsaConfig().getTo();
441 if (!StringUtils.isNullOrEmpty(to))
442 {
443 header = removeWsaProperty(override, header, "wsa:To");
444 header.appendChild(builder.createWsaAddressChildElement("wsa:To", envelopeElement, to));
445 }
446
447 String relationshipType = wsaContainer.getWsaConfig().getRelationshipType();
448 String relatesTo = wsaContainer.getWsaConfig().getRelatesTo();
449 if (!StringUtils.isNullOrEmpty(relationshipType) && !StringUtils.isNullOrEmpty(relatesTo))
450 {
451 header = processWsaRelatesToProperty(header, override, "wsa:RelatesTo", relationshipType, relatesTo);
452 }
453 else if (wsaContainer instanceof WsdlMockResponse)
454 {
455 if (SoapUI.getSettings().getBoolean(WsaSettings.USE_DEFAULT_RELATIONSHIP_TYPE))
456 {
457 if (!StringUtils.isNullOrEmpty(relatesTo))
458 {
459 header = processWsaRelatesToProperty(header, override, "wsa:RelatesTo", relationshipTypeReply, relatesTo);
460 } else if (SoapUI.getSettings().getBoolean(WsaSettings.USE_DEFAULT_RELATES_TO))
461 {
462 header = processWsaRelatesToProperty(header, override, "wsa:RelatesTo", relationshipTypeReply, unspecifiedMessage);
463 }
464 }
465 }
466
467 }
468
469 String msgId = wsaContainer.getWsaConfig().getMessageID();
470 if (!StringUtils.isNullOrEmpty(msgId))
471 {
472 header = processWsaProperty(header, override, "wsa:MessageID", msgId, false);
473 }
474
475 content = xmlContentObject.xmlText();
476 }
477 catch (XmlException e)
478 {
479 SoapUI.logError(e);
480 }
481
482 return content;
483 }
484
485 public class WsaBuilder
486 {
487 private final String wsaVersionNameSpace;
488 private final Boolean mustUnderstand;
489
490 public WsaBuilder(String wsaVersionNameSpace, Boolean mustUnderstand)
491 {
492
493 this.wsaVersionNameSpace = wsaVersionNameSpace;
494 this.mustUnderstand = mustUnderstand;
495 }
496
497 public Element createWsaChildElement(String elementName, Element addToElement, String wsaProperty)
498 {
499 Element wsaElm = addToElement.getOwnerDocument().createElementNS(wsaVersionNameSpace, elementName);
500 Text txtElm = addToElement.getOwnerDocument().createTextNode(wsaProperty);
501 if (mustUnderstand != null)
502 {
503 wsaElm.setAttributeNS(soapVersion.getEnvelopeNamespace(), "mustUnderstand", mustUnderstand ? "1" : "0");
504 }
505 wsaElm.appendChild(txtElm);
506 return wsaElm;
507 }
508
509 public Element createWsaAddressChildElement(String elementName, Element addToElement, String wsaProperty)
510 {
511 Element wsAddressElm = addToElement.getOwnerDocument().createElementNS(wsaVersionNameSpace, "wsa:Address");
512 Element wsaElm = addToElement.getOwnerDocument().createElementNS(wsaVersionNameSpace, elementName);
513 Text txtElm = addToElement.getOwnerDocument().createTextNode(wsaProperty);
514 if (mustUnderstand != null)
515 {
516 wsaElm.setAttributeNS(soapVersion.getEnvelopeNamespace(), "mustUnderstand", mustUnderstand ? "1" : "0");
517 }
518 wsAddressElm.appendChild(txtElm);
519 wsaElm.appendChild(wsAddressElm);
520 return wsaElm;
521 }
522
523 public Element createRelatesToElement(String elementName, Element addToElement, String relationshipType,
524 String relatesTo)
525 {
526 Element wsAddressElm = addToElement.getOwnerDocument().createElementNS(wsaVersionNameSpace, "wsa:Address");
527 Element wsaElm = addToElement.getOwnerDocument().createElementNS(wsaVersionNameSpace, elementName);
528 wsaElm.setAttribute("RelationshipType", relationshipType);
529 Text txtElm = addToElement.getOwnerDocument().createTextNode(relatesTo);
530 if (mustUnderstand != null)
531 {
532 wsaElm.setAttributeNS(soapVersion.getEnvelopeNamespace(), "mustUnderstand", mustUnderstand ? "1" : "0");
533 }
534 wsAddressElm.appendChild(txtElm);
535 wsaElm.appendChild(wsAddressElm);
536 return wsaElm;
537 }
538 }
539
540 private boolean getExistingWsAddressing(String content)
541 {
542 boolean appliedWsAddressing = false;
543 try
544 {
545 xmlHeaderObject = (XmlObject) SoapUtils.getHeaderElement(xmlContentObject, soapVersion, true);
546 String currentWsaVersionNameSpace = ((Element) xmlHeaderObject.getDomNode()).getAttribute("xmlns:wsa");
547 NodeList headerElements = ((Element) xmlHeaderObject.getDomNode()).getChildNodes();
548 headerWsaElementList = new ArrayList<Node>();
549 for (int i = 0; i < headerElements.getLength(); i++)
550 {
551 Node childNode = headerElements.item(i);
552 String namespaceURI = childNode.getNamespaceURI();
553 if (!StringUtils.isNullOrEmpty(namespaceURI) && namespaceURI.equals(currentWsaVersionNameSpace))
554 {
555 headerWsaElementList.add(childNode);
556 }
557 }
558 if (headerWsaElementList.size() > 0)
559 {
560 appliedWsAddressing = true;
561 }
562 }
563 catch (XmlException e)
564 {
565 SoapUI.logError(e);
566 }
567 return appliedWsAddressing;
568 }
569
570 private String cleanExistingWsaHeaders(String content)
571 {
572 Iterator<Node> iter = headerWsaElementList.iterator();
573 while (iter.hasNext())
574 {
575 ((Element) xmlHeaderObject.getDomNode()).removeChild((Node) iter.next());
576
577 }
578
579 ((Element) xmlHeaderObject.getDomNode()).removeAttribute("xmlns:wsa");
580
581 content = xmlContentObject.xmlText();
582
583 return content;
584 }
585
586 public static boolean isAnonymousAddress(String address, String wsaVersionNamespace)
587 {
588 return (address.equals(wsaVersionNamespace + "/anonymous")) ? true : false;
589 }
590
591 public static boolean isNoneAddress(String address, String wsaVersionNamespace)
592 {
593 return (address.equals(wsaVersionNamespace + "/none")) ? true : false;
594 }
595
596 }