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