1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.mock;
14
15 import java.util.Collections;
16 import java.util.HashSet;
17 import java.util.LinkedList;
18 import java.util.List;
19 import java.util.Set;
20
21 import javax.servlet.http.HttpServletRequest;
22 import javax.servlet.http.HttpServletResponse;
23 import javax.wsdl.BindingOperation;
24 import javax.wsdl.Part;
25 import javax.xml.namespace.QName;
26
27 import org.apache.xmlbeans.XmlObject;
28 import org.mortbay.jetty.Request;
29 import org.w3c.dom.Element;
30 import org.w3c.dom.Node;
31 import org.w3c.dom.NodeList;
32
33 import com.eviware.soapui.SoapUI;
34 import com.eviware.soapui.impl.wsdl.WsdlInterface;
35 import com.eviware.soapui.impl.wsdl.WsdlOperation;
36 import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
37 import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
38 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
39 import com.eviware.soapui.model.mock.MockResult;
40 import com.eviware.soapui.model.mock.MockRunListener;
41 import com.eviware.soapui.model.mock.MockRunner;
42 import com.eviware.soapui.support.xml.XmlUtils;
43
44 /***
45 * MockRunner that dispatches Http Requests to their designated WsdlMockOperation if possible
46 *
47 * @author ole.matzura
48 */
49
50 public class WsdlMockRunner implements MockRunner
51 {
52 private WsdlMockService mockService;
53 private List<WsdlMockResult> mockResults = Collections.synchronizedList( new LinkedList<WsdlMockResult>());
54 private long maxResults = 100;
55 private int removed = 0;
56 private WsdlMockRunContext mockContext;
57
58 public WsdlMockRunner( WsdlMockService mockService, WsdlTestRunContext context ) throws Exception
59 {
60 this.mockService = mockService;
61
62 Set<WsdlInterface> interfaces = new HashSet<WsdlInterface>();
63
64 for( int i = 0; i < mockService.getMockOperationCount(); i++ )
65 {
66 WsdlOperation operation = mockService.getMockOperationAt( i ).getOperation();
67 if( operation != null )
68 interfaces.add( operation.getInterface() );
69 }
70
71 for( WsdlInterface iface : interfaces )
72 iface.getWsdlContext().loadIfNecessary( false );
73
74 mockContext = new WsdlMockRunContext( mockService, context );
75
76 SoapUI.getMockEngine().startMockService( this );
77
78 MockRunListener[] mockRunListeners = mockService.getMockRunListeners();
79
80 for( MockRunListener listener : mockRunListeners )
81 {
82 listener.onMockRunnerStart( this );
83 }
84 }
85
86 public WsdlMockRunContext getMockContext()
87 {
88 return mockContext;
89 }
90
91 public synchronized void addMockResult( WsdlMockResult mockResult )
92 {
93 mockResults.add( mockResult );
94 while( mockResults.size() > maxResults )
95 {
96 mockResults.remove( 0 );
97 removed++;
98 }
99 }
100
101 public void stop()
102 {
103 SoapUI.getMockEngine().stopMockService( this );
104
105 MockRunListener[] mockRunListeners = mockService.getMockRunListeners();
106
107 for( MockRunListener listener : mockRunListeners )
108 {
109 listener.onMockRunnerStop( this );
110 }
111 }
112
113 public WsdlMockService getMockService()
114 {
115 return mockService;
116 }
117
118 public long getMaxResults()
119 {
120 return maxResults;
121 }
122
123 public synchronized void setMaxResults( long l )
124 {
125 this.maxResults = l;
126
127 while( mockResults.size() > l )
128 {
129 mockResults.remove( 0 );
130 removed++;
131 }
132 }
133
134 @SuppressWarnings("unchecked")
135 public WsdlMockResult dispatchRequest( HttpServletRequest request, HttpServletResponse response ) throws DispatchException
136 {
137 WsdlMockResult result = null;
138 MockRunListener[] mockRunListeners = mockService.getMockRunListeners();
139
140 try
141 {
142 for( MockRunListener listener : mockRunListeners )
143 {
144 listener.onMockRequest( this, request, response );
145 }
146
147 long timestamp = System.currentTimeMillis();
148 String soapAction = request.getHeader( "SOAPAction" );
149
150 WsdlMockRequest mockRequest = new WsdlMockRequest( request, response, mockContext );
151
152 SoapVersion soapVersion = mockRequest.getSoapVersion();
153 if( soapVersion == null )
154 throw new DispatchException( "Unrecognized SOAP Version" );
155
156 XmlObject contentElm = mockRequest.getContentElement();
157 if( contentElm == null )
158 throw new DispatchException( "Missing content element in body" );
159
160 QName contentQName = XmlUtils.getQName( contentElm.getDomNode() );
161 NodeList contentChildNodes = null;
162
163 for( int c = 0; c < mockService.getMockOperationCount(); c++ )
164 {
165 WsdlMockOperation mockOperation = ( WsdlMockOperation ) mockService.getMockOperationAt( c );
166 WsdlOperation wsdlOperation = ( WsdlOperation ) mockOperation.getOperation();
167 if( wsdlOperation == null )
168 continue;
169
170 if( mockService.isRequireSoapVersion() &&
171 wsdlOperation.getInterface().getSoapVersion() != mockRequest.getSoapVersion() )
172 {
173 continue;
174 }
175
176 String action = wsdlOperation.getAction() == null ? "\"\"" : "\"" + wsdlOperation.getAction() + "\"";
177
178
179 if( (soapAction == null && wsdlOperation.getAction() == null ) ||
180 (action.equals( soapAction ) || (wsdlOperation.getAction() != null && wsdlOperation.getAction().equals( soapAction ) )))
181 {
182 QName qname = wsdlOperation.getRequestBodyElementQName();
183
184 if( !qname.equals( contentQName ))
185 continue;
186
187 long startTime = 0;
188
189
190 if( wsdlOperation.getStyle().equals( WsdlOperation.STYLE_DOCUMENT ))
191 {
192
193 startTime = System.nanoTime();
194 result = mockOperation.dispatchRequest( mockRequest, response );
195 }
196 else if( wsdlOperation.getStyle().equals( WsdlOperation.STYLE_RPC ))
197 {
198 BindingOperation bindingOperation = wsdlOperation.getBindingOperation();
199 List<Part> parts = bindingOperation.getOperation().getInput().getMessage().getOrderedParts( null );
200
201 if( contentChildNodes == null )
202 contentChildNodes = XmlUtils.getChildElements( ( Element ) contentElm.getDomNode() );
203
204 int i = 0;
205
206 if( parts.size() > 0 )
207 {
208 for( int x = 0; x < parts.size(); x++ )
209 {
210 if( WsdlUtils.isAttachmentInputPart( parts.get( x ), bindingOperation ))
211 {
212 parts.remove( x );
213 x--;
214 }
215 }
216
217 for( ; i < contentChildNodes.getLength() && !parts.isEmpty(); i++ )
218 {
219 Node item = contentChildNodes.item( i );
220 if( item.getNodeType() != Node.ELEMENT_NODE )
221 continue;
222
223 int j=0;
224 while ((j<parts.size()) && (!item.getNodeName().equals( parts.get( j ).getName())))
225 {
226 j++;
227 }
228
229 if (j==parts.size())
230 break;
231
232 parts.remove( j );
233 }
234 }
235
236
237 if( i == contentChildNodes.getLength() && parts.isEmpty() )
238 {
239 startTime = System.nanoTime();
240 result = mockOperation.dispatchRequest( mockRequest, response );
241 }
242 }
243
244 if( startTime == 0 )
245 {
246 throw new DispatchException( "Failed to find matching operation for request" );
247 }
248 else
249 {
250 ((Request)request).setHandled( true );
251 result.setTimeTaken( ( System.nanoTime() - startTime ) / 1000000 );
252 result.setTimestamp( timestamp );
253 addMockResult( result );
254 return result;
255 }
256 }
257 }
258
259 throw new DispatchException( "Missing operation for soapAction [" + soapAction + "] and body element [" +
260 contentQName + "] with SOAP Version [" + mockRequest.getSoapVersion() + "]" );
261 }
262 catch( Exception e )
263 {
264 if( e instanceof DispatchException )
265 throw (DispatchException)e;
266
267 throw new DispatchException( e );
268 }
269 finally
270 {
271 if( result != null )
272 {
273 for( MockRunListener listener : mockRunListeners )
274 {
275 listener.onMockResult( result );
276 }
277 }
278 }
279 }
280
281 public MockResult getMockResultAt( int index )
282 {
283 return index <= removed ? null : mockResults.get( index-removed );
284 }
285
286 public int getMockResultCount()
287 {
288 return mockResults.size() + removed;
289 }
290
291 public synchronized void clearResults()
292 {
293 mockResults.clear();
294 }
295
296 public void release()
297 {
298 clearResults();
299 mockService = null;
300 mockContext.clear();
301 }
302 }