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