View Javadoc

1   /*
2    *  soapUI, copyright (C) 2006 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
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;
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.extensions.mime.MIMEContent;
26  import javax.wsdl.extensions.mime.MIMEMultipartRelated;
27  import javax.wsdl.extensions.mime.MIMEPart;
28  import javax.xml.namespace.QName;
29  
30  import org.apache.xmlbeans.SchemaType;
31  
32  import com.eviware.soapui.config.CallConfig;
33  import com.eviware.soapui.config.OperationConfig;
34  import com.eviware.soapui.config.PartsConfig.Part;
35  import com.eviware.soapui.impl.wsdl.actions.operation.AddToMockServiceAction;
36  import com.eviware.soapui.impl.wsdl.actions.operation.NewRequestAction;
37  import com.eviware.soapui.impl.wsdl.actions.operation.RelabelOperationAction;
38  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
39  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
40  import com.eviware.soapui.impl.wsdl.support.soap.SoapMessageBuilder;
41  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
42  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
43  import com.eviware.soapui.model.iface.MessagePart;
44  import com.eviware.soapui.model.iface.Operation;
45  import com.eviware.soapui.model.iface.Request;
46  import com.eviware.soapui.model.iface.MessagePart.FaultPart;
47  import com.eviware.soapui.support.UISupport;
48  import com.eviware.soapui.support.action.ActionSupport;
49  
50  /***
51   * WSDL implementation of Operation, maps to a WSDL BindingOperation
52   * 
53   * @author Ole.Matzura
54   */
55  
56  public class WsdlOperation extends AbstractWsdlModelItem<OperationConfig> implements Operation
57  {
58     public static final String STYLE_DOCUMENT = "Document";
59  	public static final String STYLE_RPC = "RPC";
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        addAction( new AddToMockServiceAction( this ));
81  //      addAction( new AddAsMockResponseStepAction(this));
82        addAction( ActionSupport.SEPARATOR_ACTION );
83        addAction( new NewRequestAction( this ));
84        addAction( new RelabelOperationAction( this ));
85        addAction( ActionSupport.SEPARATOR_ACTION );
86        addAction( new ShowOnlineHelpAction( HelpUrls.OPERATION_HELP_URL ));
87        
88        oneWayIcon = UISupport.createImageIcon( "/onewayoperation.gif" );
89     }
90     
91  	public String getAction()
92     {
93        return getConfig().getAction();
94     }
95  
96     public WsdlRequest getRequestAt(int index)
97     {
98        return requests.get( index );
99     }
100    
101    public WsdlRequest getRequestByName(String requestName)
102 	{
103 		return (WsdlRequest) getWsdlModelItemByName( requests, requestName );
104 	}
105 
106 	public int getRequestCount()
107    {
108       return requests.size();
109    }
110 
111    public ImageIcon getIcon()
112 	{
113 		if( isOneWay() )
114 			return oneWayIcon;
115 		else
116 			return super.getIcon();
117 	}
118 
119 	public WsdlRequest addNewRequest( String name )
120    {
121       WsdlRequest requestImpl = new WsdlRequest( this, getConfig().addNewCall() );
122       requestImpl.setName( name );
123       requests.add( requestImpl );
124       ((WsdlInterface)getInterface()).fireRequestAdded( requestImpl );
125       return requestImpl;
126    }
127 
128    public WsdlInterface getInterface()
129    {
130       return iface;
131    }
132 
133    public void setAction(String soapAction)
134    {
135       String old = getAction();
136       getConfig().setAction( soapAction );
137       notifyPropertyChanged( ACTION_PROPERTY, old, soapAction );
138    }
139 
140    public String createRequest( boolean buildOptional )
141    {
142       if( iface.getBindingName() == null )
143       {
144       	UISupport.showErrorMessage( "Missing binding name, please try to refresh " +
145                "Interface\nfor request generation to work correctly" );
146          return null;
147       }
148       
149       if( getBindingOperationName() == null )
150       {
151       	UISupport.showErrorMessage(  "Missing bindingOperation name, please try to refresh " +
152                "Interface\nfor request generation to work correctly" );
153          return null;
154       }
155       
156       try
157       {
158          SoapMessageBuilder builder = (SoapMessageBuilder) iface.getMessageBuilder();
159          BindingOperation bindingOperation = findBindingOperation( iface.getWsdlContext().getDefinition() );
160          
161          if( bindingOperation == null )
162          {
163          	UISupport.showErrorMessage( "Failed to find bindingOperation, please try to refresh " +
164                   "Interface\nfor request generation to work correctly" );
165             return null;
166          }
167          
168 			return builder.buildSoapRequest( bindingOperation, buildOptional );
169       }
170       catch (Exception e)
171       {
172          e.printStackTrace();
173          return null;
174       }
175    }
176    
177    public String createResponse( boolean buildOptional )
178    {
179       if( iface.getBindingName() == null )
180       {
181       	UISupport.showErrorMessage( "Missing binding name, please try to refresh " +
182                "Interface\nfor request generation to work correctly" );
183          return null;
184       }
185       
186       if( getBindingOperationName() == null )
187       {
188       	UISupport.showErrorMessage(  "Missing bindingOperation name, please try to refresh " +
189                "Interface\nfor request generation to work correctly" );
190          return null;
191       }
192       
193       try
194       {
195          SoapMessageBuilder builder = (SoapMessageBuilder) iface.getMessageBuilder();
196          BindingOperation bindingOperation = findBindingOperation( iface.getWsdlContext().getDefinition() );
197          
198          if( bindingOperation == null )
199          {
200          	UISupport.showErrorMessage( "Failed to find bindingOperation, please try to refresh " +
201                   "Interface\nfor request generation to work correctly" );
202             return null;
203          }
204          
205 			return builder.buildSoapResponse( bindingOperation, buildOptional );
206       }
207       catch (Exception e)
208       {
209          e.printStackTrace();
210          return null;
211       }
212    }
213    
214    public BindingOperation findBindingOperation(Definition definition)
215    {
216       Binding binding = definition.getBinding( iface.getBindingName() );
217       if( binding == null )
218       	return null;
219       
220 		String inputName = getInputName();
221 		String outputName = getOutputName();
222 		
223 		if( inputName == null )
224 			inputName = ":none";
225 		
226 		if( outputName == null )
227 			outputName = ":none";
228 		
229 		BindingOperation result = binding.getBindingOperation( getConfig().getBindingOperationName(), inputName, outputName );
230 
231 		if( result == null && (inputName.equals( ":none" ) || outputName.equals( ":none" )))
232 		{
233 			// fall back to this behaviour for WSDL4j 1.5.0 compatibility
234 			result = binding.getBindingOperation( getConfig().getBindingOperationName(), 
235 						inputName.equals( ":none" ) ? null : inputName, outputName.equals( ":none" ) ? null : outputName ); 
236 		}
237 		return result;
238    }
239   
240    public void removeRequest( WsdlRequest request )
241    {
242       int ix = requests.indexOf( request );
243       requests.remove( ix );
244 
245       try
246       {
247       	((WsdlInterface)getInterface()).fireRequestRemoved( request );
248       }
249       finally
250       {
251 	      request.release();
252 	      getConfig().removeCall( ix );
253       }
254    }
255 
256    public String getBindingOperationName()
257    {
258       return getConfig().getBindingOperationName();
259    }
260    
261    public void setBindingOperationName( String name )
262    {
263       getConfig().setBindingOperationName( name );
264    }
265    
266    public void setInputName( String name )
267    {
268    	getConfig().setInputName( name );
269    }
270 
271    public String getInputName()
272    {
273    	String inputName = getConfig().getInputName();
274    	return inputName == null || inputName.trim().length() == 0 ? null : inputName;
275    }
276    
277    public void setOutputName( String name )
278    {
279    	if( name == null )
280    	{
281    		if( getConfig().isSetOutputName() )
282    			getConfig().unsetOutputName();
283    	}
284    	else
285    		getConfig().setOutputName( name );
286    }
287 
288    public String getOutputName()
289    {
290    	String outputName = getConfig().getOutputName();
291    	return outputName == null || outputName.trim().length() == 0 ? null : outputName;
292    }
293    
294    public void setOneWay( boolean isOneWay )
295    {
296    	getConfig().setIsOneWay( isOneWay );
297    }
298    
299    public boolean isOneWay()
300    {
301    	return getConfig().getIsOneWay();
302    }
303    
304 	public void initFromBindingOperation(BindingOperation operation, boolean notifyUpdate )
305 	{
306       setAction( WsdlUtils.getSoapAction( operation ));
307       setName( operation.getOperation().getName() );
308       setBindingOperationName( operation.getName() );
309       setInputName( operation.getBindingInput().getName() );
310       
311       BindingOutput bindingOutput = operation.getBindingOutput();
312       
313       // bindingOutput is null for oneway operations
314 		if( bindingOutput != null )
315       	setOutputName( bindingOutput.getName() );
316 		else
317 			setOutputName( null );
318 
319       setOneWay( bindingOutput == null );
320       
321       initAttachments(operation);
322       
323       if( notifyUpdate )
324       {
325       	iface.fireOperationUpdated( this );
326       }
327 	}
328 
329 	private void initAttachments(BindingOperation operation)
330 	{
331 		if( getConfig().isSetRequestParts() )
332 			getConfig().unsetRequestParts();
333 		
334 		if( getConfig().isSetResponseParts() )
335 			getConfig().unsetResponseParts();
336 		
337 		BindingOutput bindingOutput = operation.getBindingOutput();
338 		
339 		if( bindingOutput != null )
340 	   {
341 		   MIMEMultipartRelated multipartOutput = (MIMEMultipartRelated) WsdlUtils.getExtensiblityElement( 
342 		    		bindingOutput.getExtensibilityElements(), MIMEMultipartRelated.class );
343 		 
344 		   getConfig().setReceivesAttachments( multipartOutput != null );
345 	   }
346 		
347 		MIMEMultipartRelated multipartInput = (MIMEMultipartRelated) WsdlUtils.getExtensiblityElement( 
348       		operation.getBindingInput().getExtensibilityElements(), MIMEMultipartRelated.class );
349  
350       getConfig().setSendsAttachments( multipartInput != null );
351       if( multipartInput != null )
352       {
353       	List<MIMEPart> parts = multipartInput.getMIMEParts();
354       	Map<String,Part> partMap = new HashMap<String,Part>();
355 
356       	for( int c = 0; c < parts.size(); c++ )
357       	{
358 	      	List<MIMEContent> contentParts = WsdlUtils.getExtensiblityElements( parts.get(c).getExtensibilityElements(), MIMEContent.class );
359 	      	
360 	      	for( MIMEContent content : contentParts )
361 	      	{
362 	      		Part part = partMap.get( content.getPart());
363 	      		if( part != null )
364 	      		{ 
365 	      			if( !part.getContentTypeList().contains( content.getType() ))
366 	      				part.addContentType( content.getType() );
367 	      		}
368 	      		else
369 	      		{
370 	      			if( !getConfig().isSetRequestParts() )
371 	      				getConfig().addNewRequestParts();
372 	      			
373 	      			Part requestPart = getConfig().getRequestParts().addNewPart();
374 	      			requestPart.addContentType( content.getType() );
375 	      			requestPart.setName( content.getPart() );
376 	      			
377 	      			partMap.put( requestPart.getName(), requestPart );
378 	      		}
379 	      	}
380       	}
381       }
382 	}
383 	
384 	public boolean getReceivesAttachments()
385 	{
386 		return getConfig().getReceivesAttachments();
387 	}
388 	
389 	public boolean getSendsAttachments()
390 	{
391 		return getConfig().getSendsAttachments();
392 	}
393 	
394 	public QName getRequestBodyElementQName() throws Exception
395 	{
396 		WsdlInterface iface = (WsdlInterface) getInterface();
397 		
398 		Definition definition = iface.getWsdlContext().getDefinition();
399 		BindingOperation bindingOperation = findBindingOperation( definition );
400 		if( WsdlUtils.isRpc( definition, bindingOperation))
401 		{
402 			String ns = WsdlUtils.getSoapBodyNamespace( bindingOperation.getBindingInput().getExtensibilityElements() );
403 	      if( ns == null )
404 	      {
405 	      	ns = definition.getTargetNamespace();
406 	      }
407 			
408 			return new QName( ns, bindingOperation.getName() );
409 		}
410 		else
411 		{
412 			List<javax.wsdl.Part> parts = bindingOperation.getOperation().getInput().getMessage().getOrderedParts( null );
413 			if( parts == null || parts.isEmpty() )
414 				return null;
415 			
416 			javax.wsdl.Part part = parts.get( 0 );
417 			
418 			if( part.getElementName() != null )
419 			{
420 				return part.getElementName();
421 			}
422 			else
423 			{
424 				return new QName( definition.getTargetNamespace(), part.getName() );	
425 			}
426 		}
427 	}
428 	
429 	public QName getResponseBodyElementQName() throws Exception
430 	{
431 		if( isOneWay() )
432 			return null;
433 		
434 		WsdlInterface iface = (WsdlInterface) getInterface();
435 		
436 		Definition definition = iface.getWsdlContext().getDefinition();
437 		BindingOperation bindingOperation = findBindingOperation( definition );
438 		if( WsdlUtils.isRpc( definition, bindingOperation))
439 		{
440 			String ns = WsdlUtils.getSoapBodyNamespace( bindingOperation.getBindingOutput().getExtensibilityElements() );
441 	      if( ns == null )
442 	      {
443 	      	ns = definition.getTargetNamespace();
444 	      }
445 			
446 			return new QName( ns, bindingOperation.getName() + "Response" );
447 		}
448 		else
449 		{
450 			List<javax.wsdl.Part> parts = bindingOperation.getOperation().getOutput().getMessage().getOrderedParts( null );
451 			if( parts == null || parts.isEmpty() )
452 				return null;
453 			
454 			javax.wsdl.Part part = parts.get( 0 );
455 			
456 			if( part.getElementName() != null )
457 			{
458 				return part.getElementName();
459 			}
460 			else
461 			{
462 				return new QName( definition.getTargetNamespace(), part.getName() );	
463 			}
464 		}
465 	}
466 	
467 	public String getStyle()
468 	{
469 		WsdlContext wsdlContext = iface.getWsdlContext();
470 		if( !wsdlContext.isLoaded() )
471 			return "<not loaded>";
472 		
473 		try
474 		{
475 			Definition definition = wsdlContext.getDefinition();
476 			BindingOperation bindingOperation = findBindingOperation( definition);
477 			
478 			if( bindingOperation == null )
479 				return "<missing bindingOperation>";
480 			
481 			if( WsdlUtils.isRpc( definition, bindingOperation ))
482 			{
483 				return WsdlOperation.STYLE_RPC;
484 			}
485 			else
486 			{
487 				return WsdlOperation.STYLE_DOCUMENT;
488 			}
489 		}
490 		catch (Exception e)
491 		{
492 			e.printStackTrace();
493 			return "<error>";
494 		}
495 	}
496 
497 	public void release()
498 	{
499 		super.release();
500 		
501 		for( WsdlRequest request : requests )
502 			request.release();
503 	}
504 
505 	public BindingOperation getBindingOperation()
506 	{
507 		try
508 		{
509 			return findBindingOperation( ((WsdlInterface)getInterface()).getWsdlContext().getDefinition() );
510 		}
511 		catch( Exception e )
512 		{
513 			e.printStackTrace();
514 			return null;
515 		}
516 	}
517 
518 	public List<Request> getRequests()
519 	{
520 		return new ArrayList<Request>( requests );
521 	}
522 
523 	public MessagePart [] getFaultParts()
524 	{
525 		BindingOperation bindingOperation = getBindingOperation();
526 		Map bindingFaults = bindingOperation.getBindingFaults();
527 
528 		List<MessagePart> result = new ArrayList<MessagePart>();
529 		for( Object key : bindingFaults.keySet() )
530 		{
531 			result.add( new WsdlFaultPart( (String)key ));
532 		}
533 	
534 		return result.toArray( new MessagePart[result.size()] );
535 	}
536 	
537 	private class WsdlFaultPart extends FaultPart
538 	{
539 		private final String name;
540 
541 		public WsdlFaultPart( String name )
542 		{
543 			this.name = name;
544 		}
545 
546 		@Override
547 		public javax.wsdl.Part[] getWsdlParts()
548 		{
549 			return WsdlUtils.getFaultParts( getBindingOperation(), name );
550 		}
551 
552 		@Override
553 		public QName getPartElement()
554 		{
555 			return null;
556 		}
557 
558 		public String getDescription()
559 		{
560 			return null;
561 		}
562 
563 		public String getName()
564 		{
565 			return name;
566 		}
567 
568 		@Override
569 		public SchemaType getSchemaType()
570 		{
571 			return null;
572 		}}
573 }