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 interfaces.add( mockService.getMockOperationAt( i ).getOperation().getInterface() );
67 }
68
69 for( WsdlInterface iface : interfaces )
70 iface.getWsdlContext().loadIfNecessary( false );
71
72 mockContext = new WsdlMockRunContext( mockService, context );
73
74 SoapUI.getMockEngine().startMockService( this );
75
76 MockRunListener[] mockRunListeners = mockService.getMockRunListeners();
77
78 for( MockRunListener listener : mockRunListeners )
79 {
80 listener.onMockRunnerStart( this );
81 }
82 }
83
84 public WsdlMockRunContext getMockContext()
85 {
86 return mockContext;
87 }
88
89 public synchronized void addMockResult( WsdlMockResult mockResult )
90 {
91 mockResults.add( mockResult );
92 while( mockResults.size() > maxResults )
93 {
94 mockResults.remove( 0 );
95 removed++;
96 }
97 }
98
99 public void stop()
100 {
101 SoapUI.getMockEngine().stopMockService( this );
102
103 MockRunListener[] mockRunListeners = mockService.getMockRunListeners();
104
105 for( MockRunListener listener : mockRunListeners )
106 {
107 listener.onMockRunnerStop( this );
108 }
109 }
110
111 public WsdlMockService getMockService()
112 {
113 return mockService;
114 }
115
116 public long getMaxResults()
117 {
118 return maxResults;
119 }
120
121 public synchronized void setMaxResults( long l )
122 {
123 this.maxResults = l;
124
125 while( mockResults.size() > l )
126 {
127 mockResults.remove( 0 );
128 removed++;
129 }
130 }
131
132 public WsdlMockResult dispatchRequest( HttpServletRequest request, HttpServletResponse response ) throws DispatchException
133 {
134 WsdlMockResult result = null;
135 MockRunListener[] mockRunListeners = mockService.getMockRunListeners();
136
137 try
138 {
139 for( MockRunListener listener : mockRunListeners )
140 {
141 listener.onMockRequest( this, request, response );
142 }
143
144 long timestamp = System.currentTimeMillis();
145 String soapAction = request.getHeader( "SOAPAction" );
146
147 WsdlMockRequest mockRequest = new WsdlMockRequest( request, response, mockContext );
148
149 SoapVersion soapVersion = mockRequest.getSoapVersion();
150 if( soapVersion == null )
151 throw new DispatchException( "Unrecognized SOAP Version" );
152
153 XmlObject contentElm = mockRequest.getContentElement();
154 if( contentElm == null )
155 throw new DispatchException( "Missing content element in body" );
156
157 QName contentQName = XmlUtils.getQName( contentElm.getDomNode() );
158 NodeList contentChildNodes = null;
159
160 for( int c = 0; c < mockService.getMockOperationCount(); c++ )
161 {
162 WsdlMockOperation mockOperation = ( WsdlMockOperation ) mockService.getMockOperationAt( c );
163 WsdlOperation wsdlOperation = ( WsdlOperation ) mockOperation.getOperation();
164 if( wsdlOperation == null )
165 continue;
166
167 if( mockService.isRequireSoapVersion() &&
168 wsdlOperation.getInterface().getSoapVersion() != mockRequest.getSoapVersion() )
169 {
170 continue;
171 }
172
173 String action = wsdlOperation.getAction() == null ? "\"\"" : "\"" + wsdlOperation.getAction() + "\"";
174
175
176 if( (soapAction == null && wsdlOperation.getAction() == null ) ||
177 (action.equals( soapAction ) || (wsdlOperation.getAction() != null && wsdlOperation.getAction().equals( soapAction ) )))
178 {
179 QName qname = wsdlOperation.getRequestBodyElementQName();
180
181 if( !qname.equals( contentQName ))
182 continue;
183
184 long startTime = 0;
185
186
187 if( wsdlOperation.getStyle().equals( WsdlOperation.STYLE_DOCUMENT ))
188 {
189
190 startTime = System.nanoTime();
191 result = mockOperation.dispatchRequest( mockRequest, response );
192 }
193 else if( wsdlOperation.getStyle().equals( WsdlOperation.STYLE_RPC ))
194 {
195 BindingOperation bindingOperation = wsdlOperation.getBindingOperation();
196 List<Part> parts = bindingOperation.getOperation().getInput().getMessage().getOrderedParts( null );
197
198 if( contentChildNodes == null )
199 contentChildNodes = XmlUtils.getChildElements( ( Element ) contentElm.getDomNode() );
200
201 int i = 0;
202
203 if( parts.size() > 0 )
204 {
205 for( int x = 0; x < parts.size(); x++ )
206 {
207 if( WsdlUtils.isAttachmentInputPart( parts.get( x ), bindingOperation ))
208 {
209 parts.remove( x );
210 x--;
211 }
212 }
213
214 for( ; i < contentChildNodes.getLength() && !parts.isEmpty(); i++ )
215 {
216 Node item = contentChildNodes.item( i );
217 if( item.getNodeType() != Node.ELEMENT_NODE )
218 continue;
219
220 int j=0;
221 while ((j<parts.size()) && (!item.getNodeName().equals( parts.get( j ).getName())))
222 {
223 j++;
224 }
225
226 if (j==parts.size())
227 break;
228
229 parts.remove( j );
230 }
231 }
232
233
234 if( i == contentChildNodes.getLength() && parts.isEmpty() )
235 {
236 startTime = System.nanoTime();
237 result = mockOperation.dispatchRequest( mockRequest, response );
238 }
239 }
240
241 if( startTime == 0 )
242 {
243 throw new DispatchException( "Failed to find matching operation for request" );
244 }
245 else
246 {
247 ((Request)request).setHandled( true );
248 result.setTimeTaken( ( System.nanoTime() - startTime ) / 1000000 );
249 result.setTimestamp( timestamp );
250 addMockResult( result );
251 return result;
252 }
253 }
254 }
255
256 throw new DispatchException( "Missing operation for soapAction [" + soapAction + "] and body element [" +
257 contentQName + "] with SOAP Version [" + mockRequest.getSoapVersion() + "]" );
258 }
259 catch( Exception e )
260 {
261 if( e instanceof DispatchException )
262 throw (DispatchException)e;
263
264 throw new DispatchException( e );
265 }
266 finally
267 {
268 if( result != null )
269 {
270 for( MockRunListener listener : mockRunListeners )
271 {
272 listener.onMockResult( result );
273 }
274 }
275 }
276 }
277
278 public MockResult getMockResultAt( int index )
279 {
280 return index <= removed ? null : mockResults.get( index-removed );
281 }
282
283 public int getMockResultCount()
284 {
285 return mockResults.size() + removed;
286 }
287
288 public synchronized void clearResults()
289 {
290 mockResults.clear();
291 }
292
293 public void release()
294 {
295 clearResults();
296 mockService = null;
297 mockContext.clear();
298 }
299 }