1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.mock;
14
15 import java.io.IOException;
16 import java.io.PrintWriter;
17 import java.io.StringReader;
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.LinkedList;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25
26 import javax.servlet.http.HttpServletRequest;
27 import javax.servlet.http.HttpServletResponse;
28
29 import org.mortbay.jetty.Request;
30 import org.xml.sax.InputSource;
31
32 import com.eviware.soapui.SoapUI;
33 import com.eviware.soapui.impl.wsdl.WsdlInterface;
34 import com.eviware.soapui.impl.wsdl.WsdlOperation;
35 import com.eviware.soapui.impl.wsdl.support.soap.SoapUtils;
36 import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
37 import com.eviware.soapui.impl.wsdl.support.wsdl.CachedWsdlLoader;
38 import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
39 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
40 import com.eviware.soapui.model.iface.Interface;
41 import com.eviware.soapui.model.mock.MockResult;
42 import com.eviware.soapui.model.mock.MockRunListener;
43 import com.eviware.soapui.model.mock.MockRunner;
44 import com.eviware.soapui.monitor.MockEngine;
45 import com.eviware.soapui.support.StringUtils;
46 import com.eviware.soapui.support.types.StringToStringMap;
47 import com.eviware.soapui.support.xml.XmlUtils;
48
49 /***
50 * MockRunner that dispatches Http Requests to their designated
51 * WsdlMockOperation if possible
52 *
53 * @author ole.matzura
54 */
55
56 public class WsdlMockRunner implements MockRunner
57 {
58 private WsdlMockService mockService;
59 private final List<WsdlMockResult> mockResults = Collections.synchronizedList( new LinkedList<WsdlMockResult>() );
60 private long maxResults = 100;
61 private int removed = 0;
62 private final WsdlMockRunContext mockContext;
63 private final Map<String, StringToStringMap> wsdlCache = new HashMap<String, StringToStringMap>();
64 private boolean running;
65
66 public WsdlMockRunner( WsdlMockService mockService, WsdlTestRunContext context ) throws Exception
67 {
68 this.mockService = mockService;
69
70 Set<WsdlInterface> interfaces = new HashSet<WsdlInterface>();
71
72 for( int i = 0; i < mockService.getMockOperationCount(); i++ )
73 {
74 WsdlOperation operation = mockService.getMockOperationAt( i ).getOperation();
75 if( operation != null )
76 interfaces.add( operation.getInterface() );
77 }
78
79 for( WsdlInterface iface : interfaces )
80 iface.getWsdlContext().loadIfNecessary( false );
81
82 mockContext = new WsdlMockRunContext( mockService, context );
83
84 mockService.runStartScript( mockContext, this );
85
86 SoapUI.getMockEngine().startMockService( this );
87 running = true;
88
89 MockRunListener[] mockRunListeners = mockService.getMockRunListeners();
90
91 for( MockRunListener listener : mockRunListeners )
92 {
93 listener.onMockRunnerStart( this );
94 }
95
96 initWsdlCache();
97 }
98
99 private void initWsdlCache()
100 {
101 for( Interface iface : mockService.getMockedInterfaces() )
102 {
103 try
104 {
105 CachedWsdlLoader loader = null;
106
107 if( iface.isCached() )
108 {
109 loader = ( CachedWsdlLoader ) iface.createWsdlLoader();
110 }
111 else
112 {
113 loader = new CachedWsdlLoader( iface.getDefinition() );
114 }
115
116 String wsdlPrefix = getInterfacePrefix( iface ).substring( 1 );
117 StringToStringMap parts = loader.createFilesForExport( wsdlPrefix + "&part=" );
118
119 for( String key : parts.keySet() )
120 {
121 if( key.endsWith( ".wsdl" ) )
122 {
123 InputSource inputSource = new InputSource( new StringReader( parts.get( key ) ) );
124 String content = WsdlUtils.replacePortEndpoint( iface, inputSource, getLocalMockServiceEndpoint() );
125
126 if( content != null )
127 parts.put( key, content );
128 }
129 }
130
131 wsdlCache.put( iface.getName(), parts );
132
133 MockEngine.log.info( "Mounted WSDL for interface [" + iface.getName() + "] at [" + wsdlPrefix + "]" );
134 }
135 catch( Exception e )
136 {
137 e.printStackTrace();
138 }
139 }
140 }
141
142 public String getLocalMockServiceEndpoint()
143 {
144 String host = mockService.getHost();
145 if( StringUtils.isNullOrEmpty( host ))
146 host = "127.0.0.1";
147
148 return "http://" + host + ":" + mockService.getPort() + mockService.getPath();
149 }
150
151 public String getInterfacePrefix( Interface iface )
152 {
153 String wsdlPrefix = getOverviewUrl() + "&interface=" + iface.getName();
154 return wsdlPrefix;
155 }
156
157 public WsdlMockRunContext getMockContext()
158 {
159 return mockContext;
160 }
161
162 public synchronized void addMockResult( WsdlMockResult mockResult )
163 {
164 mockResults.add( mockResult );
165 while( mockResults.size() > maxResults )
166 {
167 mockResults.remove( 0 );
168 removed++;
169 }
170 }
171
172 public boolean isRunning()
173 {
174 return running;
175 }
176
177 public void stop()
178 {
179 if( !isRunning() )
180 return;
181
182 SoapUI.getMockEngine().stopMockService( this );
183
184 MockRunListener[] mockRunListeners = mockService.getMockRunListeners();
185
186 for( MockRunListener listener : mockRunListeners )
187 {
188 listener.onMockRunnerStop( this );
189 }
190
191 try
192 {
193 mockService.runStopScript( mockContext, this );
194 running = false;
195 }
196 catch( Exception e )
197 {
198 SoapUI.logError( e );
199 }
200 }
201
202 public WsdlMockService getMockService()
203 {
204 return mockService;
205 }
206
207 public long getMaxResults()
208 {
209 return maxResults;
210 }
211
212 public synchronized void setMaxResults( long l )
213 {
214 this.maxResults = l;
215
216 while( mockResults.size() > l )
217 {
218 mockResults.remove( 0 );
219 removed++;
220 }
221 }
222
223 @SuppressWarnings( "unchecked" )
224 public WsdlMockResult dispatchMockRequest( HttpServletRequest request, HttpServletResponse response )
225 throws DispatchException
226 {
227 WsdlMockResult result = null;
228 MockRunListener[] mockRunListeners = mockService.getMockRunListeners();
229
230 try
231 {
232 for( MockRunListener listener : mockRunListeners )
233 {
234 listener.onMockRequest( this, request, response );
235 }
236
237 long timestamp = System.currentTimeMillis();
238 WsdlMockRequest mockRequest = new WsdlMockRequest( request, response, mockContext );
239
240 SoapVersion soapVersion = mockRequest.getSoapVersion();
241 if( soapVersion == null )
242 throw new DispatchException( "Unrecognized SOAP Version" );
243
244 String soapAction = mockRequest.getSoapAction();
245
246 WsdlOperation operation = SoapUtils.findOperationForRequest( soapVersion, soapAction, mockRequest
247 .getRequestXmlObject(), mockService.getProject().getInterfaceList(), mockService.isRequireSoapVersion() );
248
249 if( operation != null )
250 {
251 WsdlMockOperation mockOperation = mockService.getMockOperation( operation );
252 if( mockOperation != null )
253 {
254 long startTime = System.nanoTime();
255 result = mockOperation.dispatchRequest( mockRequest, response );
256 ( ( Request ) request ).setHandled( true );
257 result.setTimeTaken( ( System.nanoTime() - startTime ) / 1000000 );
258 result.setTimestamp( timestamp );
259 addMockResult( result );
260 return result;
261 }
262 else
263 {
264 throw new DispatchException( "Failed to find matching operation for request" );
265 }
266 }
267
268 throw new DispatchException( "Missing operation for soapAction [" + soapAction + "] and body element ["
269 + XmlUtils.getQName( mockRequest.getContentElement().getDomNode() ) + "] with SOAP Version ["
270 + mockRequest.getSoapVersion() + "]" );
271 }
272 catch( Exception e )
273 {
274 if( e instanceof DispatchException )
275 throw ( DispatchException ) e;
276
277 throw new DispatchException( e );
278 }
279 finally
280 {
281 if( result != null )
282 {
283 for( MockRunListener listener : mockRunListeners )
284 {
285 listener.onMockResult( result );
286 }
287 }
288 }
289 }
290
291 public MockResult getMockResultAt( int index )
292 {
293 return index <= removed ? null : mockResults.get( index - removed );
294 }
295
296 public int getMockResultCount()
297 {
298 return mockResults.size() + removed;
299 }
300
301 public synchronized void clearResults()
302 {
303 mockResults.clear();
304 }
305
306 public void release()
307 {
308 clearResults();
309 mockService = null;
310 mockContext.clear();
311 }
312
313 public void dispatchWsdlRequest( HttpServletRequest request, HttpServletResponse response ) throws DispatchException
314 {
315 try
316 {
317 String ifaceName = request.getParameter( "interface" );
318 WsdlInterface iface = mockService.getProject().getInterfaceByName( ifaceName );
319 if( iface == null )
320 {
321 printInterfaceList( response );
322 return;
323 }
324
325 StringToStringMap parts = wsdlCache.get( iface.getName() );
326 String content = parts.get( request.getParameter( "part" ) );
327
328 if( content == null )
329 {
330 printPartList( iface, parts, response );
331 return;
332 }
333
334 if( content != null )
335 {
336 response.setStatus( HttpServletResponse.SC_OK );
337 response.setContentType( "text/xml" );
338 response.setCharacterEncoding( "UTF-8" );
339 response.getWriter().print( content );
340 }
341 }
342 catch( Exception e )
343 {
344 e.printStackTrace();
345 }
346 finally
347 {
348 try
349 {
350 response.flushBuffer();
351 }
352 catch( IOException e )
353 {
354 e.printStackTrace();
355 }
356 }
357 }
358
359 private void printPartList( WsdlInterface iface, StringToStringMap parts, HttpServletResponse response )
360 throws IOException
361 {
362 response.setStatus( HttpServletResponse.SC_OK );
363 response.setContentType( "text/html" );
364
365 PrintWriter out = response.getWriter();
366 out.print( "<html><body><p>Parts in interface [" + iface.getName() + "]</p><ul>" );
367
368 for( String key : parts.keySet() )
369 {
370 out.print( "<li><a href=\"" );
371 out.print( getInterfacePrefix( iface ) + "&part=" + key );
372 out.print( "\">" + key + "</a></li>" );
373 }
374
375 out.print( "</ul></p></body></html>" );
376 }
377
378 private void printInterfaceList( HttpServletResponse response ) throws IOException
379 {
380 response.setStatus( HttpServletResponse.SC_OK );
381 response.setContentType( "text/html" );
382
383 PrintWriter out = response.getWriter();
384 out.print( "<html><body><p>Mocked Interfaces in project [" + mockService.getProject().getName() + "]</p><ul>" );
385
386 for( Interface iface : mockService.getProject().getInterfaceList() )
387 {
388 out.print( "<li><a href=\"" );
389 out.print( getInterfacePrefix( iface ) );
390 out.print( "\">" + iface.getName() + "</a></li>" );
391 }
392
393 out.print( "</ul></p></body></html>" );
394 }
395
396 public String getOverviewUrl()
397 {
398 return mockService.getPath() + "?WSDL";
399 }
400 }