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          getConfig().unsetFaultMockOperation();
356       else
357          getConfig().setFaultMockOperation( faultMockOperation.getName() );
358    }
359 
360    private class MockServiceIconAnimator extends ModelItemIconAnimator<WsdlMockService> implements MockRunListener
361    {
362       public MockServiceIconAnimator()
363       {
364          super( WsdlMockService.this, "/mockService.gif", "/mockService", 4, "gif" );
365       }
366 
367       public void onMockRequest( MockRunner runner, HttpServletRequest request, HttpServletResponse response )
368       {
369       }
370 
371       public void onMockResult( MockResult result )
372       {
373       }
374 
375       public void onMockRunnerStart( MockRunner mockRunner )
376       {
377          start();
378       }
379 
380       public void onMockRunnerStop( MockRunner mockRunner )
381       {
382          stop();
383          WsdlMockService.this.mockRunner = null;
384       }
385    }
386 
387    public String getLocalEndpoint()
388    {
389       String host = getHost();
390       if( StringUtils.isNullOrEmpty( host ) )
391          host = "127.0.0.1";
392 
393       return "http://" + host + ":" + getPort() + getPath();
394    }
395 
396    public boolean isRequireSoapVersion()
397    {
398       return getSettings().getBoolean( REQUIRE_SOAP_VERSION );
399    }
400 
401    public void setRequireSoapVersion( boolean requireSoapVersion )
402    {
403       getSettings().setBoolean( REQUIRE_SOAP_VERSION, requireSoapVersion );
404    }
405 
406    public boolean isRequireSoapAction()
407    {
408       return getSettings().getBoolean( REQUIRE_SOAP_ACTION );
409    }
410 
411    public void setRequireSoapAction( boolean requireSoapAction )
412    {
413       getSettings().setBoolean( REQUIRE_SOAP_ACTION, requireSoapAction );
414    }
415 
416    public WsdlMockRunner start() throws Exception
417    {
418       return start( null );
419    }
420 
421    public boolean hasMockOperation( Operation operation )
422    {
423       return getMockOperation( operation ) != null;
424    }
425 
426    public void setStartScript( String script )
427    {
428       String oldScript = getStartScript();
429 
430       if( !getConfig().isSetStartScript() )
431          getConfig().addNewStartScript();
432 
433       getConfig().getStartScript().setStringValue( script );
434 
435       if( startScriptEngine != null )
436          startScriptEngine.setScript( script );
437 
438       notifyPropertyChanged( START_SCRIPT_PROPERTY, oldScript, script );
439    }
440 
441    public String getStartScript()
442    {
443       return getConfig().isSetStartScript() ? getConfig().getStartScript().getStringValue() : null;
444    }
445 
446    public void setStopScript( String script )
447    {
448       String oldScript = getStopScript();
449 
450       if( !getConfig().isSetStopScript() )
451          getConfig().addNewStopScript();
452 
453       getConfig().getStopScript().setStringValue( script );
454       if( stopScriptEngine != null )
455          stopScriptEngine.setScript( script );
456 
457       notifyPropertyChanged( STOP_SCRIPT_PROPERTY, oldScript, script );
458    }
459 
460    public String getStopScript()
461    {
462       return getConfig().isSetStopScript() ? getConfig().getStopScript().getStringValue() : null;
463    }
464 
465    public Object runStartScript( WsdlMockRunContext runContext, WsdlMockRunner runner ) throws Exception
466    {
467       String script = getStartScript();
468       if( StringUtils.isNullOrEmpty( script ) )
469          return null;
470 
471       if( startScriptEngine == null )
472       {
473          startScriptEngine = SoapUIScriptEngineRegistry.create( SoapUIScriptEngineRegistry.GROOVY_ID, this );
474          startScriptEngine.setScript( script );
475       }
476 
477       startScriptEngine.setVariable( "context", runContext );
478       startScriptEngine.setVariable( "mockRunner", runner );
479       startScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
480       return startScriptEngine.run();
481    }
482 
483    public Object runStopScript( WsdlMockRunContext runContext, WsdlMockRunner runner ) throws Exception
484    {
485       String script = getStopScript();
486       if( StringUtils.isNullOrEmpty( script ) )
487          return null;
488 
489       if( stopScriptEngine == null )
490       {
491          stopScriptEngine = SoapUIScriptEngineRegistry.create( SoapUIScriptEngineRegistry.GROOVY_ID, this );
492          stopScriptEngine.setScript( script );
493       }
494 
495       stopScriptEngine.setVariable( "context", runContext );
496       stopScriptEngine.setVariable( "mockRunner", runner );
497       stopScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
498       return stopScriptEngine.run();
499    }
500 
501    public void setOnRequestScript( String script )
502    {
503       String oldScript = getOnRequestScript();
504 
505       if( !getConfig().isSetOnRequestScript() )
506          getConfig().addNewOnRequestScript();
507 
508       getConfig().getOnRequestScript().setStringValue( script );
509 
510       if( onRequestScriptEngine != null )
511          onRequestScriptEngine.setScript( script );
512 
513       notifyPropertyChanged( "onRequestScript", oldScript, script );
514    }
515 
516    public String getOnRequestScript()
517    {
518       return getConfig().isSetOnRequestScript() ? getConfig().getOnRequestScript().getStringValue() : null;
519    }
520 
521    public void setAfterRequestScript( String script )
522    {
523       String oldScript = getAfterRequestScript();
524 
525       if( !getConfig().isSetAfterRequestScript() )
526          getConfig().addNewAfterRequestScript();
527 
528       getConfig().getAfterRequestScript().setStringValue( script );
529       if( afterRequestScriptEngine != null )
530          afterRequestScriptEngine.setScript( script );
531 
532       notifyPropertyChanged( "afterRequestScript", oldScript, script );
533    }
534 
535    public String getAfterRequestScript()
536    {
537       return getConfig().isSetAfterRequestScript() ? getConfig().getAfterRequestScript().getStringValue() : null;
538    }
539 
540    public Object runOnRequestScript( WsdlMockRunContext runContext, WsdlMockRunner runner, WsdlMockRequest mockRequest ) throws Exception
541    {
542       String script = getOnRequestScript();
543       if( StringUtils.isNullOrEmpty( script ) )
544          return null;
545 
546       if( onRequestScriptEngine == null )
547       {
548          onRequestScriptEngine = SoapUIScriptEngineRegistry.create( SoapUIScriptEngineRegistry.GROOVY_ID, this );
549          onRequestScriptEngine.setScript( script );
550       }
551 
552       onRequestScriptEngine.setVariable( "context", runContext );
553       onRequestScriptEngine.setVariable( "mockRequest", mockRequest );
554       onRequestScriptEngine.setVariable( "mockRunner", runner );
555       onRequestScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
556       return onRequestScriptEngine.run();
557    }
558 
559    public Object runAfterRequestScript( WsdlMockRunContext runContext, WsdlMockRunner runner, MockResult mockResult ) throws Exception
560    {
561       String script = getAfterRequestScript();
562       if( StringUtils.isNullOrEmpty( script ) )
563          return null;
564 
565       if( afterRequestScriptEngine == null )
566       {
567          afterRequestScriptEngine = SoapUIScriptEngineRegistry.create( SoapUIScriptEngineRegistry.GROOVY_ID, this );
568          afterRequestScriptEngine.setScript( script );
569       }
570 
571       afterRequestScriptEngine.setVariable( "context", runContext );
572       afterRequestScriptEngine.setVariable( "mockResult", mockResult );
573       afterRequestScriptEngine.setVariable( "mockRunner", runner );
574       afterRequestScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
575       return afterRequestScriptEngine.run();
576    }
577 
578    public List<? extends ModelItem> getChildren()
579    {
580       return mockOperations;
581    }
582 
583    public List<MockOperation> getMockOperationList()
584    {
585       return Collections.unmodifiableList( new ArrayList<MockOperation>( mockOperations ) );
586    }
587 
588    public String getIncomingWss()
589    {
590       return getConfig().getIncomingWss();
591    }
592 
593    public void setIncomingWss( String incomingWss )
594    {
595       String old = getIncomingWss();
596       getConfig().setIncomingWss( incomingWss );
597       notifyPropertyChanged( INCOMING_WSS, old, incomingWss );
598    }
599 
600    public String getOutgoingWss()
601    {
602       return getConfig().getOutgoingWss();
603    }
604 
605    public void setOutgoingWss( String outgoingWss )
606    {
607       String old = getOutgoingWss();
608       getConfig().setOutgoingWss( outgoingWss );
609       notifyPropertyChanged( OUGOING_WSS, old, outgoingWss );
610    }
611 
612    public boolean isDispatchResponseMessages()
613    {
614       return getConfig().getDispatchResponseMessages();
615    }
616 
617    public void setDispatchResponseMessages( boolean dispatchResponseMessages )
618    {
619       boolean old = isDispatchResponseMessages();
620       getConfig().setDispatchResponseMessages( dispatchResponseMessages );
621       notifyPropertyChanged( "dispatchResponseMessages", old, dispatchResponseMessages );
622    }
623 
624    public List<WsdlOperation> getMockedOperations()
625    {
626       List<WsdlOperation> result = new ArrayList<WsdlOperation>();
627 
628       for( WsdlMockOperation mockOperation : mockOperations )
629          result.add( mockOperation.getOperation() );
630 
631       return result;
632    }
633 
634    public void setDocroot( String docroot )
635    {
636       docrootProperty.set( docroot, true );
637    }
638 
639    public String getDocroot()
640    {
641       return docrootProperty.get();
642    }
643 
644    @Override
645    public void resolve( ResolveContext context )
646    {
647       super.resolve( context );
648       docrootProperty.resolveFile( context, "Missing MockService docroot" );
649    }
650 
651    public void replace( WsdlMockOperation mockOperation, MockOperationConfig reloadedMockOperation )
652    {
653       int ix = mockOperations.indexOf( mockOperation );
654       if( ix == -1 )
655          throw new RuntimeException( "Unkonws MockOperation specified to removeMockOperation" );
656 
657       mockOperations.remove( ix );
658       fireMockOperationRemoved( mockOperation );
659       mockOperation.release();
660       getConfig().removeMockOperation( ix );
661 
662       MockOperationConfig newConfig = (MockOperationConfig) getConfig().insertNewMockOperation( ix )
663               .set( reloadedMockOperation ).changeType( MockOperationConfig.type );
664       WsdlMockOperation newOperation = new WsdlMockOperation( this, newConfig );
665       mockOperations.add( ix, newOperation );
666       newOperation.afterLoad();
667       fireMockOperationAdded( newOperation );
668    }
669 
670 }