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