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;
    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.BindingOperation;
    22  import javax.wsdl.Part;
    23  import javax.wsdl.Port;
    24  import javax.wsdl.Service;
    25  import javax.xml.namespace.QName;
    26
    27  import org.apache.log4j.Logger;
    28  import org.apache.xmlbeans.SchemaGlobalElement;
    29  import org.apache.xmlbeans.SchemaType;
    30  import org.apache.xmlbeans.XmlException;
    31  import org.apache.xmlbeans.XmlObject;
    32
    33  import com.eviware.soapui.impl.wsdl.WsdlInterface;
    34  import com.eviware.soapui.impl.wsdl.WsdlOperation;
    35  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
    36  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
    37  import com.eviware.soapui.model.iface.Operation;
    38
    39  /***
    40   * XmlObject based wrapper for manipulation, etc..
    41   *
    42   * @author Ole.Matzura
    43   */
    44
    45  public class MessageXmlObject
    46  {
    47  	private XmlObject messageObj;
    48  	private WsdlContext wsdlContext;
    49  	private List<MessageXmlPart> messageParts = new ArrayList<MessageXmlPart>();
    50
    51  	private final static Logger log = Logger.getLogger( MessageXmlObject.class );
    52  	private final String messageContent;
    53  	private Operation operation;
    54  	private final boolean isRequest;
    55
    56  	public MessageXmlObject( WsdlOperation operation, String messageContent, boolean isRequest )
    57  	{
    58  		this.messageContent = messageContent;
    59  		this.operation = operation;
    60  		this.isRequest = isRequest;
    61  		wsdlContext = ((WsdlInterface)operation.getInterface()).getWsdlContext();
    62  	}
    63
    64  	public String getMessageContent()
    65  	{
    66  		if( messageObj == null )
    67  		{
    68  			return messageContent;
    69  		}
    70  		else
    71  		{
    72  			for( int c = 0; c < messageParts.size(); c++ )
    73  				messageParts.get( c ).update();
    74
    75  			return messageObj.xmlText();
    76  		}
    77  	}
    78
    79  	public XmlObject getMessageObj() throws XmlException
    80  	{
    81  		if( messageObj == null )
    82  		{
    83  		   messageObj = XmlObject.Factory.parse( getMessageContent() );
    84  		}
    85
    86  		return messageObj;
    87  	}
    88
    89  	public MessageXmlPart [] getMessageParts() throws Exception
    90     {
    91     	String operationName = operation.getName();
    92  		BindingOperation bindingOperation = findBindingOperation( operationName );
    93  		if (bindingOperation == null)
    94  		{
    95  			throw new Exception("Missing operation ["	+ operationName + "] in wsdl definition");
    96  		}
    97
    98  		 if( !wsdlContext.hasSchemaTypes() )
    99         {
    100 			 throw new Exception("Missing schema types for message");
    101        }
    102
    103        XmlObject msgXml = getMessageObj();
    104        Part[] inputParts = WsdlUtils.getInputParts(bindingOperation);
    105        messageParts.clear();
    106
    107        if( WsdlUtils.isRpc( wsdlContext.getDefinition(), bindingOperation ))
    108        {
    109       	 //  	 get root element
    110           XmlObject[] paths = msgXml.selectPath( "declare namespace env='" +
    111                    		wsdlContext.getSoapVersion().getEnvelopeNamespace() + "';" +
    112                 "declare namespace ns='" + wsdlContext.getDefinition().getTargetNamespace() + "';" +
    113                 "$this/env:Envelope/env:Body/ns:" + bindingOperation.getName() );
    114
    115           if( paths.length != 1 )
    116           {
    117          	 throw new Exception("Missing message wrapper element [" +
    118                    wsdlContext.getDefinition().getTargetNamespace() + "@" + bindingOperation.getName() );
    119           }
    120           else
    121           {
    122              XmlObject wrapper = paths[0];
    123
    124              for (int i = 0; i < inputParts.length; i++)
    125              {
    126                 Part part = inputParts[i];
    127
    128
    129                 QName partName = part.getElementName();
    130                 if( partName == null )
    131                	 partName = new QName( part.getName() );
    132
    133                 XmlObject[] children = wrapper.selectChildren( partName );
    134
    135                 // attachment part?
    136                 if( WsdlUtils.isAttachmentInputPart( part, bindingOperation ))
    137                 {
    138                	 // not required
    139                	 if( children.length == 1 )
    140                	 {
    141 	               	 QName typeName = part.getTypeName();
    142 	               	 SchemaType type = typeName == null ? null : wsdlContext.getSchemaTypeLoader().findType( typeName );
    143 	               	 messageParts.add( new MessageXmlPart( children[0], type, part, bindingOperation, isRequest ));
    144                	 }
    145                 }
    146                 else if( children.length != 1 )
    147                 {
    148                    log.error("Missing message part [" + part.getName() + "]" );
    149                 }
    150                 else
    151                 {
    152                    QName typeName = part.getTypeName();
    153                    if( typeName == null )
    154                    {
    155                   	 typeName = partName;
    156                   	 SchemaGlobalElement type = wsdlContext.getSchemaTypeLoader().findElement( typeName );
    157
    158                   	 if( type != null )
    159 	                   {
    160                   		 messageParts.add( new MessageXmlPart( children[0], type.getType(), part, bindingOperation, isRequest ) );
    161 	                   }
    162 	                   else log.error( "Missing element [" + typeName + "] in associated schema for part [" + part.getName() + "]" );
    163                    }
    164                    else
    165                    {
    166 	                   SchemaType type = wsdlContext.getSchemaTypeLoader().findType( typeName );
    167 	                   if( type != null )
    168 	                   {
    169 	                  	 messageParts.add( new MessageXmlPart( children[0], type, part, bindingOperation, isRequest ));
    170 	                   }
    171 	                   else log.error( "Missing type [" + typeName + "] in associated schema for part [" + part.getName() + "]" );
    172                    }
    173                 }
    174              }
    175           }
    176        }
    177        else
    178        {
    179           Part part = inputParts[0];
    180           QName elementName = part.getElementName();
    181           if( elementName != null )
    182           {
    183           	// just check for correct message element, other elements are avoided (should create an error)
    184              XmlObject[] paths = msgXml.selectPath( "declare namespace env='" +
    185                    		wsdlContext.getSoapVersion().getEnvelopeNamespace() + "';" +
    186                    "declare namespace ns='" + elementName.getNamespaceURI() + "';" +
    187                    "$this/env:Envelope/env:Body/ns:" + elementName.getLocalPart() );
    188
    189              if( paths.length == 1 )
    190              {
    191                 SchemaGlobalElement elm = wsdlContext.getSchemaTypeLoader().findElement( elementName );
    192                 if( elm != null )
    193                 {
    194                	 messageParts.add( new MessageXmlPart( paths[0], elm.getType(), part, bindingOperation, isRequest ));
    195                 }
    196                 else throw new Exception("Missing part type in associated schema" );
    197              }
    198              else throw new Exception("Missing message part with name [" + elementName + "]" );
    199           }
    200        }
    201
    202    	return messageParts.toArray( new MessageXmlPart[messageParts.size()] );
    203    }
    204
    205 	private BindingOperation findBindingOperation(String operationName) throws Exception
    206 	{
    207 		Map services = wsdlContext.getDefinition().getAllServices();
    208 		Iterator i = services.keySet().iterator();
    209 		while( i.hasNext() )
    210 		{
    211 			Service service = (Service) wsdlContext.getDefinition().getService( (QName) i.next());
    212 			Map ports = service.getPorts();
    213
    214 			Iterator iterator = ports.keySet().iterator();
    215 			while( iterator.hasNext() )
    216 			{
    217 				Port port = (Port) service.getPort( (String) iterator.next() );
    218 				BindingOperation bindingOperation = port.getBinding().getBindingOperation( operationName, null, null );
    219 				if( bindingOperation != null ) return bindingOperation;
    220 			}
    221 		}
    222
    223 		Map bindings = wsdlContext.getDefinition().getAllBindings();
    224 		i = bindings.keySet().iterator();
    225 		while( i.hasNext() )
    226 		{
    227 			Binding binding = (Binding) bindings.get( i.next() );
    228 			BindingOperation bindingOperation = binding.getBindingOperation( operationName, null, null );
    229 			if( bindingOperation != null ) return bindingOperation;
    230 		}
    231
    232 		return null;
    233 	}
    234 }