1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl;
14
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19
20 import javax.swing.ImageIcon;
21 import javax.wsdl.Binding;
22 import javax.wsdl.BindingOperation;
23 import javax.wsdl.BindingOutput;
24 import javax.wsdl.Definition;
25 import javax.wsdl.Message;
26 import javax.wsdl.extensions.mime.MIMEContent;
27 import javax.wsdl.extensions.mime.MIMEMultipartRelated;
28 import javax.wsdl.extensions.mime.MIMEPart;
29 import javax.xml.namespace.QName;
30
31 import org.apache.log4j.Logger;
32 import org.apache.xmlbeans.SchemaType;
33
34 import com.eviware.soapui.SoapUI;
35 import com.eviware.soapui.config.CallConfig;
36 import com.eviware.soapui.config.OperationConfig;
37 import com.eviware.soapui.config.PartsConfig.Part;
38 import com.eviware.soapui.impl.wsdl.support.soap.SoapMessageBuilder;
39 import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
40 import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
41 import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils.SoapHeader;
42 import com.eviware.soapui.model.iface.MessagePart;
43 import com.eviware.soapui.model.iface.Operation;
44 import com.eviware.soapui.model.iface.Request;
45 import com.eviware.soapui.model.iface.MessagePart.FaultPart;
46 import com.eviware.soapui.support.UISupport;
47
48 /***
49 * WSDL implementation of Operation, maps to a WSDL BindingOperation
50 *
51 * @author Ole.Matzura
52 */
53
54 public class WsdlOperation extends AbstractWsdlModelItem<OperationConfig> implements Operation
55 {
56 public static final String STYLE_DOCUMENT = "Document";
57 public static final String STYLE_RPC = "RPC";
58
59 public final static Logger log = Logger.getLogger( WsdlOperation.class );
60 private List<WsdlRequest> requests = new ArrayList<WsdlRequest>();
61 private WsdlInterface iface;
62 private ImageIcon oneWayIcon;
63
64 public WsdlOperation( WsdlInterface iface, OperationConfig operationConfig )
65 {
66 super( operationConfig, iface, "/operation.gif" );
67 this.iface = iface;
68
69 if( operationConfig.isSetIsOneWay())
70 {
71 operationConfig.setIsOneWay( false );
72 }
73
74 List<CallConfig> requestConfigs = getConfig().getCallList();
75 for (CallConfig config : requestConfigs)
76 {
77 requests.add( new WsdlRequest( this, config));
78 }
79
80 oneWayIcon = UISupport.createImageIcon( "/onewayoperation.gif" );
81 }
82
83 public String getAction()
84 {
85 return getConfig().getAction();
86 }
87
88 public WsdlRequest getRequestAt(int index)
89 {
90 return requests.get( index );
91 }
92
93 public WsdlRequest getRequestByName(String requestName)
94 {
95 return (WsdlRequest) getWsdlModelItemByName( requests, requestName );
96 }
97
98 public int getRequestCount()
99 {
100 return requests.size();
101 }
102
103 public ImageIcon getIcon()
104 {
105 if( isOneWay() )
106 return oneWayIcon;
107 else
108 return super.getIcon();
109 }
110
111 public WsdlRequest addNewRequest( String name )
112 {
113 WsdlRequest requestImpl = new WsdlRequest( this, getConfig().addNewCall() );
114 requestImpl.setName( name );
115 requests.add( requestImpl );
116 ((WsdlInterface)getInterface()).fireRequestAdded( requestImpl );
117 return requestImpl;
118 }
119
120 public WsdlInterface getInterface()
121 {
122 return iface;
123 }
124
125 public void setAction(String soapAction)
126 {
127 String old = getAction();
128 getConfig().setAction( soapAction );
129 notifyPropertyChanged( ACTION_PROPERTY, old, soapAction );
130 }
131
132 public String createRequest( boolean buildOptional )
133 {
134 if( iface.getBindingName() == null )
135 {
136 UISupport.showErrorMessage( "Missing binding name, please try to refresh " +
137 "Interface\nfor request generation to work correctly" );
138 return null;
139 }
140
141 if( getBindingOperationName() == null )
142 {
143 UISupport.showErrorMessage( "Missing bindingOperation name, please try to refresh " +
144 "Interface\nfor request generation to work correctly" );
145 return null;
146 }
147
148 try
149 {
150 SoapMessageBuilder builder = (SoapMessageBuilder) iface.getMessageBuilder();
151 BindingOperation bindingOperation = findBindingOperation( iface.getWsdlContext().getDefinition() );
152
153 if( bindingOperation == null )
154 {
155 UISupport.showErrorMessage( "Failed to find bindingOperation, please try to refresh " +
156 "Interface\nfor request generation to work correctly" );
157 return null;
158 }
159
160 return builder.buildSoapRequest( bindingOperation, buildOptional );
161 }
162 catch (Exception e)
163 {
164 SoapUI.logError( e );
165 return null;
166 }
167 }
168
169 public String createResponse( boolean buildOptional )
170 {
171 if( iface.getBindingName() == null )
172 {
173 UISupport.showErrorMessage( "Missing binding name, please try to refresh " +
174 "Interface\nfor request generation to work correctly" );
175 return null;
176 }
177
178 if( getBindingOperationName() == null )
179 {
180 UISupport.showErrorMessage( "Missing bindingOperation name, please try to refresh " +
181 "Interface\nfor request generation to work correctly" );
182 return null;
183 }
184
185 try
186 {
187 SoapMessageBuilder builder = (SoapMessageBuilder) iface.getMessageBuilder();
188 BindingOperation bindingOperation = findBindingOperation( iface.getWsdlContext().getDefinition() );
189
190 if( bindingOperation == null )
191 {
192 UISupport.showErrorMessage( "Failed to find bindingOperation, please try to refresh " +
193 "Interface\nfor request generation to work correctly" );
194 return null;
195 }
196
197 return builder.buildSoapResponse( bindingOperation, buildOptional );
198 }
199 catch (Exception e)
200 {
201 SoapUI.logError( e );
202 return null;
203 }
204 }
205
206 public BindingOperation findBindingOperation(Definition definition)
207 {
208 Binding binding = definition.getBinding( iface.getBindingName() );
209 if( binding == null )
210 return null;
211
212 String inputName = getInputName();
213 String outputName = getOutputName();
214
215 if( inputName == null )
216 inputName = ":none";
217
218 if( outputName == null )
219 outputName = ":none";
220
221 BindingOperation result = binding.getBindingOperation( getConfig().getBindingOperationName(), inputName, outputName );
222
223 if( result == null && (inputName.equals( ":none" ) || outputName.equals( ":none" )))
224 {
225
226 result = binding.getBindingOperation( getConfig().getBindingOperationName(),
227 inputName.equals( ":none" ) ? null : inputName, outputName.equals( ":none" ) ? null : outputName );
228 }
229 return result;
230 }
231
232 public void removeRequest( WsdlRequest request )
233 {
234 int ix = requests.indexOf( request );
235 requests.remove( ix );
236
237 try
238 {
239 ((WsdlInterface)getInterface()).fireRequestRemoved( request );
240 }
241 finally
242 {
243 request.release();
244 getConfig().removeCall( ix );
245 }
246 }
247
248 public String getBindingOperationName()
249 {
250 return getConfig().getBindingOperationName();
251 }
252
253 public void setBindingOperationName( String name )
254 {
255 getConfig().setBindingOperationName( name );
256 }
257
258 public void setInputName( String name )
259 {
260 getConfig().setInputName( name );
261 }
262
263 public String getInputName()
264 {
265 String inputName = getConfig().getInputName();
266 return inputName == null || inputName.trim().length() == 0 ? null : inputName;
267 }
268
269 public void setOutputName( String name )
270 {
271 if( name == null )
272 {
273 if( getConfig().isSetOutputName() )
274 getConfig().unsetOutputName();
275 }
276 else
277 getConfig().setOutputName( name );
278 }
279
280 public String getOutputName()
281 {
282 String outputName = getConfig().getOutputName();
283 return outputName == null || outputName.trim().length() == 0 ? null : outputName;
284 }
285
286 public void setOneWay( boolean isOneWay )
287 {
288 getConfig().setIsOneWay( isOneWay );
289 }
290
291 public boolean isOneWay()
292 {
293 return getConfig().getIsOneWay();
294 }
295
296 public void initFromBindingOperation(BindingOperation operation, boolean notifyUpdate )
297 {
298 setAction( WsdlUtils.getSoapAction( operation ));
299 setName( operation.getOperation().getName() );
300 setBindingOperationName( operation.getName() );
301 setInputName( operation.getBindingInput().getName() );
302
303 BindingOutput bindingOutput = operation.getBindingOutput();
304
305
306 if( bindingOutput != null )
307 setOutputName( bindingOutput.getName() );
308 else
309 setOutputName( null );
310
311 setOneWay( bindingOutput == null );
312
313 initAttachments(operation);
314
315 if( notifyUpdate )
316 {
317 iface.fireOperationUpdated( this );
318 }
319 }
320
321 @SuppressWarnings("unchecked")
322 private void initAttachments(BindingOperation operation)
323 {
324 if( getConfig().isSetRequestParts() )
325 getConfig().unsetRequestParts();
326
327 if( getConfig().isSetResponseParts() )
328 getConfig().unsetResponseParts();
329
330 BindingOutput bindingOutput = operation.getBindingOutput();
331
332 if( bindingOutput != null )
333 {
334 MIMEMultipartRelated multipartOutput = (MIMEMultipartRelated) WsdlUtils.getExtensiblityElement(
335 bindingOutput.getExtensibilityElements(), MIMEMultipartRelated.class );
336
337 getConfig().setReceivesAttachments( multipartOutput != null );
338 if( multipartOutput != null )
339 {
340 List<MIMEPart> parts = multipartOutput.getMIMEParts();
341 Map<String,Part> partMap = new HashMap<String,Part>();
342
343 for( int c = 0; c < parts.size(); c++ )
344 {
345 List<MIMEContent> contentParts = WsdlUtils.getExtensiblityElements( parts.get(c).getExtensibilityElements(), MIMEContent.class );
346
347 for( MIMEContent content : contentParts )
348 {
349 Part part = partMap.get( content.getPart());
350 if( part != null )
351 {
352 if( !part.getContentTypeList().contains( content.getType() ))
353 part.addContentType( content.getType() );
354 }
355 else
356 {
357 if( !getConfig().isSetResponseParts() )
358 getConfig().addNewResponseParts();
359
360 Part responsePart = getConfig().getResponseParts().addNewPart();
361 responsePart.addContentType( content.getType() );
362 responsePart.setName( content.getPart() );
363
364 partMap.put( responsePart.getName(), responsePart );
365 }
366 }
367 }
368 }
369 }
370
371 MIMEMultipartRelated multipartInput = (MIMEMultipartRelated) WsdlUtils.getExtensiblityElement(
372 operation.getBindingInput().getExtensibilityElements(), MIMEMultipartRelated.class );
373
374 getConfig().setSendsAttachments( multipartInput != null );
375 if( multipartInput != null )
376 {
377 List<MIMEPart> parts = multipartInput.getMIMEParts();
378 Map<String,Part> partMap = new HashMap<String,Part>();
379
380 for( int c = 0; c < parts.size(); c++ )
381 {
382 List<MIMEContent> contentParts = WsdlUtils.getExtensiblityElements( parts.get(c).getExtensibilityElements(), MIMEContent.class );
383
384 for( MIMEContent content : contentParts )
385 {
386 Part part = partMap.get( content.getPart());
387 if( part != null )
388 {
389 if( !part.getContentTypeList().contains( content.getType() ))
390 part.addContentType( content.getType() );
391 }
392 else
393 {
394 if( !getConfig().isSetRequestParts() )
395 getConfig().addNewRequestParts();
396
397 Part requestPart = getConfig().getRequestParts().addNewPart();
398 requestPart.addContentType( content.getType() );
399 requestPart.setName( content.getPart() );
400
401 partMap.put( requestPart.getName(), requestPart );
402 }
403 }
404 }
405 }
406 }
407
408 public boolean getReceivesAttachments()
409 {
410 return getConfig().getReceivesAttachments();
411 }
412
413 public boolean getSendsAttachments()
414 {
415 return getConfig().getSendsAttachments();
416 }
417
418 @SuppressWarnings("unchecked")
419 public QName getRequestBodyElementQName() throws Exception
420 {
421 WsdlInterface iface = (WsdlInterface) getInterface();
422
423 Definition definition = iface.getWsdlContext().getDefinition();
424 BindingOperation bindingOperation = findBindingOperation( definition );
425 if( WsdlUtils.isRpc( definition, bindingOperation))
426 {
427 String ns = WsdlUtils.getSoapBodyNamespace( bindingOperation.getBindingInput().getExtensibilityElements() );
428 if( ns == null )
429 {
430 ns = definition.getTargetNamespace();
431 }
432
433 return new QName( ns, bindingOperation.getName() );
434 }
435 else
436 {
437 List<javax.wsdl.Part> parts = bindingOperation.getOperation().getInput().getMessage().getOrderedParts( null );
438 if( parts == null || parts.isEmpty() )
439 return null;
440
441 javax.wsdl.Part part = parts.get( 0 );
442
443 if( part.getElementName() != null )
444 {
445 return part.getElementName();
446 }
447 else
448 {
449 return new QName( definition.getTargetNamespace(), part.getName() );
450 }
451 }
452 }
453
454 @SuppressWarnings("unchecked")
455 public QName getResponseBodyElementQName() throws Exception
456 {
457 if( isOneWay() )
458 return null;
459
460 WsdlInterface iface = (WsdlInterface) getInterface();
461
462 Definition definition = iface.getWsdlContext().getDefinition();
463 BindingOperation bindingOperation = findBindingOperation( definition );
464 if( WsdlUtils.isRpc( definition, bindingOperation))
465 {
466 String ns = WsdlUtils.getSoapBodyNamespace( bindingOperation.getBindingOutput().getExtensibilityElements() );
467 if( ns == null )
468 {
469 ns = definition.getTargetNamespace();
470 }
471
472 return new QName( ns, bindingOperation.getName() + "Response" );
473 }
474 else
475 {
476 List<javax.wsdl.Part> parts = bindingOperation.getOperation().getOutput().getMessage().getOrderedParts( null );
477 if( parts == null || parts.isEmpty() )
478 return null;
479
480 javax.wsdl.Part part = parts.get( 0 );
481
482 if( part.getElementName() != null )
483 {
484 return part.getElementName();
485 }
486 else
487 {
488 return new QName( definition.getTargetNamespace(), part.getName() );
489 }
490 }
491 }
492
493 public String getStyle()
494 {
495 WsdlContext wsdlContext = iface.getWsdlContext();
496 if( !wsdlContext.isLoaded() )
497 return "<not loaded>";
498
499 try
500 {
501 Definition definition = wsdlContext.getDefinition();
502 BindingOperation bindingOperation = findBindingOperation( definition);
503
504 if( bindingOperation == null )
505 return "<missing bindingOperation>";
506
507 if( WsdlUtils.isRpc( definition, bindingOperation ))
508 {
509 return WsdlOperation.STYLE_RPC;
510 }
511 else
512 {
513 return WsdlOperation.STYLE_DOCUMENT;
514 }
515 }
516 catch (Exception e)
517 {
518 SoapUI.logError( e );
519 return "<error>";
520 }
521 }
522
523 public void release()
524 {
525 super.release();
526
527 for( WsdlRequest request : requests )
528 request.release();
529 }
530
531 public BindingOperation getBindingOperation()
532 {
533 try
534 {
535 return findBindingOperation( ((WsdlInterface)getInterface()).getWsdlContext().getDefinition() );
536 }
537 catch( Exception e )
538 {
539 SoapUI.logError( e );
540 return null;
541 }
542 }
543
544 public List<Request> getRequests()
545 {
546 return new ArrayList<Request>( requests );
547 }
548
549 public MessagePart[] getDefaultRequestParts()
550 {
551 try
552 {
553
554 List<MessagePart> result = new ArrayList<MessagePart>();
555 WsdlContext wsdlContext = getInterface().getWsdlContext();
556 BindingOperation bindingOperation = findBindingOperation(wsdlContext.getDefinition());
557
558 if( bindingOperation == null )
559 return new MessagePart[0];
560
561
562 List<SoapHeader> headers = WsdlUtils.getSoapHeaders( bindingOperation.getBindingInput()
563 .getExtensibilityElements());
564
565 for (int i = 0; i < headers.size(); i++)
566 {
567 SoapHeader header = headers.get( i );
568
569 Message message = wsdlContext.getDefinition().getMessage( header.getMessage() );
570 if( message == null )
571 {
572 log.error( "Missing message for header: " + header.getMessage() );
573 continue;
574 }
575
576 javax.wsdl.Part part = message.getPart( header.getPart() );
577
578 if( part != null )
579 {
580 SchemaType schemaType = WsdlUtils.getSchemaTypeForPart( wsdlContext, part );
581 if( schemaType != null )
582 result.add( new WsdlHeaderPart( part.getName(), schemaType, part.getElementName() ));
583 }
584 else
585 log.error( "Missing part for header; " + header.getPart() );
586 }
587
588
589 javax.wsdl.Part[] parts = WsdlUtils.getInputParts( bindingOperation );
590
591 for( int i = 0; i < parts.length; i++ )
592 {
593 javax.wsdl.Part part = parts[i];
594
595 if( !WsdlUtils.isAttachmentInputPart( part, bindingOperation ))
596 {
597 SchemaType schemaType = WsdlUtils.getSchemaTypeForPart( wsdlContext, part );
598 if( schemaType != null )
599 result.add( new WsdlContentPart( part.getName(), schemaType, part.getElementName() ));
600 }
601 }
602
603 return result.toArray( new MessagePart[result.size()] );
604 }
605 catch (Exception e)
606 {
607 SoapUI.logError( e );
608 return new MessagePart [0];
609 }
610 }
611
612 public MessagePart[] getDefaultResponseParts()
613 {
614 try
615 {
616
617 List<MessagePart> result = new ArrayList<MessagePart>();
618 WsdlContext wsdlContext = getInterface().getWsdlContext();
619 BindingOperation bindingOperation = findBindingOperation(wsdlContext.getDefinition());
620
621 if( bindingOperation == null )
622 return new MessagePart[0];
623
624
625 List<SoapHeader> headers = WsdlUtils.getSoapHeaders( bindingOperation.getBindingOutput()
626 .getExtensibilityElements());
627
628 for (int i = 0; i < headers.size(); i++)
629 {
630 SoapHeader header = headers.get( i );
631
632 Message message = wsdlContext.getDefinition().getMessage( header.getMessage() );
633 if( message == null )
634 {
635 log.error( "Missing message for header: " + header.getMessage() );
636 continue;
637 }
638
639 javax.wsdl.Part part = message.getPart( header.getPart() );
640
641 if( part != null )
642 {
643 SchemaType schemaType = WsdlUtils.getSchemaTypeForPart( wsdlContext, part );
644 if( schemaType != null )
645 result.add( new WsdlHeaderPart( part.getName(), schemaType, part.getElementName() ));
646 }
647 else
648 log.error( "Missing part for header; " + header.getPart() );
649 }
650
651
652 javax.wsdl.Part[] parts = WsdlUtils.getOutputParts( bindingOperation );
653
654 for( int i = 0; i < parts.length; i++ )
655 {
656 javax.wsdl.Part part = parts[i];
657
658 if( !WsdlUtils.isAttachmentOutputPart( part, bindingOperation ))
659 {
660 SchemaType schemaType = WsdlUtils.getSchemaTypeForPart( wsdlContext, part );
661 if( schemaType != null )
662 result.add( new WsdlContentPart( part.getName(), schemaType, part.getElementName() ));
663 }
664 }
665
666 return result.toArray( new MessagePart[result.size()] );
667 }
668 catch (Exception e)
669 {
670 SoapUI.logError( e );
671 return new MessagePart [0];
672 }
673 }
674
675 public MessagePart [] getFaultParts()
676 {
677 BindingOperation bindingOperation = getBindingOperation();
678 Map bindingFaults = bindingOperation.getBindingFaults();
679
680 List<MessagePart> result = new ArrayList<MessagePart>();
681 for( Object key : bindingFaults.keySet() )
682 {
683 result.add( new WsdlFaultPart( (String)key ));
684 }
685
686 return result.toArray( new MessagePart[result.size()] );
687 }
688
689 private class WsdlFaultPart extends FaultPart
690 {
691 private final String name;
692
693 public WsdlFaultPart( String name )
694 {
695 this.name = name;
696 }
697
698 @Override
699 public javax.wsdl.Part[] getWsdlParts()
700 {
701 try
702 {
703 return WsdlUtils.getFaultParts( getBindingOperation(), name );
704 }
705 catch( Exception e )
706 {
707 log.error( e.toString(), e );
708 }
709
710 return new javax.wsdl.Part[0];
711 }
712
713 @Override
714 public QName getPartElement()
715 {
716 return null;
717 }
718
719 public String getDescription()
720 {
721 return null;
722 }
723
724 public String getName()
725 {
726 return name;
727 }
728
729 @Override
730 public SchemaType getSchemaType()
731 {
732 return null;
733 }}
734
735 @Override
736 public void onSave()
737 {
738 for( WsdlRequest request : requests )
739 request.onSave();
740 }
741 }