View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
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 }