View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 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.wsdl;
14  
15  import java.util.ArrayList;
16  import java.util.Iterator;
17  import java.util.List;
18  import java.util.Map;
19  
20  import javax.wsdl.Binding;
21  import javax.wsdl.BindingFault;
22  import javax.wsdl.BindingOperation;
23  import javax.wsdl.BindingOutput;
24  import javax.wsdl.Definition;
25  import javax.wsdl.Message;
26  import javax.wsdl.Part;
27  import javax.wsdl.Port;
28  import javax.wsdl.Service;
29  import javax.wsdl.extensions.ExtensibilityElement;
30  import javax.wsdl.extensions.mime.MIMEContent;
31  import javax.wsdl.extensions.mime.MIMEMultipartRelated;
32  import javax.wsdl.extensions.mime.MIMEPart;
33  import javax.wsdl.extensions.soap.SOAPAddress;
34  import javax.wsdl.extensions.soap.SOAPBinding;
35  import javax.wsdl.extensions.soap.SOAPBody;
36  import javax.wsdl.extensions.soap.SOAPFault;
37  import javax.wsdl.extensions.soap.SOAPHeader;
38  import javax.wsdl.extensions.soap.SOAPOperation;
39  import javax.wsdl.extensions.soap12.SOAP12Address;
40  import javax.wsdl.extensions.soap12.SOAP12Binding;
41  import javax.wsdl.extensions.soap12.SOAP12Body;
42  import javax.wsdl.extensions.soap12.SOAP12Fault;
43  import javax.wsdl.extensions.soap12.SOAP12Header;
44  import javax.wsdl.extensions.soap12.SOAP12Operation;
45  import javax.wsdl.factory.WSDLFactory;
46  import javax.wsdl.xml.WSDLReader;
47  import javax.xml.namespace.QName;
48  
49  import org.apache.log4j.Logger;
50  
51  /***
52   * Wsdl-related tools
53   * 
54   * @author Ole.Matzura
55   */
56  
57  public class WsdlUtils
58  {
59     private final static Logger log = Logger.getLogger( WsdlUtils.class );
60  	private static WSDLReader wsdlReader;
61     
62     public static <T extends ExtensibilityElement> T getExtensiblityElement(List list, Class<T> clazz )
63     {
64        List<T> elements = getExtensiblityElements( list, clazz );
65        return elements.isEmpty() ? null : elements.get( 0 );
66     }
67     
68     public static <T extends ExtensibilityElement> List<T> getExtensiblityElements(List list, Class<T> clazz )
69     {
70        List<T> result = new ArrayList<T>();
71        
72        for( Iterator<T> i = list.iterator(); i.hasNext(); )
73        {
74           T elm = (T) i.next();
75           if( clazz.isAssignableFrom( elm.getClass() ) )
76           {
77              result.add( elm );
78           }
79        }
80  
81        return result;
82     }
83     
84     public static String getSoapAction(BindingOperation operation)
85     {
86        List list = operation.getExtensibilityElements();
87        SOAPOperation soapOperation = (SOAPOperation) WsdlUtils.getExtensiblityElement( list, SOAPOperation.class );
88        if( soapOperation != null )
89        	return soapOperation.getSoapActionURI();
90        
91        SOAP12Operation soap12Operation = (SOAP12Operation) WsdlUtils.getExtensiblityElement( list, SOAP12Operation.class );
92        if( soap12Operation != null )
93        	return soap12Operation.getSoapActionURI();
94        
95        return null;
96     }
97     
98     public static String[] getEndpointsForBinding(Definition definition, Binding binding)
99     {
100       List<String> result = new ArrayList<String>(); 
101       Map map = definition.getAllServices();
102       for( Iterator i = map.values().iterator(); i.hasNext(); )
103       {
104          Service service = (Service) i.next();
105          Map portMap = service.getPorts();
106          for( Iterator i2 = portMap.values().iterator(); i2.hasNext(); )
107          {
108             Port port = (Port) i2.next();
109             if( port.getBinding() == binding )
110             {
111             	String endpoint = WsdlUtils.getSoapEndpoint( port );
112             	if( endpoint != null )
113             		result.add( endpoint );
114             }
115          }
116       }
117       
118       return result.toArray( new String[result.size()]);
119    }
120    
121    public static Binding findBindingForOperation(Definition definition, BindingOperation bindingOperation)
122    {
123       Map services = definition.getAllServices();
124       Iterator<Service> s = services.values().iterator();
125       
126       while( s.hasNext())
127       {
128          Map ports = s.next().getPorts();
129          Iterator<Port> p = ports.values().iterator();
130          while( p.hasNext())
131          {
132             Binding binding = p.next().getBinding();
133             List bindingOperations = binding.getBindingOperations();
134             for (Iterator iter = bindingOperations.iterator(); iter.hasNext();)
135             {
136                BindingOperation op = (BindingOperation) iter.next();
137                if( op.getName().equals( bindingOperation.getName() ))
138                   return binding;
139             }
140          }
141       }
142       
143       Map bindings = definition.getAllBindings();
144       Iterator<QName> names = bindings.keySet().iterator();
145       while( names.hasNext() ) 
146       {
147       	Binding binding = definition.getBinding( names.next() );
148       	List bindingOperations = binding.getBindingOperations();
149          for (Iterator iter = bindingOperations.iterator(); iter.hasNext();)
150          {
151             BindingOperation op = (BindingOperation) iter.next();
152             if( op.getName().equals( bindingOperation.getName() ))
153                return binding;
154          }
155       }
156       
157       return null;
158    }
159    
160    public static boolean isInputSoapEncoded(BindingOperation bindingOperation)
161    {
162       SOAPBody soapBody = (SOAPBody) WsdlUtils.getExtensiblityElement(bindingOperation.getBindingInput()
163             .getExtensibilityElements(), SOAPBody.class);
164       
165       if( soapBody != null )
166       {
167       	return soapBody.getUse() != null && soapBody.getUse().equalsIgnoreCase( "encoded" ) &&
168       		(soapBody.getEncodingStyles() == null || soapBody.getEncodingStyles().contains( "http://schemas.xmlsoap.org/soap/encoding/" ));
169       }
170       
171       SOAP12Body soap12Body = (SOAP12Body) WsdlUtils.getExtensiblityElement(bindingOperation.getBindingInput()
172                .getExtensibilityElements(), SOAP12Body.class);
173          
174       if( soap12Body != null )
175       {
176       	return soap12Body.getUse() != null && soap12Body.getUse().equalsIgnoreCase( "encoded" ) &&
177       		(soap12Body.getEncodingStyle() == null || soap12Body.getEncodingStyle().equals( "http://schemas.xmlsoap.org/soap/encoding/" ));
178       }
179       
180       return false;
181    }
182    
183    public static boolean isOutputSoapEncoded(BindingOperation bindingOperation)
184    {
185       BindingOutput bindingOutput = bindingOperation.getBindingOutput();
186       if( bindingOutput == null )
187       	return false;
188       
189 		SOAPBody soapBody = (SOAPBody) WsdlUtils.getExtensiblityElement(bindingOutput
190             .getExtensibilityElements(), SOAPBody.class);
191       
192 		if( soapBody != null )
193 		{
194 			return soapBody.getUse() != null && soapBody.getUse().equalsIgnoreCase( "encoded" ) &&
195       		(soapBody.getEncodingStyles() == null || soapBody.getEncodingStyles().contains( "http://schemas.xmlsoap.org/soap/encoding/" ));
196 		}
197 		
198 		SOAP12Body soap12Body = (SOAP12Body) WsdlUtils.getExtensiblityElement(bindingOutput
199 	            .getExtensibilityElements(), SOAP12Body.class);
200 	      
201 		if( soap12Body != null )
202 		{
203 			return soap12Body.getUse() != null && soap12Body.getUse().equalsIgnoreCase( "encoded" ) &&
204       		(soap12Body.getEncodingStyle() == null || soap12Body.getEncodingStyle().equals( "http://schemas.xmlsoap.org/soap/encoding/" ));
205 		}
206 		
207 		return false;
208    }
209    
210    public static boolean isRpc(Definition definition, BindingOperation bindingOperation)
211    {
212       SOAPOperation soapOperation = (SOAPOperation) WsdlUtils.getExtensiblityElement( 
213             bindingOperation.getExtensibilityElements(), SOAPOperation.class );
214       
215       if( soapOperation != null && soapOperation.getStyle() != null )
216          return soapOperation.getStyle().equalsIgnoreCase("rpc");
217       
218       SOAP12Operation soap12Operation = (SOAP12Operation) WsdlUtils.getExtensiblityElement( 
219                bindingOperation.getExtensibilityElements(), SOAP12Operation.class );
220          
221       if( soap12Operation != null && soap12Operation.getStyle() != null )
222          return soap12Operation.getStyle().equalsIgnoreCase("rpc");
223       
224       Binding binding = findBindingForOperation( definition, bindingOperation );
225       if( binding == null ) 
226       {
227          log.error( "Failed to find binding for operation [" + bindingOperation.getName() + "] in definition [" + 
228                definition.getDocumentBaseURI() + "]" );
229          return false;
230       }
231       
232       return isRpc(binding);
233    }
234 
235 	public static boolean isRpc(Binding binding)
236 	{
237 		SOAPBinding soapBinding = (SOAPBinding) WsdlUtils.getExtensiblityElement( 
238             binding.getExtensibilityElements(), SOAPBinding.class );
239       
240 		if( soapBinding != null )
241 			return "rpc".equalsIgnoreCase( soapBinding.getStyle());
242 		
243 		SOAP12Binding soap12Binding = (SOAP12Binding) WsdlUtils.getExtensiblityElement( 
244 	            binding.getExtensibilityElements(), SOAP12Binding.class );
245 	      
246 		if( soap12Binding != null )
247 			return "rpc".equalsIgnoreCase( soap12Binding.getStyle());
248 		
249 		return false;
250 	}
251    
252    /***
253     * Returns a list of parts for the specifed operation, either as specified in body or all
254     */
255    
256    public static Part[] getInputParts(BindingOperation operation)
257    {
258       List<Part> result = new ArrayList<Part>();
259       Message msg = operation.getOperation().getInput().getMessage();
260       SOAPBody soapBody = (SOAPBody) WsdlUtils.getExtensiblityElement(operation.getBindingInput()
261             .getExtensibilityElements(), SOAPBody.class);
262 
263       if (soapBody == null || soapBody.getParts() == null)
264       {
265       	SOAP12Body soap12Body = (SOAP12Body) WsdlUtils.getExtensiblityElement(operation.getBindingInput()
266       	            .getExtensibilityElements(), SOAP12Body.class);
267       	
268       	if (soap12Body == null || soap12Body.getParts() == null)
269          {
270       		if( msg != null )
271       			result.addAll( msg.getOrderedParts( null ));
272          }
273       	else
274       	{
275       		Iterator i = soap12Body.getParts().iterator();
276             while (i.hasNext())
277             {
278                String partName = (String) i.next();
279                Part part = msg.getPart( partName );
280                
281                result.add(part);
282             }
283       	}
284       }
285       else
286       {
287          Iterator i = soapBody.getParts().iterator();
288          while (i.hasNext())
289          {
290             String partName = (String) i.next();
291             Part part = msg.getPart( partName );
292             
293             result.add(part);
294          }
295       }
296 
297       return result.toArray(new Part[result.size()]);
298    }
299    
300    public static boolean isAttachmentInputPart( Part part, BindingOperation operation )
301    {
302    	return getInputMultipartContent(part, operation).length > 0;
303    }
304    
305    public static boolean isAttachmentOutputPart( Part part, BindingOperation operation )
306    {
307    	return getOutputMultipartContent(part, operation).length > 0;
308    }
309 
310    public static MIMEContent[] getOutputMultipartContent( Part part, BindingOperation operation )
311    {
312    	MIMEMultipartRelated multipartOutput = (MIMEMultipartRelated) WsdlUtils.getExtensiblityElement( 
313       		operation.getBindingOutput().getExtensibilityElements(), MIMEMultipartRelated.class );
314    	
315    	return getContentParts(part, multipartOutput);
316    }
317    
318    public static MIMEContent[] getInputMultipartContent( Part part, BindingOperation operation )
319    {
320    	MIMEMultipartRelated multipartInput = (MIMEMultipartRelated) WsdlUtils.getExtensiblityElement( 
321       		operation.getBindingInput().getExtensibilityElements(), MIMEMultipartRelated.class );
322    	
323    	return getContentParts(part, multipartInput);
324    }
325    
326 	public static MIMEContent[] getContentParts(Part part, MIMEMultipartRelated multipart)
327 	{
328 		List<MIMEContent> result = new ArrayList<MIMEContent>();
329 		
330 		if( multipart != null )
331    	{
332    		List<MIMEPart> parts = multipart.getMIMEParts();
333 
334       	for( int c = 0; c < parts.size(); c++ )
335       	{
336 	      	List<MIMEContent> contentParts = WsdlUtils.getExtensiblityElements( parts.get(c).getExtensibilityElements(), MIMEContent.class );
337 	      	
338 	      	for( MIMEContent content : contentParts )
339 	      	{
340 	      		if( content.getPart().equals( part.getName() ))
341 	      		  result.add( content );
342 	      	}
343       	}
344    	}
345    	
346    	return result.toArray( new MIMEContent[result.size()] );
347 	}
348    
349    public static Part[] getFaultParts(BindingOperation bindingOperation, String faultName)
350    {
351       List<Part> result = new ArrayList<Part>();
352       
353       BindingFault bindingFault = bindingOperation.getBindingFault( faultName );
354       SOAPFault soapFault = (SOAPFault) WsdlUtils.getExtensiblityElement(bindingFault
355             .getExtensibilityElements(), SOAPFault.class);
356 
357       if (soapFault != null && soapFault.getName() != null )
358       {
359          result.addAll( bindingOperation.getOperation().getFault( soapFault.getName() ).getMessage().getOrderedParts( null ));
360       }
361       else
362       {
363       	SOAP12Fault soap12Fault = (SOAP12Fault) WsdlUtils.getExtensiblityElement(bindingFault
364                   .getExtensibilityElements(), SOAP12Fault.class);
365       	
366       	 if (soap12Fault != null && soap12Fault.getName() != null )
367           {
368              result.addAll( bindingOperation.getOperation().getFault( soap12Fault.getName() ).getMessage().getOrderedParts( null ));
369           }
370           else
371           {
372          	 result.addAll( bindingOperation.getOperation().getFault( faultName ).getMessage().getOrderedParts( null ));
373           }
374       }
375       
376       return result.toArray(new Part[result.size()]);
377    }
378    
379    public static Part[] getOutputParts(BindingOperation operation)
380    {
381    	BindingOutput bindingOutput = operation.getBindingOutput();
382    	if( bindingOutput == null )
383    		return new Part[0];
384    	
385       List<Part> result = new ArrayList<Part>();
386       Message msg = operation.getOperation().getOutput().getMessage();
387 		SOAPBody soapBody = (SOAPBody) WsdlUtils.getExtensiblityElement(bindingOutput
388             .getExtensibilityElements(), SOAPBody.class);
389 
390       if (soapBody == null || soapBody.getParts() == null)
391       {
392       	SOAP12Body soap12Body = (SOAP12Body) WsdlUtils.getExtensiblityElement(bindingOutput
393                   .getExtensibilityElements(), SOAP12Body.class);
394       	
395       	if(soap12Body == null || soap12Body.getParts() == null)
396       	{
397       		result.addAll( msg.getOrderedParts( null ));
398       	}
399       	else
400       	{
401       		Iterator i = soap12Body.getParts().iterator();
402             while (i.hasNext())
403             {
404                String partName = (String) i.next();
405                Part part = msg.getPart( partName );
406                
407                result.add(part);
408             }
409       	}
410       }
411       else
412       {
413          Iterator i = soapBody.getParts().iterator();
414          while (i.hasNext())
415          {
416             String partName = (String) i.next();
417             Part part = msg.getPart( partName );
418             
419             result.add(part);
420          }
421       }
422 
423       return result.toArray(new Part[result.size()]);
424    }
425 
426 	public static boolean isMultipartRequest(Definition definition, BindingOperation bindingOperation)
427 	{
428 		return (MIMEMultipartRelated) WsdlUtils.getExtensiblityElement(
429 					bindingOperation.getBindingInput().getExtensibilityElements(), MIMEMultipartRelated.class ) != null;
430 	}
431 
432 	public static String getSoapEndpoint( Port port )
433 	{
434 		SOAPAddress soapAddress = (SOAPAddress) WsdlUtils.getExtensiblityElement( port.getExtensibilityElements(), SOAPAddress.class );
435       if( soapAddress != null )
436       	return soapAddress.getLocationURI();
437       
438       SOAP12Address soap12Address = (SOAP12Address) WsdlUtils.getExtensiblityElement( port.getExtensibilityElements(), SOAP12Address.class );
439       if( soap12Address != null )
440       	return soap12Address.getLocationURI();
441       
442       return null;
443 	}
444 
445 	public static String getSoapBodyNamespace( List list )
446 	{
447 		SOAPBody soapBody = (SOAPBody) WsdlUtils.getExtensiblityElement( list, SOAPBody.class);
448 		if( soapBody != null )
449 			return soapBody.getNamespaceURI();
450 		
451 		SOAP12Body soap12Body = (SOAP12Body) WsdlUtils.getExtensiblityElement( list, SOAP12Body.class);
452 		if( soap12Body != null )
453 			return soap12Body.getNamespaceURI();
454 	      
455 		return null;
456 	}
457 	
458 	public interface SoapHeader
459 	{
460 		public QName getMessage();
461 		
462 		public String getPart();
463 	}
464 	
465 	public static class Soap11Header implements SoapHeader
466 	{
467 		private final SOAPHeader soapHeader;
468 
469 		public Soap11Header( SOAPHeader soapHeader )
470 		{
471 			this.soapHeader = soapHeader;}
472 		
473 		public QName getMessage()
474 		{
475 			return soapHeader.getMessage();
476 		}
477 
478 		public String getPart()
479 		{
480 			return soapHeader.getPart();
481 		}
482 	}
483 	
484 	public static class Soap12Header implements SoapHeader
485 	{
486 		private final SOAP12Header soapHeader;
487 
488 		public Soap12Header( SOAP12Header soapHeader )
489 		{
490 			this.soapHeader = soapHeader;}
491 		
492 		public QName getMessage()
493 		{
494 			return soapHeader.getMessage();
495 		}
496 
497 		public String getPart()
498 		{
499 			return soapHeader.getPart();
500 		}
501 	}
502 
503 	public static List<SoapHeader> getSoapHeaders( List list )
504 	{
505 		List<SoapHeader> result = new ArrayList<SoapHeader>();
506 		
507 		List<SOAPHeader> soapHeaders = WsdlUtils.getExtensiblityElements( list, SOAPHeader.class);
508 		if( soapHeaders != null && !soapHeaders.isEmpty() )
509 		{
510 			for( SOAPHeader header : soapHeaders )
511 				result.add( new Soap11Header( header ));
512 		}
513 		else
514 		{
515 			List<SOAP12Header> soap12Headers = WsdlUtils.getExtensiblityElements( list, SOAP12Header.class);
516 			if( soap12Headers != null && !soap12Headers.isEmpty() )
517 			{
518 				for( SOAP12Header header : soap12Headers )
519 					result.add( new Soap12Header( header ));
520 			}
521 		}
522 		
523 		return result;
524 	}
525 
526 	public static synchronized Definition readDefinition( String wsdlUrl ) throws Exception 
527 	{
528 		if( wsdlReader == null )
529 		{
530 		   WSDLFactory factory = WSDLFactory.newInstance();
531 		   wsdlReader = factory.newWSDLReader();
532 		   wsdlReader.setFeature("javax.wsdl.verbose", true);
533 		   wsdlReader.setFeature("javax.wsdl.importDocuments", true);
534 		}
535 		
536 	   return wsdlReader.readWSDL( new UrlWsdlLoader( wsdlUrl ) );
537 	}
538 }