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.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 }