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