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.tools;
14  
15  import java.text.SimpleDateFormat;
16  import java.util.ArrayList;
17  import java.util.Date;
18  import java.util.List;
19  
20  import org.apache.commons.cli.CommandLine;
21  
22  import com.eviware.soapui.SoapUI;
23  import com.eviware.soapui.impl.wsdl.WsdlProject;
24  import com.eviware.soapui.impl.wsdl.mock.WsdlMockService;
25  import com.eviware.soapui.model.mock.MockResult;
26  import com.eviware.soapui.model.mock.MockRunner;
27  import com.eviware.soapui.model.mock.MockService;
28  import com.eviware.soapui.model.project.ProjectFactoryRegistry;
29  import com.eviware.soapui.model.support.MockRunListenerAdapter;
30  
31  /***
32   * Standalone tool-runner used from maven-plugin, can also be used from
33   * command-line (see xdocs) or directly from other classes.
34   * <p>
35   * For standalone usage, set the project file (with setProjectFile) and other
36   * desired properties before calling run
37   * </p>
38   * 
39   * @author Ole.Matzura
40   */
41  
42  public class SoapUIMockServiceRunner extends AbstractSoapUIRunner
43  {
44  	private String mockService;
45  	private String port;
46  	private String path;
47  	private List<MockRunner> runners = new ArrayList<MockRunner>();
48  	private boolean block;
49  	private String projectPassword;
50  	private WsdlProject project;
51  	private boolean saveAfterRun;
52  
53  	public static String TITLE = "soapUI " + SoapUI.SOAPUI_VERSION + " MockService Runner";
54  
55  	/***
56  	 * Runs the specified MockService in the specified soapUI project file, see
57  	 * soapUI xdocs for details.
58  	 * 
59  	 * @param args
60  	 * @throws Exception
61  	 */
62  
63  	public static void main( String[] args ) throws Exception
64  	{
65  		System.exit( new SoapUIMockServiceRunner().runFromCommandLine( args ));
66  	}
67  
68  	public void setMockService( String mockService )
69  	{
70  		this.mockService = mockService;
71  	}
72  
73  	public void setPath( String path )
74  	{
75  		this.path = path;
76  	}
77  
78  	public void setPort( String port )
79  	{
80  		this.port = port;
81  	}
82  
83  	public SoapUIMockServiceRunner()
84  	{
85  		super( TITLE );
86  	}
87  
88  	public SoapUIMockServiceRunner( String title )
89  	{
90  		super( title );
91  	}
92  
93  	public boolean runRunner() throws Exception
94  	{
95  		initGroovyLog();
96  
97  		String projectFile = getProjectFile();
98  
99  		// WsdlProject project = new WsdlProject( projectFile,
100 		// getProjectPassword() );
101 		project = ( WsdlProject )ProjectFactoryRegistry.getProjectFactory( "wsdl" ).createNew( projectFile,
102 				getProjectPassword() );
103 		if( project.isDisabled() )
104 			throw new Exception( "Failed to load soapUI project file [" + projectFile + "]" );
105 
106 		initProject();
107 
108 		if( mockService == null )
109 			log.info( "Running all MockServices in project [" + project.getName() + "]" );
110 		else
111 			log.info( "Running MockService [" + mockService + "] in project [" + project.getName() + "]" );
112 
113 		log.info( "Press any key to terminate" );
114 
115 		long startTime = System.nanoTime();
116 
117 		for( int c = 0; c < project.getMockServiceCount(); c++ )
118 		{
119 			MockService ms = project.getMockServiceAt( c );
120 			if( mockService == null || ms.getName().equals( mockService ) )
121 				runMockService( ( WsdlMockService )ms );
122 		}
123 
124 		log.info( "Started " + runners.size() + " runner" + ( ( runners.size() == 1 ) ? "" : "s" ) );
125 
126 		if( block )
127 		{
128 			System.out.println( "Press any key to terminate..." );
129 			while( System.in.available() == 0 )
130 			{
131 				Thread.sleep( 1000 );
132 
133 				// check if runners are still running
134 				for( int c = 0; c < runners.size(); c++ )
135 				{
136 					if( !runners.get( c ).isRunning() )
137 					{
138 						runners.remove( c );
139 						c-- ;
140 					}
141 				}
142 
143 				if( runners.isEmpty() )
144 					break;
145 			}
146 
147 			if( System.in.available() > 0 )
148 				System.in.read();
149 
150 			for( MockRunner runner : runners )
151 				runner.stop();
152 
153 			if( saveAfterRun && !project.isRemote() )
154 			{
155 				try
156 				{
157 					project.save();
158 				}
159 				catch( Throwable t )
160 				{
161 					log.error( "Failed to save project", t );
162 				}
163 			}
164 		}
165 
166 		long timeTaken = ( System.nanoTime() - startTime ) / 1000000;
167 		log.info( "time taken: " + timeTaken + "ms" );
168 
169 		exportReports();
170 
171 		return block;
172 	}
173 
174 	protected void initProject() throws Exception
175 	{
176 		initProjectProperties( project );
177 	}
178 
179 	protected void exportReports() throws Exception
180 	{
181 	}
182 
183 	/***
184 	 * Runs the specified MockService
185 	 * 
186 	 * @param mockService
187 	 */
188 
189 	public void runMockService( WsdlMockService mockService )
190 	{
191 		try
192 		{
193 			if( path != null )
194 				mockService.setPath( path );
195 
196 			if( port != null )
197 				mockService.setPort( Integer.parseInt( port ) );
198 
199 			mockService.addMockRunListener( new LogListener() );
200 			runners.add( mockService.start() );
201 		}
202 		catch( Exception e )
203 		{
204 			SoapUI.logError( e );
205 		}
206 	}
207 
208 	public class LogListener extends MockRunListenerAdapter
209 	{
210 		private SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS" );
211 		private int responseCount;
212 
213 		public void onMockRunnerStart( MockRunner mockRunner )
214 		{
215 			log.info( "MockService started on port " + mockRunner.getMockService().getPort() + " at path ["
216 					+ mockRunner.getMockService().getPath() + "]" );
217 		}
218 
219 		public void onMockRunnerStop( MockRunner mockRunner )
220 		{
221 			log.info( "MockService stopped, handled " + responseCount + " requests" );
222 		}
223 
224 		public void onMockResult( MockResult result )
225 		{
226 			responseCount++ ;
227 			log.info( "Handled request " + responseCount + "; [" + result.getMockResponse().getMockOperation().getName()
228 					+ "] with [" + result.getMockResponse().getName() + "] in [" + result.getTimeTaken() + "ms] at ["
229 					+ dateFormat.format( new Date( result.getTimestamp() ) ) + "]" );
230 		}
231 	}
232 
233 	@Override
234 	protected SoapUIOptions initCommandLineOptions()
235 	{
236 		SoapUIOptions options = new SoapUIOptions( "mockservicerunner" );
237 		options.addOption( "m", true, "Specified the name of the MockService to run" );
238 		options.addOption( "p", true, "Sets the local port to listen on" );
239 		options.addOption( "a", true, "Sets the url path to listen on" );
240 		options.addOption( "s", true, "Sets the soapui-settings.xml file to use" );
241 		options.addOption( "b", false, "Turns off blocking read for termination" );
242 		options.addOption( "x", true, "Sets project password for decryption if project is encrypted" );
243 		options.addOption( "v", true, "Sets password for soapui-settings.xml file" );
244 		options.addOption( "D", true, "Sets system property with name=value" );
245 		options.addOption( "G", true, "Sets global property with name=value" );
246 		options.addOption( "P", true, "Sets or overrides project property with name=value" );
247 		options.addOption( "S", false, "Saves the project after running the mockService(s)" );
248 
249 		return options;
250 	}
251 
252 	@Override
253 	protected boolean processCommandLine( CommandLine cmd )
254 	{
255 		if( cmd.hasOption( "m" ) )
256 			setMockService( getCommandLineOptionSubstSpace( cmd, "m" ) );
257 
258 		if( cmd.hasOption( "a" ) )
259 			setPath( getCommandLineOptionSubstSpace( cmd, "a" ) );
260 
261 		if( cmd.hasOption( "p" ) )
262 			setPort( cmd.getOptionValue( "p" ) );
263 
264 		if( cmd.hasOption( "s" ) )
265 			setSettingsFile( getCommandLineOptionSubstSpace( cmd, "s" ) );
266 
267 		setBlock( !cmd.hasOption( 'b' ) );
268 		setSaveAfterRun( cmd.hasOption( 'S' ) );
269 
270 		if( cmd.hasOption( "x" ) )
271 		{
272 			setProjectPassword( cmd.getOptionValue( "x" ) );
273 		}
274 
275 		if( cmd.hasOption( "v" ) )
276 		{
277 			setSoapUISettingsPassword( cmd.getOptionValue( "v" ) );
278 		}
279 
280 		if( cmd.hasOption( "D" ) )
281 		{
282 			setSystemProperties( cmd.getOptionValues( "D" ) );
283 		}
284 
285 		if( cmd.hasOption( "G" ) )
286 		{
287 			setGlobalProperties( cmd.getOptionValues( "G" ) );
288 		}
289 
290 		if( cmd.hasOption( "P" ) )
291 		{
292 			setProjectProperties( cmd.getOptionValues( "P" ) );
293 		}
294 
295 		return true;
296 	}
297 
298 	public void setProjectPassword( String projectPassword )
299 	{
300 		this.projectPassword = projectPassword;
301 	}
302 
303 	public String getProjectPassword()
304 	{
305 		return projectPassword;
306 	}
307 
308 	public void setBlock( boolean block )
309 	{
310 		this.block = block;
311 	}
312 
313 	public void setSaveAfterRun( boolean saveAfterRun )
314 	{
315 		this.saveAfterRun = saveAfterRun;
316 	}
317 
318 	public WsdlProject getProject()
319 	{
320 		return project;
321 	}
322 	
323 	public void stopAll() {
324 		for ( MockRunner runner : runners ) {
325 			runner.stop();
326 		}
327 	}
328 }