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.teststeps;
14  
15  import com.eviware.soapui.config.AsyncResponseStepConfig;
16  import com.eviware.soapui.config.MockResponseConfig;
17  import com.eviware.soapui.config.TestAssertionConfig;
18  import com.eviware.soapui.config.TestStepConfig;
19  import com.eviware.soapui.impl.wsdl.*;
20  import com.eviware.soapui.impl.wsdl.mock.*;
21  import com.eviware.soapui.impl.wsdl.panels.mockoperation.WsdlMockResultMessageExchange;
22  import com.eviware.soapui.impl.wsdl.support.assertions.AssertableConfig;
23  import com.eviware.soapui.impl.wsdl.support.assertions.AssertedXPathsContainer;
24  import com.eviware.soapui.impl.wsdl.support.assertions.AssertionsSupport;
25  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
26  import com.eviware.soapui.impl.wsdl.teststeps.assertions.TestAssertionRegistry;
27  import com.eviware.soapui.model.ModelItem;
28  import com.eviware.soapui.model.iface.Interface;
29  import com.eviware.soapui.model.iface.Operation;
30  import com.eviware.soapui.model.iface.SubmitContext;
31  import com.eviware.soapui.model.mock.MockResult;
32  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
33  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
34  import com.eviware.soapui.model.support.*;
35  import com.eviware.soapui.model.testsuite.*;
36  import com.eviware.soapui.model.testsuite.AssertionError;
37  import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
38  import com.eviware.soapui.support.UISupport;
39  import com.eviware.soapui.support.types.StringToStringMap;
40  import org.apache.log4j.Logger;
41  
42  import javax.swing.*;
43  import java.beans.PropertyChangeEvent;
44  import java.beans.PropertyChangeListener;
45  import java.util.*;
46  
47  // TODO Ericsson: Move WsdlAsyncResponseTestStep to pro?
48  public class WsdlAsyncResponseTestStep extends WsdlTestStepWithProperties implements PropertyChangeListener, Assertable
49  {
50     private static final Logger log = Logger.getLogger( WsdlAsyncResponseTestStep.class );
51  
52     public static final String STATUS_PROPERTY = WsdlAsyncResponseTestStep.class.getName() + "@status";
53     public static final String TIMEOUT_PROPERTY = WsdlAsyncResponseTestStep.class.getName() + "@timeout";
54     public static final String MATCHING_VALUE_PROPERTY = WsdlAsyncResponseTestStep.class.getName() + "@matchingValue";
55  
56     private AsyncResponseStepConfig testStepConfig;
57     private MockResponseConfig mockResponseConfig;
58     private WsdlMockOperation mockOperation;
59     private WsdlMockService mockService;
60     private WsdlMockResponse mockResponse;
61  
62     private AssertionsSupport assertionsSupport;
63     private InternalMockRunListener listener;
64  
65     private final InternalProjectListener projectListener = new InternalProjectListener();
66     private final InternalInterfaceListener interfaceListener = new InternalInterfaceListener();
67     private WsdlInterface iface;
68     private AssertionStatus oldStatus;
69  
70     /***
71      * Constructor
72      *
73      * @param testCase
74      * @param config
75      * @param forLoadTest
76      */
77     public WsdlAsyncResponseTestStep( WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest )
78     {
79        super( testCase, config, true, forLoadTest );
80  
81        if( config.getConfig() != null )
82        {
83           testStepConfig = (AsyncResponseStepConfig) config.getConfig().changeType( AsyncResponseStepConfig.type );
84           mockResponseConfig = testStepConfig.getResponse();
85        }
86        else
87        {
88           testStepConfig = (AsyncResponseStepConfig) config.addNewConfig().changeType( AsyncResponseStepConfig.type );
89           mockResponseConfig = testStepConfig.addNewResponse();
90        }
91  
92        assertionsSupport = new AssertionsSupport( this, new AssertableConfig()
93        {
94  
95           public TestAssertionConfig addNewAssertion()
96           {
97              return testStepConfig.addNewAssertion();
98           }
99  
100          public List<TestAssertionConfig> getAssertionList()
101          {
102             return testStepConfig.getAssertionList();
103          }
104 
105          public void removeAssertion( int ix )
106          {
107             testStepConfig.removeAssertion( ix );
108          }
109       } );
110 
111       createMockService();
112 
113       if( !forLoadTest )
114       {
115          setIcon( UISupport.createImageIcon( "/asyncResponseStep.gif" ) );
116          if( iface != null )
117          {
118             iface.getProject().addProjectListener( projectListener );
119             iface.addInterfaceListener( interfaceListener );
120          }
121       }
122 
123       addProperty( new TestStepBeanProperty( "Response", false, mockResponse, "responseContent", this ) );
124       addProperty( new DefaultTestStepProperty( "Request", true, new DefaultTestStepProperty.PropertyHandlerAdapter()
125       {
126          public String getValue( DefaultTestStepProperty property )
127          {
128             WsdlMockResult mockResult = getMockResponse().getMockResult();
129             if( mockResult == null )
130             {
131                return null;
132             }
133             else
134             {
135                return mockResult.getMockRequest().getRequestContent();
136             }
137          }
138       }, this ) );
139 
140       addProperty( new TestStepBeanProperty( "Matching Value", false, this, "matchingValue", this ) );
141    }
142 
143    public void resetConfigOnMove( TestStepConfig config )
144    {
145       super.resetConfigOnMove( config );
146 
147       testStepConfig = (AsyncResponseStepConfig) config.getConfig().changeType( AsyncResponseStepConfig.type );
148       mockResponseConfig = this.testStepConfig.getResponse();
149       mockResponse.setConfig( mockResponseConfig );
150 
151       assertionsSupport.refresh();
152    }
153 
154    public boolean cancel()
155    {
156       if( listener != null )
157       {
158          listener.cancel();
159       }
160 
161       return true;
162    }
163 
164    public void createMockService()
165    {
166       WsdlProject project = getTestCase().getTestSuite().getProject();
167       MockRunnerManager manager = MockRunnerManagerImpl.getInstance( getTestCase() );
168 
169       mockService = manager.getMockService( getPort(), getPath() );
170 
171       iface = (WsdlInterface) project.getInterfaceByName( testStepConfig.getInterface() );
172       iface.addInterfaceListener( interfaceListener );
173 
174       WsdlOperation operation = iface.getOperationByName( testStepConfig.getOperation() );
175       mockOperation = mockService.getMockOperation( operation );
176       if( mockOperation == null )
177          mockOperation = mockService.addNewMockOperation( operation );
178    //   mockOperation.setDispatchStyle( DispatchStyleConfig.QUERY_MATCH );
179       mockResponse = mockOperation.addNewMockResponse( mockResponseConfig );
180       mockResponse.addPropertyChangeListener( this );
181 
182       listener = new InternalMockRunListener();
183       mockService.addMockRunListener( listener );
184    }
185 
186    public TestStepResult run( TestRunner testRunner, TestRunContext context )
187    {
188       WsdlMockResponse oldResponse = getMockResponse();
189       mockResponse = null; //mockOperation.addNewMockResponse( getRequestQuery(), getMatchingValue() );
190       mockResponse.setConfig( oldResponse.getConfig() );
191 
192       WsdlSingleMessageExchangeTestStepResult result = new WsdlSingleMessageExchangeTestStepResult( this );
193 
194       result.startTimer();
195       long timeout = getTimeout();
196 
197       synchronized( listener )
198       {
199          long start = System.currentTimeMillis();
200          do
201          {
202             try
203             {
204                listener.wait( timeout );
205             }
206             catch( InterruptedException e )
207             {
208                // Do nothing
209             }
210 
211             timeout -= ( System.currentTimeMillis() - start );
212          }
213          while( timeout > 0 );
214       }
215 
216       if( listener.getResult() != null )
217       {
218          AssertedWsdlMockResultMessageExchange messageExchange = new AssertedWsdlMockResultMessageExchange( listener
219                  .getResult() );
220 
221          result.setMessageExchange( messageExchange );
222 
223          context.setProperty( AssertedXPathsContainer.ASSERTEDXPATHSCONTAINER_PROPERTY, messageExchange );
224          updateAssertionStatus( listener.getResult(), ( ( context ) ) );
225       }
226 
227       result.stopTimer();
228 
229       if( listener.getResult() == null )
230       {
231          if( listener.isCanceled() )
232          {
233             result.setStatus( TestStepStatus.CANCELED );
234          }
235          else
236          {
237             result.setStatus( TestStepStatus.FAILED );
238             result.addMessage( ( new StringBuilder() ).append( "Timeout occured after " ).append( timeout ).append(
239                     " milliseconds" ).toString() );
240          }
241       }
242       else if( getAssertionStatus() == AssertionStatus.FAILED )
243       {
244          result.setStatus( TestStepStatus.FAILED );
245          if( getAssertionCount() == 0 )
246          {
247             result.addMessage( "Invalid/empty request" );
248          }
249          else
250          {
251             for( int i = 0; i < getAssertionCount(); i++ )
252             {
253                AssertionError assertionErrors[] = getAssertionAt( i ).getErrors();
254                if( assertionErrors != null )
255                {
256                   for( int j = 0; j < assertionErrors.length; j++ )
257                   {
258                      AssertionError assertionError = assertionErrors[j];
259                      result.addMessage( assertionError.getMessage() );
260                   }
261                }
262             }
263          }
264       }
265       else
266       {
267          result.setStatus( TestStepStatus.OK );
268       }
269 
270       return result;
271    }
272 
273    private void updateAssertionStatus( WsdlMockResult mockResult, SubmitContext submitContext )
274    {
275       if( oldStatus == null )
276       {
277          oldStatus = getAssertionStatus();
278       }
279 
280       for( int i = 0; i < getAssertionCount(); i++ )
281       {
282          WsdlMessageAssertion assertion = getAssertionAt( i );
283          if( !assertion.isDisabled() )
284             assertion.assertRequest( new WsdlMockResultMessageExchange( mockResult, getMockResponse() ), submitContext );
285       }
286 
287       AssertionStatus newAssertionStatus = getAssertionStatus();
288       if( newAssertionStatus != oldStatus )
289       {
290          notifyPropertyChanged( STATUS_PROPERTY, oldStatus, newAssertionStatus );
291          oldStatus = newAssertionStatus;
292       }
293    }
294 
295    public void finish( TestRunner testrunner, TestRunContext testruncontext )
296    {
297    }
298 
299    public WsdlMockResponse getMockResponse()
300    {
301       return mockResponse;
302    }
303 
304    public void setPort( int port )
305    {
306       mockService.setPort( port );
307       testStepConfig.setPort( port );
308    }
309 
310    public int getPort()
311    {
312       return testStepConfig.getPort();
313    }
314 
315    public void setPath( String path )
316    {
317       mockService.setPath( path );
318       testStepConfig.setPath( path );
319    }
320 
321    public String getPath()
322    {
323       return testStepConfig.getPath();
324    }
325 
326    public void setRequestQuery( String query )
327    {
328       testStepConfig.setRequestQuery( query );
329    }
330 
331    public String getRequestQuery()
332    {
333       return testStepConfig.getRequestQuery();
334    }
335 
336    public void setMatchingValue( String value )
337    {
338       // Make sure matching value is never null.
339       if( value == null )
340       {
341          value = "";
342       }
343 
344       String oldValue = testStepConfig.getMatchingValue();
345 
346       if( !value.equals( oldValue ) )
347       {
348          testStepConfig.setMatchingValue( value );
349          notifyPropertyChanged( MATCHING_VALUE_PROPERTY, oldValue, value );
350       }
351    }
352 
353    public String getMatchingValue()
354    {
355       return testStepConfig.getMatchingValue();
356    }
357 
358    public long getContentLength()
359    {
360       if( mockResponse == null )
361       {
362          return 0;
363       }
364       else
365       {
366          return mockResponse.getContentLength();
367       }
368    }
369 
370    public String getEncoding()
371    {
372       return mockResponse.getEncoding();
373    }
374 
375    public void setEncoding( String encoding )
376    {
377       mockResponse.setEncoding( encoding );
378    }
379 
380    public boolean isMtomEnabled()
381    {
382       return mockResponse.isMtomEnabled();
383    }
384 
385    public void setMtomEnabled( boolean mtomEnabled )
386    {
387       mockResponse.setMtomEnabled( mtomEnabled );
388    }
389 
390    public String getOutgoingWss()
391    {
392       return mockResponse.getOutgoingWss();
393    }
394 
395    public void setOutgoingWss( String outgoingWss )
396    {
397       mockResponse.setOutgoingWss( outgoingWss );
398    }
399 
400    public boolean isForceMtom()
401    {
402       return mockResponse.isForceMtom();
403    }
404 
405    public void setForceMtom( boolean forceMtom )
406    {
407       mockResponse.setForceMtom( forceMtom );
408    }
409 
410    public boolean isInlineFilesEnabled()
411    {
412       return mockResponse.isInlineFilesEnabled();
413    }
414 
415    public void setInlineFilesEnabled( boolean inlineFilesEnabled )
416    {
417       mockResponse.setInlineFilesEnabled( inlineFilesEnabled );
418    }
419 
420    public boolean isMultipartEnabled()
421    {
422       return mockResponse.isMultipartEnabled();
423    }
424 
425    public void setMultipartEnabled( boolean multipartEnabled )
426    {
427       mockResponse.setMultipartEnabled( multipartEnabled );
428    }
429 
430    public long getResponseDelay()
431    {
432       return mockResponse.getResponseDelay();
433    }
434 
435    public void setResponseDelay( long delay )
436    {
437       mockResponse.setResponseDelay( delay );
438    }
439 
440    public String getResponseHttpStatus()
441    {
442       return mockResponse.getResponseHttpStatus();
443    }
444 
445    public void setResponseHttpStatus( String status )
446    {
447       mockResponse.setResponseHttpStatus( status );
448    }
449 
450    public boolean isEncodeAttachments()
451    {
452       return mockResponse.isEncodeAttachments();
453    }
454 
455    public boolean isRemoveEmptyContent()
456    {
457       return mockResponse.isRemoveEmptyContent();
458    }
459 
460    public boolean isStripWhitespaces()
461    {
462       return mockResponse.isStripWhitespaces();
463    }
464 
465    public void setEncodeAttachments( boolean encodeAttachments )
466    {
467       mockResponse.setEncodeAttachments( encodeAttachments );
468    }
469 
470    public void setRemoveEmptyContent( boolean removeEmptyContent )
471    {
472       mockResponse.setRemoveEmptyContent( removeEmptyContent );
473    }
474 
475    public void setStripWhitespaces( boolean stripWhitespaces )
476    {
477       mockResponse.setStripWhitespaces( stripWhitespaces );
478    }
479 
480    public void propertyChange( PropertyChangeEvent event )
481    {
482       if( event.getSource() == mockResponse )
483       {
484          mockResponseConfig.set( mockResponse.getConfig() );
485 
486          notifyPropertyChanged( event.getPropertyName(), event.getOldValue(), event.getNewValue() );
487       }
488       /*
489          * else if (event.getSource() == this) { if
490          * (event.getPropertyName().equals(MATCHING_VALUE_PROPERTY)) {
491          * testStepConfig.setMatchingValue((String) event.getNewValue());
492          * notifyPropertyChanged(event.getPropertyName(), event.getOldValue(),
493          * event.getNewValue()); } }
494          */
495    }
496 
497    public WsdlMessageAssertion addAssertion( String assertion )
498    {
499       PropertyChangeNotifier notifier = new PropertyChangeNotifier();
500 
501       TestAssertionConfig assertionConfig = testStepConfig.addNewAssertion();
502       assertionConfig.setType( TestAssertionRegistry.getInstance().getAssertionTypeForName( assertion ) );
503 
504       WsdlMessageAssertion messageAssertion = assertionsSupport.addWsdlAssertion( assertionConfig );
505 
506       assertionsSupport.fireAssertionAdded( messageAssertion );
507 
508       if( getMockResponse().getMockResult() != null )
509       {
510          messageAssertion.assertRequest( new WsdlMockResultMessageExchange( getMockResponse().getMockResult(),
511                  getMockResponse() ), new WsdlSubmitContext( this ) );
512          notifier.notifyChange();
513       }
514 
515       return messageAssertion;
516    }
517 
518    public void addAssertionsListener( AssertionsListener listener )
519    {
520       assertionsSupport.addAssertionsListener( listener );
521    }
522 
523    public WsdlMessageAssertion getAssertionAt( int i )
524    {
525       return assertionsSupport.getAssertionAt( i );
526    }
527 
528    public int getAssertionCount()
529    {
530       return assertionsSupport.getAssertionCount();
531    }
532 
533    public void removeAssertionsListener( AssertionsListener listener )
534    {
535       assertionsSupport.removeAssertionsListener( listener );
536    }
537 
538    public AssertionStatus getAssertionStatus()
539    {
540       AssertionStatus currentStatus = AssertionStatus.UNKNOWN;
541       int i = getAssertionCount();
542       if( i == 0 )
543       {
544          return currentStatus;
545       }
546 
547       int j = 0;
548       do
549       {
550          if( j >= i )
551          {
552             break;
553          }
554 
555          WsdlMessageAssertion assertion = getAssertionAt( j );
556          if( !assertion.isDisabled() && assertion.getStatus() == AssertionStatus.FAILED )
557          {
558             currentStatus = AssertionStatus.FAILED;
559             break;
560          }
561 
562          j++;
563       }
564       while( true );
565 
566       if( currentStatus == AssertionStatus.UNKNOWN )
567       {
568          currentStatus = AssertionStatus.VALID;
569       }
570 
571       return currentStatus;
572    }
573 
574    public void removeAssertion( TestAssertion assertion )
575    {
576       PropertyChangeNotifier notifier = new PropertyChangeNotifier();
577 
578       assertionsSupport.removeAssertion( (WsdlMessageAssertion) assertion );
579 
580       notifier.notifyChange();
581    }
582 
583    public String getAssertableContent()
584    {
585       WsdlMockResult result = getMockResponse().getMockResult();
586 
587       if( result == null )
588       {
589          return null;
590       }
591       else
592       {
593          return result.getMockRequest().getRequestContent();
594       }
595    }
596 
597    public TestStep getTestStep()
598    {
599       return this;
600    }
601 
602    public void setName( String name )
603    {
604       super.setName( name );
605 
606       if( mockService != null )
607       {
608          mockService.setName( getName() );
609       }
610    }
611 
612    public WsdlInterface getInterface()
613    {
614       return getOperation().getInterface();
615    }
616 
617    public WsdlOperation getOperation()
618    {
619       return getMockResponse().getMockOperation().getOperation();
620    }
621 
622    public void setInterface( String interfaceName )
623    {
624       WsdlInterface wsdlInterface = (WsdlInterface) getTestCase().getTestSuite().getProject().getInterfaceByName(
625               interfaceName );
626 
627       if( wsdlInterface != null )
628       {
629          testStepConfig.setInterface( wsdlInterface.getName() );
630          WsdlOperation wsdloperation = wsdlInterface.getOperationAt( 0 );
631          testStepConfig.setOperation( wsdloperation.getName() );
632          mockOperation.setOperation( wsdloperation );
633       }
634    }
635 
636    public void setOperation( String operationName )
637    {
638       WsdlOperation wsdlOperation = getInterface().getOperationByName( operationName );
639       if( wsdlOperation != null )
640       {
641          testStepConfig.setOperation( operationName );
642          mockOperation.setOperation( wsdlOperation );
643       }
644    }
645 
646    public void release()
647    {
648       super.release();
649 
650       assertionsSupport.release();
651 
652       if( mockResponse != null )
653       {
654          mockResponse.removePropertyChangeListener( this );
655       }
656 
657       if( mockService != null )
658       {
659          mockService.release();
660       }
661 
662       if( iface != null )
663       {
664          iface.getProject().removeProjectListener( projectListener );
665          iface.removeInterfaceListener( interfaceListener );
666       }
667    }
668 
669    public TestAssertionRegistry.AssertableType getAssertableType()
670    {
671       return TestAssertionRegistry.AssertableType.REQUEST;
672    }
673 
674    public Collection<WsdlInterface> getRequiredInterfaces()
675    {
676       ArrayList<WsdlInterface> interfaces = new ArrayList<WsdlInterface>();
677       interfaces.add( getInterface() );
678 
679       return interfaces;
680    }
681 
682    public String getDefaultSourcePropertyName()
683    {
684       return "Response";
685    }
686 
687    public String getDefaultTargetPropertyName()
688    {
689       return "Resource";
690    }
691 
692    public void beforeSave()
693    {
694       super.beforeSave();
695 
696       if( mockResponse != null )
697       {
698          mockResponse.beforeSave();
699          mockResponseConfig.set( mockResponse.getConfig() );
700       }
701    }
702 
703    public long getTimeout()
704    {
705       return testStepConfig.getTimeout();
706    }
707 
708    public void setTimeout( long newTimeout )
709    {
710       long oldTimeout = getTimeout();
711       testStepConfig.setTimeout( newTimeout );
712       notifyPropertyChanged( TIMEOUT_PROPERTY, Long.valueOf( oldTimeout ), Long.valueOf( newTimeout ) );
713    }
714 
715    public boolean dependsOn( AbstractWsdlModelItem<?> modelItem )
716    {
717       return modelItem == getOperation().getInterface();
718    }
719 
720    public WsdlMessageAssertion cloneAssertion( TestAssertion testAssertion, String s )
721    {
722       TestAssertionConfig assertionConfig = testStepConfig.addNewAssertion();
723       assertionConfig.set( ( (WsdlMessageAssertion) testAssertion ).getConfig() );
724       assertionConfig.setName( s );
725       WsdlMessageAssertion messageAssertion = assertionsSupport.addWsdlAssertion( assertionConfig );
726 
727       assertionsSupport.fireAssertionAdded( messageAssertion );
728       return messageAssertion;
729    }
730 
731    public List<TestAssertion> getAssertionList()
732    {
733       return new ArrayList<TestAssertion>( assertionsSupport.getAssertionList() );
734    }
735 
736    public List<WsdlMessageAssertion> getChildren()
737    {
738       return assertionsSupport.getAssertionList();
739    }
740 
741    public PropertyExpansion[] getPropertyExpansions()
742    {
743       ArrayList<PropertyExpansion> expansions = new ArrayList<PropertyExpansion>();
744       expansions.addAll( PropertyExpansionUtils.extractPropertyExpansions( this, mockResponse, "responseContent" ) );
745 
746       StringToStringMap headers = mockResponse.getResponseHeaders();
747       String s;
748       for( Iterator<?> iterator = headers.keySet().iterator(); iterator.hasNext(); PropertyExpansionUtils
749               .extractPropertyExpansions( this, new ResponseHeaderHolder( headers, s ), "value" ) )
750          s = (String) iterator.next();
751 
752       return (PropertyExpansion[]) expansions.toArray( new PropertyExpansion[expansions.size()] );
753    }
754 
755    public WsdlMessageAssertion getAssertionByName( String s )
756    {
757       return assertionsSupport.getAssertionByName( s );
758    }
759 
760    public Map<String, TestAssertion> getAssertions()
761    {
762       HashMap<String, TestAssertion> hashmap = new HashMap<String, TestAssertion>();
763       TestAssertion testassertion;
764       for( Iterator<?> iterator = getAssertionList().iterator(); iterator.hasNext(); hashmap.put( testassertion
765               .getName(), testassertion ) )
766          testassertion = (TestAssertion) iterator.next();
767 
768       return hashmap;
769    }
770 
771    public String toString()
772    {
773       return WsdlAsyncResponseTestStep.class.getName() + " [port= " + this.getPort() + ", path= " + this.getPath()
774               + ", query=" + this.getRequestQuery() + ", value=" + this.getMatchingValue() + ", interface="
775               + this.getInterface().getName() + ", operation=" + this.getOperation().getName() + "]";
776    }
777 
778    public String getDefaultAssertableContent()
779    {
780       return getOperation().createResponse( true );
781    }
782 
783    private class AssertedWsdlMockResultMessageExchange extends WsdlMockResultMessageExchange implements
784            RequestAssertedMessageExchange, AssertedXPathsContainer
785    {
786       private List<AssertedXPath> list;
787 
788       public AssertedWsdlMockResultMessageExchange( WsdlMockResult result )
789       {
790          super( result, result.getMockResponse() );
791       }
792 
793       public AssertedXPath[] getAssertedXPathsForRequest()
794       {
795          return ( list == null ? new AssertedXPath[0] : list.toArray( new AssertedXPath[list.size()] ) );
796       }
797 
798       public void addAssertedXPath( AssertedXPath assertedXPath )
799       {
800          if( list == null )
801          {
802             list = new ArrayList<AssertedXPath>();
803          }
804 
805          list.add( assertedXPath );
806       }
807    }
808 
809    private class ResponseHeaderHolder
810    {
811       private final StringToStringMap headers;
812       private final String header;
813 
814       public String getValue()
815       {
816          return headers.get( header );
817       }
818 
819       public void setValue( String value )
820       {
821          headers.put( header, value );
822          getMockResponse().setResponseHeaders( headers );
823       }
824 
825       public ResponseHeaderHolder( StringToStringMap headers, String header )
826       {
827          this.headers = headers;
828          this.header = header;
829       }
830    }
831 
832    private class InternalInterfaceListener extends InterfaceListenerAdapter
833    {
834       public void operationRemoved( Operation operation )
835       {
836          if( operation == getOperation() )
837          {
838             log.debug( "Removing test step due to removed operation" );
839             getTestCase().removeTestStep( WsdlAsyncResponseTestStep.this );
840          }
841       }
842 
843       public void operationUpdated( Operation operation )
844       {
845          if( operation == getOperation() )
846          {
847             setOperation( operation.getName() );
848          }
849       }
850    }
851 
852    private class InternalProjectListener extends ProjectListenerAdapter
853    {
854       public void interfaceRemoved( Interface iface )
855       {
856          if( getOperation() != null && getOperation().getInterface().equals( iface ) )
857          {
858             log.debug( "Removing test step due to removed interface" );
859             getTestCase().removeTestStep( WsdlAsyncResponseTestStep.this );
860          }
861       }
862    }
863 
864    private class PropertyChangeNotifier
865    {
866       private AssertionStatus status;
867       private ImageIcon icon;
868 
869       public PropertyChangeNotifier()
870       {
871          status = getAssertionStatus();
872          icon = getIcon();
873       }
874 
875       public void notifyChange()
876       {
877          AssertionStatus newStatus = getAssertionStatus();
878          ImageIcon newIcon = getIcon();
879 
880          if( this.status != newStatus )
881          {
882             notifyPropertyChanged( WsdlAsyncResponseTestStep.STATUS_PROPERTY, this.status, newStatus );
883          }
884 
885          if( this.icon != newIcon )
886          {
887             notifyPropertyChanged( ModelItem.ICON_PROPERTY, this.icon, newIcon );
888          }
889       }
890    }
891 
892    private class InternalMockRunListener extends MockRunListenerAdapter
893    {
894       private WsdlMockResult result;
895       private boolean canceled;
896 
897       public void onMockResult( MockResult mockResult )
898       {
899          result = (WsdlMockResult) mockResult;
900 
901          // Wake up our thread if our MockResponse was used.
902          if( result == null || ( result != null && result.getMockResponse() == mockResponse ) )
903          {
904             synchronized( this )
905             {
906                notifyAll();
907             }
908          }
909       }
910 
911       public void cancel()
912       {
913          canceled = true;
914          listener.onMockResult( null );
915       }
916 
917       public WsdlMockResult getResult()
918       {
919          return result;
920       }
921 
922       public boolean isCanceled()
923       {
924          return canceled;
925 		}
926 	}
927 
928 }