View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 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.impl.wsdl.mock;
14  
15  import java.util.ArrayList;
16  import java.util.Arrays;
17  import java.util.Collections;
18  import java.util.HashSet;
19  import java.util.List;
20  import java.util.Set;
21  
22  import javax.servlet.http.HttpServletRequest;
23  import javax.servlet.http.HttpServletResponse;
24  import javax.swing.ImageIcon;
25  
26  import com.eviware.soapui.SoapUI;
27  import com.eviware.soapui.config.MockOperationConfig;
28  import com.eviware.soapui.config.MockServiceConfig;
29  import com.eviware.soapui.impl.wsdl.AbstractTestPropertyHolderWsdlModelItem;
30  import com.eviware.soapui.impl.wsdl.WsdlInterface;
31  import com.eviware.soapui.impl.wsdl.WsdlOperation;
32  import com.eviware.soapui.impl.wsdl.WsdlProject;
33  import com.eviware.soapui.impl.wsdl.support.ModelItemIconAnimator;
34  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
35  import com.eviware.soapui.model.ModelItem;
36  import com.eviware.soapui.model.iface.Operation;
37  import com.eviware.soapui.model.mock.MockOperation;
38  import com.eviware.soapui.model.mock.MockResult;
39  import com.eviware.soapui.model.mock.MockRunListener;
40  import com.eviware.soapui.model.mock.MockRunner;
41  import com.eviware.soapui.model.mock.MockService;
42  import com.eviware.soapui.model.mock.MockServiceListener;
43  import com.eviware.soapui.model.project.Project;
44  import com.eviware.soapui.support.StringUtils;
45  import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
46  import com.eviware.soapui.support.scripting.SoapUIScriptEngineRegistry;
47  
48  /***
49   * A MockService for simulation WsdlInterfaces and their operations
50   * 
51   * @author ole.matzura
52   */
53  
54  public class WsdlMockService extends AbstractTestPropertyHolderWsdlModelItem<MockServiceConfig> implements MockService
55  {
56  	private static final String REQUIRE_SOAP_VERSION = WsdlMockService.class.getName() + "@require-soap-version";
57  	private static final String REQUIRE_SOAP_ACTION = WsdlMockService.class.getName() + "@require-soap-action";
58  
59  	public final static String START_SCRIPT_PROPERTY = WsdlMockService.class.getName() + "@startScript";
60     public final static String STOP_SCRIPT_PROPERTY = WsdlMockService.class.getName() + "@stopScript";
61     public static final String INCOMING_WSS = WsdlMockService.class.getName() + "@incoming-wss";
62  	public static final String OUGOING_WSS = WsdlMockService.class.getName() + "@outgoing-wss";
63  	
64  	private List<WsdlMockOperation> mockOperations = new ArrayList<WsdlMockOperation>();
65     private Set<MockRunListener> mockRunListeners = new HashSet<MockRunListener>();
66     private Set<MockServiceListener> mockServiceListeners = new HashSet<MockServiceListener>();
67     private MockServiceIconAnimator iconAnimator;
68  	private WsdlMockRunner mockRunner;
69  	private SoapUIScriptEngine startScriptEngine;
70  	private SoapUIScriptEngine stopScriptEngine;
71  	
72  	public WsdlMockService( Project project, MockServiceConfig config)
73  	{
74  		super( config, project, "/mockService.gif" );
75  		
76  		List<MockOperationConfig> testStepConfigs = config.getMockOperationList();
77        for (MockOperationConfig tsc : testStepConfigs )
78        {
79           WsdlMockOperation testStep = new WsdlMockOperation( this, tsc );
80           mockOperations.add( testStep );
81        }
82        
83        if( !config.isSetPort() || config.getPort() < 1 )
84        	config.setPort( 8080 );
85        
86        if( !config.isSetPath() )
87        	config.setPath( "/" );
88        
89        iconAnimator = new MockServiceIconAnimator();
90        addMockRunListener( iconAnimator );
91        
92        for (MockRunListener listener : SoapUI.getListenerRegistry().getListeners( MockRunListener.class ))
93        {
94            addMockRunListener(listener);
95        }
96        
97        if( !getConfig().isSetProperties() )
98  			getConfig().addNewProperties();
99  		
100 		setPropertiesConfig( getConfig().getProperties() );
101 	}
102 
103 	public void addMockRunListener( MockRunListener listener )
104 	{
105 		mockRunListeners.add( listener );
106 	}
107 
108 	public String getPath()
109 	{
110 		return getConfig().getPath();
111 	}
112 
113 	public WsdlMockOperation getMockOperationAt( int index )
114 	{
115 		return mockOperations.get( index );
116 	}
117 
118 	public WsdlMockOperation getMockOperationByName( String name )
119 	{
120 		return ( WsdlMockOperation ) getWsdlModelItemByName( mockOperations, name );
121 	}
122 
123 	public int getMockOperationCount()
124 	{
125 		return mockOperations.size();
126 	}
127 
128 	public WsdlProject getProject()
129 	{
130 		return ( WsdlProject ) getParent();
131 	}
132 
133 	public int getPort()
134 	{
135 		return getConfig().getPort();
136 	}
137 
138 	public String getHost()
139 	{
140 		return getConfig().getHost();
141 	}
142 	
143 	public void setHost( String host )
144 	{
145 		getConfig().setHost( host );
146 	}
147 	
148 	public boolean getBindToHostOnly()
149 	{
150 		return getConfig().getBindToHostOnly();
151 	}
152 	
153 	public void setBindToHostOnly( boolean bindToHostOnly )
154 	{
155 		getConfig().setBindToHostOnly( bindToHostOnly );
156 	}
157 	
158 	public void removeMockRunListener( MockRunListener listener )
159 	{
160 		mockRunListeners.remove( listener );
161 	}
162 
163 	public WsdlMockRunner start( WsdlTestRunContext context ) throws Exception
164 	{
165 		String path = getPath();
166 		if( path == null || path.trim().length() == 0 || path.trim().charAt( 0 ) != '/' )
167 			throw new Exception( "Invalid path; must start with '/'");
168 		
169 		for( WsdlMockOperation operation : mockOperations )
170 			operation.onStart();
171 		
172 		mockRunner = new WsdlMockRunner( this, context );
173 		return mockRunner;
174 	}
175 
176 	public WsdlMockRunner getMockRunner()
177 	{
178 		return mockRunner;
179 	}
180 
181 	public WsdlMockOperation getMockOperation( Operation operation )
182 	{
183 		for( int c = 0; c < getMockOperationCount(); c++ )
184 		{
185 			WsdlMockOperation mockOperation = mockOperations.get( c );
186 			if( mockOperation.getOperation() == operation )
187 				return mockOperation;
188 		}
189 		
190 		return null;
191 	}
192 
193 	public WsdlMockOperation addNewMockOperation( WsdlOperation operation )
194 	{
195 		if( getMockOperation( operation ) != null )
196 			return null;
197 		
198 		MockOperationConfig config = getConfig().addNewMockOperation();
199 		config.setName( operation.getName() );
200 		WsdlMockOperation mockOperation = new WsdlMockOperation( this, config, operation );
201 		
202 		mockOperations.add( mockOperation );
203 		fireMockOperationAdded( mockOperation );
204 		
205 		return mockOperation;
206 	}
207 
208 	public void setPort( int port )
209 	{
210 		String oldEndpoint = getLocalEndpoint();
211 		
212 		int oldPort = getPort();
213 		if( port != oldPort )
214 		{
215 			getConfig().setPort( port );
216 			notifyPropertyChanged( PORT_PROPERTY, oldPort, port );
217 
218 			for( WsdlInterface iface : getMockedInterfaces())
219 			{
220 				if( Arrays.asList( iface.getEndpoints() ).contains( oldEndpoint ))
221 					iface.changeEndpoint( oldEndpoint, getLocalEndpoint() );
222 			}
223 		}
224 	}
225 
226 	public WsdlInterface [] getMockedInterfaces()
227 	{
228 		Set<WsdlInterface> result = new HashSet<WsdlInterface>();
229 		
230 		for( WsdlMockOperation mockOperation : mockOperations )
231 		{
232 			WsdlOperation operation = mockOperation.getOperation();
233 			if( operation != null )
234 				result.add( operation.getInterface() );
235 		}
236 		
237 		return result.toArray( new WsdlInterface[result.size()] );
238 	}
239 
240 	@Override
241    public void release()
242 	{
243 		super.release();
244 		
245 		for( WsdlMockOperation operation : mockOperations )
246 			operation.release();
247 		
248 		mockServiceListeners.clear();
249 
250 		if( startScriptEngine != null )
251 			startScriptEngine.release();
252 		
253 		if( stopScriptEngine != null )
254 			stopScriptEngine.release();
255 	}
256 	
257 	public void setPath( String path )
258 	{
259 		String oldEndpoint = getLocalEndpoint();
260 		
261 		String oldPath = getPath();
262 		if( !path.equals( oldPath ))
263 		{
264 			getConfig().setPath( path );
265 			notifyPropertyChanged( PATH_PROPERTY, oldPath, path );
266 			
267 			for( WsdlInterface iface : getMockedInterfaces())
268 			{
269 				if( Arrays.asList( iface.getEndpoints() ).contains( oldEndpoint ))
270 					iface.changeEndpoint( oldEndpoint, getLocalEndpoint() );
271 			}
272 		}
273 	}
274 
275 	public MockRunListener [] getMockRunListeners()
276 	{
277 		return mockRunListeners.toArray( new MockRunListener[mockRunListeners.size()] );
278 	}
279 
280 	public void removeMockOperation( WsdlMockOperation mockOperation )
281 	{
282 		int ix = mockOperations.indexOf( mockOperation );
283 		if( ix == -1 )
284 			throw new RuntimeException( "Unkonws MockOperation specified to removeMockOperation" );
285 		
286 		mockOperations.remove( ix );
287 		fireMockOperationRemoved( mockOperation );
288 		mockOperation.release();
289 		getConfig().removeMockOperation( ix );
290 	}
291 
292 	public void addMockServiceListener( MockServiceListener listener )
293 	{
294 		mockServiceListeners.add(  listener  );
295 	}
296 
297 	public void removeMockServiceListener( MockServiceListener listener )
298 	{
299 		mockServiceListeners.remove( listener );
300 	}
301 	
302 	protected void fireMockOperationAdded( WsdlMockOperation mockOperation )
303 	{
304 		MockServiceListener[] listeners = mockServiceListeners.toArray( new MockServiceListener[mockServiceListeners.size()] );
305 		for( MockServiceListener listener : listeners )
306 		{
307 			listener.mockOperationAdded( mockOperation );
308 		}
309 	}
310 	
311 	protected void fireMockOperationRemoved( WsdlMockOperation mockOperation )
312 	{
313 		MockServiceListener[] listeners = mockServiceListeners.toArray( new MockServiceListener[mockServiceListeners.size()] );
314 		for( MockServiceListener listener : listeners )
315 		{
316 			listener.mockOperationRemoved( mockOperation );
317 		}
318 	}
319 	
320 	protected void fireMockResponseAdded( WsdlMockResponse mockResponse )
321 	{
322 		MockServiceListener[] listeners = mockServiceListeners.toArray( new MockServiceListener[mockServiceListeners.size()] );
323 		for( MockServiceListener listener : listeners )
324 		{
325 			listener.mockResponseAdded( mockResponse );
326 		}
327 	}
328 	
329 	protected void fireMockResponseRemoved( WsdlMockResponse mockResponse )
330 	{
331 		MockServiceListener[] listeners = mockServiceListeners.toArray( new MockServiceListener[mockServiceListeners.size()] );
332 		for( MockServiceListener listener : listeners )
333 		{
334 			listener.mockResponseRemoved( mockResponse );
335 		}
336 	}
337 
338 	@Override
339 	public ImageIcon getIcon()
340 	{
341 		return iconAnimator.getIcon();
342 	}
343 
344 	private class MockServiceIconAnimator extends ModelItemIconAnimator implements MockRunListener
345 	{
346 		public MockServiceIconAnimator()
347 		{
348 			super( WsdlMockService.this, "/mockService.gif", 
349 					new String[] {"/mockService_1.gif", "/mockService_2.gif",
350 						"/mockService_3.gif", "/mockService_4.gif"} );
351 		}
352 
353 		public void onMockRequest( MockRunner runner, HttpServletRequest request, HttpServletResponse response )
354 		{
355 		}
356 
357 		public void onMockResult( MockResult result )
358 		{
359 		}
360 
361 		public void onMockRunnerStart( MockRunner mockRunner )
362 		{
363 			start();
364 		}
365 
366 		public void onMockRunnerStop( MockRunner mockRunner )
367 		{
368 			stop();
369 			WsdlMockService.this.mockRunner = null; 
370 		}
371 	}
372 	
373 	public String getLocalEndpoint()
374 	{
375 		String host = getHost();
376 		if( StringUtils.isNullOrEmpty( host ))
377 			host = "127.0.0.1";
378 		
379 		return "http://" + host + ":" + getPort() + getPath();
380 	}
381 
382 	public boolean isRequireSoapVersion()
383 	{
384 		return getSettings().getBoolean( REQUIRE_SOAP_VERSION );
385 	}
386 	
387 	public void setRequireSoapVersion( boolean requireSoapVersion )
388 	{
389 	   getSettings().setBoolean( REQUIRE_SOAP_VERSION, requireSoapVersion );	
390 	}
391 
392 	public boolean isRequireSoapAction()
393 	{
394 		return getSettings().getBoolean( REQUIRE_SOAP_ACTION );
395 	}
396 	
397 	public void setRequireSoapAction( boolean requireSoapAction )
398 	{
399 	   getSettings().setBoolean( REQUIRE_SOAP_ACTION, requireSoapAction );	
400 	}
401 
402 	
403 	public WsdlMockRunner start() throws Exception
404 	{
405 		return start( null );
406 	}
407 
408 	public boolean hasMockOperation( Operation operation )
409 	{
410 		return getMockOperation( operation ) != null;
411 	}
412 
413 	@Override
414 	public void beforeSave()
415 	{
416 		for( WsdlMockOperation mockOperation : mockOperations )
417 			mockOperation.beforeSave();
418 	}
419 	
420 	public void setStartScript( String script )
421    {
422    	String oldScript = getStartScript();
423    	
424    	if( !getConfig().isSetStartScript() )
425    		getConfig().addNewStartScript();
426    	
427    	getConfig().getStartScript().setStringValue( script );
428    	
429    	if( startScriptEngine != null )
430    		startScriptEngine.setScript( script );
431    	
432    	notifyPropertyChanged( START_SCRIPT_PROPERTY, oldScript, script );
433    }
434    
435    public String getStartScript()
436    {
437    	return getConfig().isSetStartScript() ? getConfig().getStartScript().getStringValue() : null;
438    }
439    
440    public void setStopScript( String script )
441    {
442    	String oldScript = getStopScript();
443    	
444    	if( !getConfig().isSetStopScript() )
445    		getConfig().addNewStopScript();
446    	
447    	getConfig().getStopScript().setStringValue( script );
448    	if( stopScriptEngine != null )
449    		stopScriptEngine.setScript( script );
450    	
451    	notifyPropertyChanged( STOP_SCRIPT_PROPERTY, oldScript, script );
452    }
453    
454    public String getStopScript()
455    {
456    	return getConfig().isSetStopScript() ? getConfig().getStopScript().getStringValue() : null;
457    }
458    
459    public Object runStartScript( WsdlMockRunContext runContext, WsdlMockRunner runner ) throws Exception
460 	{
461    	String script = getStartScript();
462 		if( StringUtils.isNullOrEmpty( script ))
463 			return null;
464 		
465 		if( startScriptEngine == null )
466 		{
467 			startScriptEngine = SoapUIScriptEngineRegistry.create( SoapUIScriptEngineRegistry.GROOVY_ID, this );
468 			startScriptEngine.setScript( script );
469 		}
470    	
471 		startScriptEngine.setVariable( "context", runContext );
472 		startScriptEngine.setVariable( "mockRunner", runner );
473 		startScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
474 		return startScriptEngine.run();
475 	}
476 	
477 	public Object runStopScript( WsdlMockRunContext runContext, WsdlMockRunner runner ) throws Exception
478 	{
479 		String script = getStopScript();
480 		if( StringUtils.isNullOrEmpty( script ))
481 			return null;
482 		
483 		if( stopScriptEngine == null )
484 		{
485 			stopScriptEngine = SoapUIScriptEngineRegistry.create( SoapUIScriptEngineRegistry.GROOVY_ID, this );
486 			stopScriptEngine.setScript( script );
487 		}
488 		
489 		stopScriptEngine.setVariable( "context", runContext );
490 		stopScriptEngine.setVariable( "mockRunner", runner );
491 		stopScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
492 		return stopScriptEngine.run();
493 	}
494 
495 	public List<? extends ModelItem> getChildren()
496    {
497       return mockOperations;
498    }
499 
500 	public List<MockOperation> getMockOperationList()
501 	{
502 		return Collections.unmodifiableList( new ArrayList<MockOperation>( mockOperations ));
503 	}
504 	
505 	public String getIncomingWss()
506 	{
507 		return getConfig().getIncomingWss();
508 	}
509 	
510 	public void setIncomingWss( String incomingWss )
511    {
512    	String old = getIncomingWss();
513    	getConfig().setIncomingWss( incomingWss );
514    	notifyPropertyChanged( INCOMING_WSS, old, incomingWss );
515    }
516 	
517 	public String getOutgoingWss()
518 	{
519 		return getConfig().getOutgoingWss();
520 	}
521 	
522 	public void setOutgoingWss( String outgoingWss )
523    {
524    	String old = getOutgoingWss();
525    	getConfig().setOutgoingWss( outgoingWss );
526    	notifyPropertyChanged( OUGOING_WSS, old, outgoingWss );
527    }
528 }