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