View Javadoc

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