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