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.MockOperationDispatchStyleConfig;
18  import com.eviware.soapui.config.MockResponseConfig;
19  import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
20  import com.eviware.soapui.impl.wsdl.WsdlInterface;
21  import com.eviware.soapui.impl.wsdl.WsdlOperation;
22  import com.eviware.soapui.impl.wsdl.mock.dispatch.MockOperationDispatchRegistry;
23  import com.eviware.soapui.impl.wsdl.mock.dispatch.MockOperationDispatcher;
24  import com.eviware.soapui.impl.wsdl.support.CompressedStringSupport;
25  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
26  import com.eviware.soapui.model.ModelItem;
27  import com.eviware.soapui.model.iface.Interface;
28  import com.eviware.soapui.model.iface.Operation;
29  import com.eviware.soapui.model.mock.MockOperation;
30  import com.eviware.soapui.model.mock.MockResponse;
31  import com.eviware.soapui.model.support.InterfaceListenerAdapter;
32  import com.eviware.soapui.model.support.ProjectListenerAdapter;
33  import com.eviware.soapui.settings.WsdlSettings;
34  import com.eviware.soapui.support.UISupport;
35  import org.apache.log4j.Logger;
36  
37  import javax.swing.*;
38  import java.beans.PropertyChangeEvent;
39  import java.beans.PropertyChangeListener;
40  import java.util.ArrayList;
41  import java.util.List;
42  
43  /***
44   * A WsdlMockOperation in a WsdlMockService
45   *
46   * @author ole.matzura
47   */
48  
49  public class WsdlMockOperation extends AbstractWsdlModelItem<MockOperationConfig> implements MockOperation, PropertyChangeListener
50  {
51     private final static Logger log = Logger.getLogger( WsdlMockOperation.class );
52  
53     public final static String DISPATCH_STYLE_PROPERTY = WsdlMockOperation.class.getName() + "@dispatchstyle";
54     public final static String DEFAULT_RESPONSE_PROPERTY = WsdlMockOperation.class.getName() + "@defaultresponse";
55     public final static String DISPATCH_PATH_PROPERTY = WsdlMockOperation.class.getName() + "@dispatchpath";
56     public final static String OPERATION_PROPERTY = WsdlMockOperation.class.getName() + "@operation";
57  
58     private WsdlOperation operation;
59     private MockOperationDispatcher dispatcher;
60     private List<WsdlMockResponse> responses = new ArrayList<WsdlMockResponse>();
61     private InternalInterfaceListener interfaceListener = new InternalInterfaceListener();
62     private InternalProjectListener projectListener = new InternalProjectListener();
63     private ImageIcon oneWayIcon;
64     private ImageIcon notificationIcon;
65     private ImageIcon solicitResponseIcon;
66  
67     public WsdlMockOperation( WsdlMockService mockService, MockOperationConfig config )
68     {
69        super( config, mockService, "/mockOperation.gif" );
70  
71        Interface iface = mockService.getProject().getInterfaceByName( config.getInterface() );
72        if( iface == null )
73        {
74           SoapUI.log.warn( "Missing interface [" + config.getInterface() +
75                   "] for MockOperation in project" );
76        }
77        else
78        {
79           operation = (WsdlOperation) iface.getOperationByName( config.getOperation() );
80        }
81  
82        List<MockResponseConfig> responseConfigs = config.getResponseList();
83        for( MockResponseConfig responseConfig : responseConfigs )
84        {
85           WsdlMockResponse wsdlMockResponse = new WsdlMockResponse( this, responseConfig );
86           wsdlMockResponse.addPropertyChangeListener( this );
87           responses.add( wsdlMockResponse );
88        }
89  
90        initData( config );
91     }
92  
93     private void initData( MockOperationConfig config )
94     {
95        if( !config.isSetName() )
96           config.setName( operation == null ? "<missing operation>" : operation.getName() );
97  
98        if( !config.isSetDefaultResponse() && responses.size() > 0 )
99           setDefaultResponse( responses.get( 0 ).getName() );
100 
101       if( !config.isSetDispatchStyle() )
102          config.setDispatchStyle( MockOperationDispatchStyleConfig.SEQUENCE );
103 
104       if( !getConfig().isSetDispatchConfig() )
105          getConfig().addNewDispatchConfig();
106 
107       dispatcher = MockOperationDispatchRegistry.buildDispatcher( config.getDispatchStyle().toString(), this );
108 
109       if( operation != null )
110       {
111          operation.getInterface().getProject().addProjectListener( projectListener );
112          operation.getInterface().addInterfaceListener( interfaceListener );
113          operation.getInterface().addPropertyChangeListener( WsdlInterface.NAME_PROPERTY, this );
114       }
115 
116       oneWayIcon = UISupport.createImageIcon( "/onewaymockoperation.gif" );
117       notificationIcon = UISupport.createImageIcon( "/mocknotificationoperation.gif" );
118       solicitResponseIcon = UISupport.createImageIcon( "/mocksolicitresponseoperation.gif" );
119    }
120 
121    public WsdlMockOperation( WsdlMockService mockService, MockOperationConfig config, WsdlOperation operation )
122    {
123       super( config, mockService, "/mockOperation.gif" );
124       this.operation = operation;
125 
126       config.setInterface( operation.getInterface().getName() );
127       config.setOperation( operation.getName() );
128 
129       initData( config );
130       interfaceListener = new InternalInterfaceListener();
131    }
132 
133    @Override
134    public ImageIcon getIcon()
135    {
136       if( operation != null )
137       {
138          if( isOneWay() )
139          {
140             return oneWayIcon;
141          }
142          else if( isNotification() )
143          {
144             return notificationIcon;
145          }
146          else if( isSolicitResponse() )
147          {
148             return solicitResponseIcon;
149          }
150       }
151 
152       return super.getIcon();
153    }
154 
155    public WsdlMockService getMockService()
156    {
157       return (WsdlMockService) getParent();
158    }
159 
160    public WsdlMockResponse getMockResponseAt( int index )
161    {
162       return responses.get( index );
163    }
164 
165    public WsdlOperation getOperation()
166    {
167       return operation;
168    }
169 
170    public WsdlMockResponse getMockResponseByName( String name )
171    {
172       return (WsdlMockResponse) getWsdlModelItemByName( responses, name );
173    }
174 
175    public int getMockResponseCount()
176    {
177       return responses.size();
178    }
179 
180    public WsdlMockResponse addNewMockResponse( MockResponseConfig responseConfig )
181    {
182       WsdlMockResponse mockResponse = new WsdlMockResponse( this, responseConfig );
183 
184       responses.add( mockResponse );
185       if( responses.size() == 1 )
186          setDefaultResponse( mockResponse.getName() );
187 
188       //add ws-a action
189       WsdlUtils.setDefaultWsaAction( mockResponse.getWsaConfig(), true );
190 
191       ( getMockService() ).fireMockResponseAdded( mockResponse );
192       notifyPropertyChanged( "mockResponses", null, mockResponse );
193 
194       return mockResponse;
195    }
196 
197    public WsdlMockResponse addNewMockResponse( String name, boolean createResponse )
198    {
199       MockResponseConfig responseConfig = getConfig().addNewResponse();
200       responseConfig.setName( name );
201       responseConfig.addNewResponseContent();
202 
203       if( createResponse && getOperation() != null && getOperation().isBidirectional() )
204       {
205          boolean createOptional = SoapUI.getSettings().getBoolean( WsdlSettings.XML_GENERATION_ALWAYS_INCLUDE_OPTIONAL_ELEMENTS );
206          CompressedStringSupport.setString( responseConfig.getResponseContent(), getOperation().createResponse( createOptional ) );
207       }
208 
209       return addNewMockResponse( responseConfig );
210    }
211 
212    public void removeMockResponse( WsdlMockResponse mockResponse )
213    {
214       int ix = responses.indexOf( mockResponse );
215       responses.remove( ix );
216       mockResponse.removePropertyChangeListener( this );
217 
218       try
219       {
220          ( getMockService() ).fireMockResponseRemoved( mockResponse );
221       }
222       finally
223       {
224          mockResponse.release();
225          getConfig().removeResponse( ix );
226       }
227    }
228 
229    public WsdlMockResult dispatchRequest( WsdlMockRequest request ) throws DispatchException
230    {
231       try
232       {
233          request.setOperation( getOperation() );
234          WsdlMockResult result = new WsdlMockResult( request );
235 
236          if( getMockResponseCount() == 0 )
237             throw new DispatchException( "Missing MockResponse(s) in MockOperation [" + getName() + "]" );
238 
239          result.setMockOperation( this );
240          WsdlMockResponse response = dispatcher.selectMockResponse( request, result );
241          if( response == null )
242          {
243             response = getMockResponseByName( getDefaultResponse() );
244          }
245 
246          if( response == null )
247          {
248             throw new DispatchException( "Failed to find MockResponse" );
249          }
250 
251          result.setMockResponse( response );
252          response.execute( request, result );
253 
254          return result;
255       }
256       catch( Throwable e )
257       {
258          if( e instanceof DispatchException )
259             throw (DispatchException) e;
260          else
261             throw new DispatchException( e );
262       }
263    }
264 
265    @Override
266    public void release()
267    {
268       super.release();
269 
270       if( dispatcher != null )
271          dispatcher.release();
272 
273       for( WsdlMockResponse response : responses )
274       {
275          response.removePropertyChangeListener( this );
276          response.release();
277       }
278 
279       if( operation != null )
280       {
281          operation.getInterface().getProject().removeProjectListener( projectListener );
282          operation.getInterface().removeInterfaceListener( interfaceListener );
283          operation.getInterface().removePropertyChangeListener( WsdlInterface.NAME_PROPERTY, this );
284       }
285    }
286 
287    public String getDispatchStyle()
288    {
289       return String.valueOf( getConfig().isSetDispatchStyle() ? getConfig().getDispatchStyle() : MockOperationDispatchStyleConfig.SEQUENCE );
290    }
291 
292    public MockOperationDispatcher setDispatchStyle( String dispatchStyle )
293    {
294       String old = getDispatchStyle();
295       if( dispatcher != null && dispatchStyle.equals( old ) )
296          return dispatcher;
297 
298       getConfig().setDispatchStyle( MockOperationDispatchStyleConfig.Enum.forString( dispatchStyle ) );
299 
300       if( dispatcher != null )
301       {
302          dispatcher.release();
303       }
304 
305       if( !getConfig().isSetDispatchConfig() )
306          getConfig().addNewDispatchConfig();
307 
308       dispatcher = MockOperationDispatchRegistry.buildDispatcher( dispatchStyle, this );
309 
310       notifyPropertyChanged( DISPATCH_STYLE_PROPERTY, old, dispatchStyle );
311 
312       return dispatcher;
313    }
314 
315    public String getDispatchPath()
316    {
317       return getConfig().getDispatchPath();
318    }
319 
320    public void setDispatchPath( String dispatchPath )
321    {
322       String old = getDispatchPath();
323       getConfig().setDispatchPath( dispatchPath );
324       notifyPropertyChanged( DISPATCH_PATH_PROPERTY, old, dispatchPath );
325    }
326 
327    public String getWsdlOperationName()
328    {
329       return operation == null ? null : operation.getName();
330    }
331 
332    public String getDefaultResponse()
333    {
334       return getConfig().getDefaultResponse();
335    }
336 
337    public void setDefaultResponse( String defaultResponse )
338    {
339       String old = getDefaultResponse();
340       getConfig().setDefaultResponse( defaultResponse );
341       notifyPropertyChanged( DEFAULT_RESPONSE_PROPERTY, old, defaultResponse );
342    }
343 
344    public List<MockResponse> getMockResponses()
345    {
346       return new ArrayList<MockResponse>( responses );
347    }
348 
349    public void propertyChange( PropertyChangeEvent arg0 )
350    {
351       if( arg0.getPropertyName().equals( WsdlMockResponse.NAME_PROPERTY ) )
352       {
353          if( arg0.getOldValue().equals( getDefaultResponse() ) )
354             setDefaultResponse( arg0.getNewValue().toString() );
355       }
356       else if( arg0.getPropertyName().equals( WsdlInterface.NAME_PROPERTY ) )
357       {
358          getConfig().setInterface( arg0.getNewValue().toString() );
359       }
360    }
361 
362    public WsdlMockResult getLastMockResult()
363    {
364       WsdlMockResult result = null;
365 
366       for( WsdlMockResponse response : responses )
367       {
368          WsdlMockResult mockResult = response.getMockResult();
369          if( mockResult != null )
370          {
371             if( result == null || result.getTimestamp() > mockResult.getTimestamp() )
372                result = mockResult;
373          }
374       }
375 
376       return result;
377    }
378 
379    public void setOperation( WsdlOperation operation )
380    {
381       WsdlOperation oldOperation = getOperation();
382 
383       if( operation == null )
384       {
385          getConfig().unsetInterface();
386          getConfig().unsetOperation();
387       }
388       else
389       {
390          getConfig().setInterface( operation.getInterface().getName() );
391          getConfig().setOperation( operation.getName() );
392       }
393 
394       this.operation = operation;
395 
396       notifyPropertyChanged( OPERATION_PROPERTY, oldOperation, operation );
397    }
398 
399    public MockOperationDispatcher getMockOperationDispatcher()
400    {
401       return dispatcher;
402    }
403 
404    private class InternalInterfaceListener extends InterfaceListenerAdapter
405    {
406       @Override
407       public void operationUpdated( Operation operation )
408       {
409          if( operation == WsdlMockOperation.this.operation )
410             getConfig().setOperation( operation.getName() );
411       }
412 
413       @Override
414       public void operationRemoved( Operation operation )
415       {
416          if( operation == WsdlMockOperation.this.operation )
417             getMockService().removeMockOperation( WsdlMockOperation.this );
418       }
419    }
420 
421    private class InternalProjectListener extends ProjectListenerAdapter
422    {
423       @Override
424       public void interfaceRemoved( Interface iface )
425       {
426          if( operation.getInterface() == iface )
427             getMockService().removeMockOperation( WsdlMockOperation.this );
428       }
429 
430       @Override
431       public void interfaceUpdated( Interface iface )
432       {
433          if( operation.getInterface() == iface )
434             getConfig().setInterface( iface.getName() );
435       }
436    }
437 
438    public boolean isOneWay()
439    {
440       return operation == null ? false : operation.isOneWay();
441    }
442 
443    public boolean isNotification()
444    {
445       return operation == null ? false : operation.isNotification();
446    }
447 
448    public boolean isSolicitResponse()
449    {
450       return operation == null ? false : operation.isSolicitResponse();
451    }
452 
453    public boolean isUnidirectional()
454    {
455       return operation == null ? false : operation.isUnidirectional();
456    }
457 
458    public boolean isBidirectional()
459    {
460       return !isUnidirectional();
461    }
462 
463    public List<? extends ModelItem> getChildren()
464    {
465       return responses;
466    }
467 }