View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 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.List;
17  
18  import javax.wsdl.BindingOperation;
19  import javax.wsdl.Part;
20  import javax.xml.namespace.QName;
21  
22  import org.apache.log4j.Logger;
23  import org.apache.xmlbeans.SchemaGlobalElement;
24  import org.apache.xmlbeans.SchemaType;
25  import org.apache.xmlbeans.XmlException;
26  import org.apache.xmlbeans.XmlObject;
27  
28  import com.eviware.soapui.impl.wsdl.WsdlOperation;
29  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
30  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
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 WsdlOperation 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 = operation.getBindingOperation();
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
98  				.getOutputParts( bindingOperation );
99  		messageParts.clear();
100 
101 		if( WsdlUtils.isRpc( wsdlContext.getDefinition(), bindingOperation ) )
102 		{
103 			// get root element
104 			XmlObject[] paths = msgXml.selectPath( "declare namespace env='"
105 					+ wsdlContext.getSoapVersion().getEnvelopeNamespace() + "';" + "declare namespace ns='"
106 					+ WsdlUtils.getTargetNamespace( wsdlContext.getDefinition()) + "';" + "$this/env:Envelope/env:Body/ns:"
107 					+ bindingOperation.getName() );
108 
109 			if( paths.length != 1 )
110 			{
111 				throw new Exception( "Missing message wrapper element [" + WsdlUtils.getTargetNamespace( wsdlContext.getDefinition())
112 						+ "@" + bindingOperation.getName() );
113 			}
114 			else
115 			{
116 				XmlObject wrapper = paths[0];
117 
118 				for( int i = 0; i < inputParts.length; i++ )
119 				{
120 					Part part = inputParts[i];
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,
154 										isRequest ) );
155 							}
156 							else
157 								log.error( "Missing element [" + typeName + "] in associated schema for part ["
158 										+ part.getName() + "]" );
159 						}
160 						else
161 						{
162 							SchemaType type = wsdlContext.getSchemaTypeLoader().findType( typeName );
163 							if( type != null )
164 							{
165 								messageParts.add( new MessageXmlPart( children[0], type, part, bindingOperation, isRequest ) );
166 							}
167 							else
168 								log.error( "Missing type [" + typeName + "] in associated schema for part [" + part.getName()
169 										+ "]" );
170 						}
171 					}
172 				}
173 			}
174 		}
175 		else
176 		{
177 			Part part = inputParts[0];
178 			QName elementName = part.getElementName();
179 			if( elementName != null )
180 			{
181 				// just check for correct message element, other elements are
182 				// avoided (should create an error)
183 				XmlObject[] paths = msgXml.selectPath( "declare namespace env='"
184 						+ wsdlContext.getSoapVersion().getEnvelopeNamespace() + "';" + "declare namespace ns='"
185 						+ elementName.getNamespaceURI() + "';" + "$this/env:Envelope/env:Body/ns:"
186 						+ elementName.getLocalPart() );
187 
188 				if( paths.length == 1 )
189 				{
190 					SchemaGlobalElement elm = wsdlContext.getSchemaTypeLoader().findElement( elementName );
191 					if( elm != null )
192 					{
193 						messageParts.add( new MessageXmlPart( paths[0], elm.getType(), part, bindingOperation, isRequest ) );
194 					}
195 					else
196 						throw new Exception( "Missing part type in associated schema" );
197 				}
198 				else
199 					throw new Exception( "Missing message part with name [" + elementName + "]" );
200 			}
201 		}
202 
203 		return messageParts.toArray( new MessageXmlPart[messageParts.size()] );
204 	}
205 }