1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.mockaswar;
14
15 import java.io.File;
16 import java.io.FileInputStream;
17 import java.io.IOException;
18 import java.io.PrintWriter;
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.logging.Level;
22 import java.util.logging.Logger;
23
24 import javax.servlet.ServletContext;
25 import javax.servlet.ServletException;
26 import javax.servlet.http.HttpServlet;
27 import javax.servlet.http.HttpServletRequest;
28 import javax.servlet.http.HttpServletResponse;
29
30 import org.apache.commons.collections.list.TreeList;
31 import org.apache.log4j.spi.LoggingEvent;
32
33 import com.eviware.soapui.DefaultSoapUICore;
34 import com.eviware.soapui.SoapUI;
35 import com.eviware.soapui.impl.wsdl.WsdlProject;
36 import com.eviware.soapui.impl.wsdl.mock.DispatchException;
37 import com.eviware.soapui.impl.wsdl.mock.WsdlMockRunner;
38 import com.eviware.soapui.impl.wsdl.mock.WsdlMockService;
39 import com.eviware.soapui.model.mock.MockResult;
40 import com.eviware.soapui.model.mock.MockRunner;
41 import com.eviware.soapui.model.mock.MockService;
42 import com.eviware.soapui.monitor.MockEngine;
43 import com.eviware.soapui.support.StringUtils;
44 import com.eviware.soapui.support.Tools;
45 import com.eviware.soapui.support.editor.inspectors.attachments.ContentTypeHandler;
46 import com.eviware.soapui.support.types.StringToStringsMap;
47 import com.eviware.soapui.support.xml.XmlUtils;
48
49 /***
50 * Servlet implementation class SoapUIMockServlet
51 */
52 @SuppressWarnings( "unchecked" )
53 public class MockAsWarServlet extends HttpServlet
54 {
55
56 private static final long serialVersionUID = 1L;
57 protected static Logger logger = Logger.getLogger( MockAsWarServlet.class.getName() );
58 private WsdlProject project;
59 private long maxResults;
60 private List<MockResult> results = new TreeList();
61 private List<LoggingEvent> events = new TreeList();
62 private boolean enableWebUI;
63
64 public void init() throws ServletException
65 {
66 super.init();
67 try
68 {
69 String mockServiceEndpoint = initMockServiceParameters();
70
71 logger.info( "Loading project" );
72 project = new WsdlProject( getServletContext().getRealPath( getInitParameter( "projectFile" ) ) );
73
74 logger.info( "Starting MockService(s)" );
75
76 for( MockService mockService : project.getMockServiceList() )
77 {
78 logger.info( "Starting mockService [" + mockService.getName() + "]" );
79 if( StringUtils.hasContent( mockServiceEndpoint ) )
80 {
81 ( ( WsdlMockService )mockService ).setMockServiceEndpoint( mockServiceEndpoint );
82 }
83
84 mockService.start();
85 }
86 }
87 catch( Exception ex )
88 {
89 logger.log( Level.SEVERE, null, ex );
90 }
91 }
92
93 protected String initMockServiceParameters()
94 {
95 if( StringUtils.hasContent( getInitParameter( "listeners" ) ) )
96 {
97 logger.info( "Init listeners" );
98 System.setProperty( "soapui.ext.listeners", getServletContext().getRealPath( getInitParameter( "listeners" ) ) );
99 }
100 else
101 {
102 logger.info( "Listeners not set!" );
103 }
104
105 if( StringUtils.hasContent( getInitParameter( "actions" ) ) )
106 {
107 logger.info( "Init actions" );
108 System.setProperty( "soapui.ext.actions", getServletContext().getRealPath( getInitParameter( "actions" ) ) );
109 }
110 else
111 {
112 logger.info( "Actions not set!" );
113 }
114
115 if( StringUtils.hasContent( getInitParameter( "soapuiSettings" ) ) )
116 {
117 logger.info( "Init settings" );
118 SoapUI.setSoapUICore( new MockServletSoapUICore( getServletContext(), getInitParameter( "soapuiSettings" ) ),
119 true );
120 }
121 else
122 {
123 logger.info( "Settings not set!" );
124 SoapUI.setSoapUICore( new MockServletSoapUICore( getServletContext() ), true );
125 }
126
127 if( StringUtils.hasContent( getInitParameter( "enableWebUI" ) ) )
128 {
129 if( "true".equals( getInitParameter( "enableWebUI" ) ) )
130 {
131 logger.info( "WebUI ENABLED" );
132 enableWebUI = true;
133 }
134 else
135 {
136 logger.info( "WebUI DISABLED" );
137 enableWebUI = false;
138 }
139 }
140
141 try
142 {
143 maxResults = Integer.parseInt( getInitParameter( "maxResults" ) );
144 }
145 catch( Throwable t )
146 {
147 maxResults = 1000;
148 }
149
150 SoapUI.ensureGroovyLog().addAppender( new GroovyLogAppender() );
151
152 String mockServiceEndpoint = getInitParameter( "mockServiceEndpoint" );
153 return mockServiceEndpoint;
154 }
155
156 public void destroy()
157 {
158 super.destroy();
159 getMockServletCore().stop();
160 }
161
162 protected MockServletSoapUICore getMockServletCore()
163 {
164 return ( MockServletSoapUICore )SoapUI.getSoapUICore();
165 }
166
167 protected void service( HttpServletRequest request, HttpServletResponse response ) throws ServletException,
168 IOException
169 {
170 try
171 {
172 getMockServletCore().dispatchRequest( request, response );
173 }
174 catch( DispatchException ex )
175 {
176 logger.log( Level.SEVERE, null, ex );
177 }
178 }
179
180 private void printResult( PrintWriter out, MockResult result )
181 {
182
183 out.print( "<h4>Details for MockResult at " + new java.util.Date( result.getTimestamp() ) + " ("
184 + result.getTimeTaken() + "ms)</h4>" );
185
186 out.println( "<hr/><p><b>Request Headers</b>:</p>" );
187 out.print( "<table border=\"1\"><tr><td>Header</td><td>Value</td></tr>" );
188 StringToStringsMap headers = result.getMockRequest().getRequestHeaders();
189 for( String name : headers.getKeys() )
190 {
191 for( String value : headers.get( name ) )
192 out.println( "<tr><td>" + name + "</td><td>" + value + "</td></tr>" );
193 }
194 out.println( "</table>" );
195
196 out.println( "<hr/><b>Incoming Request</b>:<br/><pre>"
197 + XmlUtils.entitize( result.getMockRequest().getRequestContent() ) + "</pre>" );
198
199 out.println( "<hr/><p><b>Response Headers</b>:</p>" );
200 out.print( "<table border\"1\"><tr><td>Header</td><td>Value</td></tr>" );
201 headers = result.getResponseHeaders();
202 for( String name : headers.getKeys() )
203 {
204 for( String value : headers.get( name ) )
205 out.println( "<tr><td>" + name + "</td><td>" + value + "</td></tr>" );
206 }
207 out.println( "</table>" );
208
209 out.println( "<hr/><b>Returned Response</b>:<pre>" + XmlUtils.entitize( result.getResponseContent() ) + "</pre>" );
210 }
211
212 private List<MockRunner> mockRunners = new ArrayList<MockRunner>();
213
214 class MockServletSoapUICore extends DefaultSoapUICore implements MockEngine
215 {
216 private final ServletContext servletContext;
217
218 public MockServletSoapUICore( ServletContext servletContext, String soapUISettings )
219 {
220 super( servletContext.getRealPath( "/" ), servletContext.getRealPath( soapUISettings ) );
221 this.servletContext = servletContext;
222 }
223
224 public void dispatchRequest( HttpServletRequest request, HttpServletResponse response ) throws DispatchException,
225 IOException
226 {
227 String pathInfo = request.getPathInfo();
228 if( pathInfo == null )
229 pathInfo = "";
230
231 for( MockRunner mockRunner : getMockRunners() )
232 {
233 if( pathInfo.equals( mockRunner.getMockService().getPath() ) )
234 {
235 MockResult result = mockRunner.dispatchRequest( request, response );
236
237 if( maxResults > 0 )
238 {
239 synchronized( results )
240 {
241 while( maxResults > 0 && results.size() > maxResults )
242 {
243 results.remove( 0 );
244 }
245 if( result != null )
246 {
247 results.add( result );
248 }
249 }
250 }
251 return;
252 }
253 }
254
255 if( enableWebUI )
256 {
257 String realPath = servletContext.getRealPath( pathInfo );
258 File file = realPath == null ? null : new File( realPath );
259 if( file != null && file.exists() && file.isFile() )
260 {
261 FileInputStream in = new FileInputStream( file );
262 response.setStatus( HttpServletResponse.SC_OK );
263 long length = file.length();
264 response.setContentLength( ( int )length );
265 response.setContentType( ContentTypeHandler.getContentTypeFromFilename( file.getName() ) );
266 Tools.readAndWrite( in, length, response.getOutputStream() );
267 in.close();
268 }
269 else if( pathInfo.equals( "/master" ) )
270 {
271 printMaster( request, response );
272 }
273 else if( pathInfo.equals( "/detail" ) )
274 {
275 printDetail( request, response );
276 }
277 else if( pathInfo.equals( "/log" ) )
278 {
279 printLog( request, response );
280 }
281 else
282 {
283 printFrameset( request, response );
284 }
285 }
286 else
287 {
288 printDisabledLogFrameset( request, response );
289 }
290 }
291
292 public void stop()
293 {
294 for( MockRunner mockRunner : getMockRunners() )
295 {
296 mockRunner.stop();
297 }
298 }
299
300 public MockServletSoapUICore( ServletContext servletContext )
301 {
302 super( servletContext.getRealPath( "/" ), null );
303 this.servletContext = servletContext;
304 }
305
306 @Override
307 protected MockEngine buildMockEngine()
308 {
309 return this;
310 }
311
312 public MockRunner[] getMockRunners()
313 {
314 return mockRunners.toArray( new MockRunner[mockRunners.size()] );
315 }
316
317 public boolean hasRunningMock( MockService mockService )
318 {
319 for( MockRunner runner : mockRunners )
320 {
321 if( runner.getMockService() == mockService )
322 {
323 return true;
324 }
325 }
326
327 return false;
328 }
329
330 public void startMockService( MockRunner runner ) throws Exception
331 {
332 mockRunners.add( runner );
333 }
334
335 public void stopMockService( MockRunner runner )
336 {
337 mockRunners.remove( runner );
338 }
339 }
340
341 public void printMaster( HttpServletRequest request, HttpServletResponse response ) throws IOException
342 {
343 response.setStatus( HttpServletResponse.SC_OK );
344 response.setContentType( "text/html" );
345
346 PrintWriter out = response.getWriter();
347 startHtmlPage( out, "MockService Log Table", "15" );
348
349 out.print( "<h3><img src=\"header_logo.jpg\"> soapUI MockServices Log for project [" + project.getName()
350 + "]</h3>" + "<p style=\"text-align: left\">WSDLs:" );
351 for( MockRunner mockRunner : mockRunners )
352 {
353 String overviewUrl = ( ( WsdlMockRunner )mockRunner ).getOverviewUrl();
354 if( overviewUrl.startsWith( "/" ) )
355 {
356 overviewUrl = overviewUrl.substring( 1 );
357 }
358
359 out.print( " [<a target=\"new\" href=\"" + overviewUrl + "\">" + mockRunner.getMockService().getName()
360 + "</a>]" );
361 }
362
363 out.print( "</p>" );
364
365 out.print( "<hr/><p><b>Processed Requests</b>: " );
366 out.print( "[<a href=\"master\">Refresh</a>] " );
367 out.print( "[<a href=\"master?clear\">Clear</a>]</p>" );
368
369 if( "clear".equals( request.getQueryString() ) )
370 {
371 results.clear();
372 }
373
374 out.print( "<table border=\"1\">" );
375 out.print( "<tr><td></td><td>Timestamp</td><td>Time Taken</td><td>MockOperation</td><td>MockResponse</td><td>MockService</td></tr>" );
376
377 int cnt = 1;
378
379 for( MockResult result : results )
380 {
381
382 out.print( "<tr><td>" + ( cnt++ ) + "</td>" );
383 out.print( "<td><a target=\"detail\" href=\"detail?" + result.hashCode() + "\">"
384 + new java.util.Date( result.getTimestamp() ) + "</a></td>" );
385 out.print( "<td>" + result.getTimeTaken() + "</td>" );
386 out.print( "<td>" + result.getMockOperation().getName() + "</td>" );
387 out.print( "<td>" + result.getMockResponse().getName() + "</td>" );
388 out.print( "<td>" + result.getMockOperation().getMockService().getName() + "</td></tr>" );
389 }
390
391 out.print( "</table>" );
392
393 out.print( "</body></html>" );
394 out.flush();
395
396 }
397
398 private void startHtmlPage( PrintWriter out, String title, String refresh )
399 {
400 out.print( "<html><head>" );
401 out.print( "<title>" + title + "</title>" );
402 if( refresh != null )
403 {
404 out.print( "<meta http-equiv=\"refresh\" content=\"" + refresh + "\"/>" );
405 }
406
407 out.print( "<link type=\"text/css\" rel=\"stylesheet\" href=\"stylesheet.css\"/>" );
408 out.print( "</head><body>" );
409 }
410
411 public void printDisabledLogFrameset( HttpServletRequest request, HttpServletResponse response ) throws IOException
412 {
413 response.setStatus( HttpServletResponse.SC_OK );
414 response.setContentType( "text/html" );
415
416 PrintWriter out = response.getWriter();
417 out.print( "<html><head><title>soapUI MockServices Log for project [" + project.getName() + "]</title></head>" );
418 out.print( "<body>" );
419 out.print( "<h3>" );
420 out.print( "Log is disabled." );
421 out.print( "</h3>" );
422 out.print( "</body></html>" );
423 out.flush();
424 }
425
426 public void printFrameset( HttpServletRequest request, HttpServletResponse response ) throws IOException
427 {
428 response.setStatus( HttpServletResponse.SC_OK );
429 response.setContentType( "text/html" );
430
431 PrintWriter out = response.getWriter();
432 out.print( "<html><head><title>soapUI MockServices Log for project [" + project.getName() + "]</title></head>" );
433 out.print( "<frameset rows=\"40%,40%,*\">" );
434 out.print( "<frame src=\"master\"/>" );
435 out.print( "<frame name=\"detail\" src=\"detail\"/>" );
436 out.print( "<frame src=\"log\"/>" );
437 out.print( "</frameset>" );
438 out.print( "</html>" );
439 out.flush();
440 }
441
442 public void printDetail( HttpServletRequest request, HttpServletResponse response ) throws IOException
443 {
444 response.setStatus( HttpServletResponse.SC_OK );
445 response.setContentType( "text/html" );
446
447 PrintWriter out = response.getWriter();
448
449 startHtmlPage( out, "MockService Detail", null );
450
451 int id = 0;
452
453 try
454 {
455 id = Integer.parseInt( request.getQueryString() );
456 }
457 catch( NumberFormatException e )
458 {
459 }
460
461 if( id > 0 )
462 {
463 for( MockResult result : results )
464 {
465 if( result.hashCode() == id )
466 {
467 id = 0;
468 printResult( out, result );
469 }
470 }
471 }
472
473 if( id > 0 )
474 {
475 out.print( "<p>Missing specified MockResult</p>" );
476 }
477
478 out.print( "</body></html>" );
479 out.flush();
480 }
481
482 private class GroovyLogAppender extends org.apache.log4j.AppenderSkeleton
483 {
484
485 protected void append( LoggingEvent event )
486 {
487 events.add( event );
488 }
489
490 public void close()
491 {
492 }
493
494 public boolean requiresLayout()
495 {
496 return false;
497 }
498 }
499
500 public void printLog( HttpServletRequest request, HttpServletResponse response ) throws IOException
501 {
502 response.setStatus( HttpServletResponse.SC_OK );
503 response.setContentType( "text/html" );
504
505 PrintWriter out = response.getWriter();
506 startHtmlPage( out, "MockService Groovy Log", "15" );
507 out.print( "<p><b>Groovy Log output</b>: " );
508 out.print( "[<a href=\"log\">Refresh</a>] " );
509 out.print( "[<a href=\"log?clear\">Clear</a>]</p>" );
510
511 if( "clear".equals( request.getQueryString() ) )
512 {
513 events.clear();
514 }
515
516 out.print( "<table border=\"1\">" );
517 out.print( "<tr><td></td><td>Timestamp</td><td>Message</td></tr>" );
518
519 int cnt = 1;
520
521 for( LoggingEvent event : events )
522 {
523
524 out.print( "<tr><td>" + ( cnt++ ) + "</td>" );
525 out.print( "<td>" + new java.util.Date( event.timeStamp ) + "</td>" );
526 out.print( "<td>" + event.getRenderedMessage() + "</td></tr>" );
527 }
528
529 out.print( "</table>" );
530
531 out.print( "</body></html>" );
532 out.flush();
533 }
534 }