View Javadoc

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