View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 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 java.beans.PropertyChangeEvent;
16  import java.beans.PropertyChangeListener;
17  import java.util.ArrayList;
18  import java.util.Collection;
19  import java.util.List;
20  import java.util.Map;
21  
22  import javax.swing.ImageIcon;
23  
24  import org.apache.log4j.Logger;
25  
26  import com.eviware.soapui.config.RequestStepConfig;
27  import com.eviware.soapui.config.TestStepConfig;
28  import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
29  import com.eviware.soapui.impl.wsdl.WsdlInterface;
30  import com.eviware.soapui.impl.wsdl.WsdlOperation;
31  import com.eviware.soapui.impl.wsdl.WsdlSubmit;
32  import com.eviware.soapui.impl.wsdl.submit.transports.http.WsdlResponse;
33  import com.eviware.soapui.impl.wsdl.support.assertions.AssertedXPathsContainer;
34  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
35  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
36  import com.eviware.soapui.impl.wsdl.teststeps.assertions.WsdlAssertionRegistry.AssertableType;
37  import com.eviware.soapui.model.ModelItem;
38  import com.eviware.soapui.model.iface.Interface;
39  import com.eviware.soapui.model.iface.Operation;
40  import com.eviware.soapui.model.iface.Submit;
41  import com.eviware.soapui.model.iface.Request.SubmitException;
42  import com.eviware.soapui.model.project.Project;
43  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
44  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContainer;
45  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
46  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionsResult;
47  import com.eviware.soapui.model.support.InterfaceListenerAdapter;
48  import com.eviware.soapui.model.support.ProjectListenerAdapter;
49  import com.eviware.soapui.model.support.TestStepBeanProperty;
50  import com.eviware.soapui.model.testsuite.Assertable;
51  import com.eviware.soapui.model.testsuite.AssertionError;
52  import com.eviware.soapui.model.testsuite.AssertionsListener;
53  import com.eviware.soapui.model.testsuite.OperationTestStep;
54  import com.eviware.soapui.model.testsuite.TestAssertion;
55  import com.eviware.soapui.model.testsuite.TestRunContext;
56  import com.eviware.soapui.model.testsuite.TestRunner;
57  import com.eviware.soapui.model.testsuite.TestStep;
58  import com.eviware.soapui.model.testsuite.TestStepResult;
59  import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
60  import com.eviware.soapui.support.types.StringToStringMap;
61  
62  /***
63   * WsdlTestStep that executes a WsdlTestRequest
64   * 
65   * @author Ole.Matzura
66   */
67  
68  public class WsdlTestRequestStep extends WsdlTestStepWithProperties implements OperationTestStep, PropertyChangeListener, PropertyExpansionContainer, Assertable
69  {
70  	private final static Logger log = Logger.getLogger( WsdlTestRequestStep.class );
71     private RequestStepConfig requestStepConfig;
72     private WsdlTestRequest testRequest;
73  	private WsdlOperation wsdlOperation;
74  	private final InternalProjectListener projectListener = new InternalProjectListener();
75  	private final InternalInterfaceListener interfaceListener = new InternalInterfaceListener();
76  	private WsdlSubmit submit;
77  
78     public WsdlTestRequestStep(WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest)
79     {
80        super( testCase, config, true, forLoadTest );
81        
82        if( getConfig().getConfig() != null )
83        {
84  			requestStepConfig = (RequestStepConfig) getConfig().getConfig().changeType(RequestStepConfig.type);
85           
86           wsdlOperation = findWsdlOperation();
87  			if( wsdlOperation == null )
88           {   
89              log.error( "Could not find operation [" + requestStepConfig.getOperation() + "] in interface [" + 
90              		requestStepConfig.getInterface() + "] for test request" );
91              requestStepConfig.setRequest(null);
92           }
93           else
94           {
95           	if( !forLoadTest )
96           	{
97  	         	wsdlOperation.getInterface().getProject().addProjectListener( projectListener );
98  	         	wsdlOperation.getInterface().addInterfaceListener( interfaceListener );
99  	         	
100 	         	// we need to listen for name changes which happen when interfaces are updated..
101 	         	wsdlOperation.getInterface().addPropertyChangeListener( this );
102 	         	wsdlOperation.addPropertyChangeListener( this );
103          	}
104          	
105             testRequest = new WsdlTestRequest( wsdlOperation, requestStepConfig.getRequest(), this, forLoadTest );
106             testRequest.addPropertyChangeListener( this );
107             
108             if( config.isSetName() )
109             	testRequest.setName( config.getName() );
110             else
111             	config.setName( testRequest.getName() );
112          }
113       }
114       else
115       {
116          requestStepConfig = (RequestStepConfig) getConfig().addNewConfig().changeType( RequestStepConfig.type );
117       }
118       
119       // init properties
120       addProperty( new TestStepBeanProperty( "Endpoint", false, testRequest, "endpoint", this ));
121       addProperty( new TestStepBeanProperty( "Username", false, testRequest, "username", this ));
122       addProperty( new TestStepBeanProperty( "Password", false, testRequest, "password", this ));
123       addProperty( new TestStepBeanProperty( "Domain", false, testRequest, "domain", this ));
124       addProperty( new TestStepBeanProperty( "Request", false, testRequest, "requestContent", this ));
125       addProperty( new TestStepBeanProperty( "Response", true, testRequest, "responseContent", this ));
126    }
127 	
128 	@Override
129    public WsdlTestStep clone( WsdlTestCase targetTestCase, String name)
130 	{
131 		beforeSave(); 
132 		
133 		TestStepConfig config = (TestStepConfig) getConfig().copy();
134 		RequestStepConfig stepConfig = (RequestStepConfig) config.getConfig().changeType(RequestStepConfig.type);
135 		
136 		while( stepConfig.getRequest().sizeOfAttachmentArray() > 0 )
137 			stepConfig.getRequest().removeAttachment( 0 );
138 		
139 		config.setName( name );
140 		stepConfig.getRequest().setName( name );
141 		
142 		WsdlTestRequestStep result = (WsdlTestRequestStep) targetTestCase.addTestStep( config );
143 		testRequest.copyAttachmentsTo( result.getTestRequest() );
144 		
145 		return result;
146 	}
147 	
148 	private WsdlOperation findWsdlOperation()
149    {
150    	WsdlTestCase testCase = getTestCase();
151    	if( testCase == null || testCase.getTestSuite() == null )
152    		return null;
153    	
154       Project project = testCase.getTestSuite().getProject();
155       WsdlOperation operation = null;
156       for( int c = 0; c < project.getInterfaceCount(); c++ )
157       {
158          if( project.getInterfaceAt( c ).getName().equals( requestStepConfig.getInterface()))
159          {
160             WsdlInterface iface = (WsdlInterface) project.getInterfaceAt( c );
161             for( int i = 0; i < iface.getOperationCount(); i++ )
162             {
163                if( iface.getOperationAt( i ).getName().equals( requestStepConfig.getOperation() ))
164                {
165                   operation = iface.getOperationAt( i );
166                   break;
167                }
168             }
169             
170             if( operation != null )
171             	break;
172          }
173       }
174       return operation;
175    }
176 	
177 	public String getInterfaceName()
178 	{
179 		return requestStepConfig.getInterface();
180 	}
181 	
182 	public String getOperationName()
183 	{
184 		return requestStepConfig.getOperation();
185 	}
186 
187 	@Override
188    public void release()
189 	{
190 		super.release();
191 		
192 		if( wsdlOperation == null )
193 			wsdlOperation = findWsdlOperation();
194 		
195       if( wsdlOperation != null )
196       {
197 	      wsdlOperation.removePropertyChangeListener( this );
198 	     	wsdlOperation.getInterface().getProject().removeProjectListener( projectListener );
199 	     	wsdlOperation.getInterface().removeInterfaceListener( interfaceListener );
200 	     	wsdlOperation.getInterface().removePropertyChangeListener( this );
201       }
202       
203       testRequest.removePropertyChangeListener( this );
204       testRequest.release();
205 	}
206 
207 	@Override
208    public void resetConfigOnMove(TestStepConfig config)
209 	{
210 		super.resetConfigOnMove(config);
211 
212 		requestStepConfig = (RequestStepConfig) config.getConfig().changeType(RequestStepConfig.type);
213 		testRequest.updateConfig( requestStepConfig.getRequest() );
214 	}
215 
216 	@Override
217    public ImageIcon getIcon()
218    {
219       return testRequest.getIcon();
220    }
221 
222    public WsdlTestRequest getTestRequest()
223    {
224       return testRequest;
225    }
226    
227 	@Override
228    public void setName(String name)
229 	{
230 		super.setName( name );
231 		testRequest.setName( name );
232 	}
233 
234    public void propertyChange(PropertyChangeEvent arg0) 
235    {
236    	if( arg0.getSource() == wsdlOperation )
237    	{
238    		if( arg0.getPropertyName().equals( Operation.NAME_PROPERTY ))
239    		{
240    			requestStepConfig.setOperation( (String) arg0.getNewValue() );
241    		}
242    	}
243    	else if( arg0.getSource() == wsdlOperation.getInterface() )
244    	{
245    		if( arg0.getPropertyName().equals( Interface.NAME_PROPERTY ))
246    		{
247    			requestStepConfig.setInterface( (String) arg0.getNewValue() );
248    		}
249    	}
250    	else if( arg0.getPropertyName().equals( TestAssertion.CONFIGURATION_PROPERTY ) || 
251    				arg0.getPropertyName().equals( TestAssertion.DISABLED_PROPERTY ))
252    	{
253    		if( getTestRequest().getResponse() != null )
254    		{
255   				getTestRequest().assertResponse( new WsdlTestRunContext( this ) );
256    		}
257    	}
258    	else
259    	{
260    		if( arg0.getSource() == testRequest && arg0.getPropertyName().equals( WsdlTestRequest.NAME_PROPERTY ))
261    		{
262    			if( !super.getName().equals( (String) arg0.getNewValue() ))
263    				super.setName( (String) arg0.getNewValue() );
264    		}
265    		
266    	   notifyPropertyChanged( arg0.getPropertyName(), arg0.getOldValue(), arg0.getNewValue());
267    	}
268    }
269 
270 	public TestStepResult run( TestRunner runner, TestRunContext runContext ) 
271 	{
272 		WsdlTestRequestStepResult testStepResult = new WsdlTestRequestStepResult(this);
273 		
274    	try
275 		{
276 			submit = testRequest.submit( runContext, false );
277 			WsdlResponse response = (WsdlResponse) submit.getResponse();
278 			
279 			if( submit.getStatus() != Submit.Status.CANCELED )
280 			{
281 				if( submit.getStatus() == Submit.Status.ERROR )
282 				{
283 					testStepResult.setStatus( TestStepStatus.FAILED );
284 					testStepResult.addMessage( submit.getError().toString() );
285 					
286 					testRequest.setResponse( null, runContext );
287 				}
288 				else if( response == null )
289 				{
290 					testStepResult.setStatus( TestStepStatus.FAILED );
291 					testStepResult.addMessage( "Request is missing response" );
292 					
293 					testRequest.setResponse( null, runContext );
294 				}
295 				else
296 				{
297 					runContext.setProperty( AssertedXPathsContainer.ASSERTEDXPATHSCONTAINER_PROPERTY, testStepResult );
298 					testRequest.setResponse( response, runContext );
299 					
300 					testStepResult.setTimeTaken( response.getTimeTaken() );
301 			   	testStepResult.setSize( response.getContentLength() );
302 			   	testStepResult.setResponse( response );
303 			   	
304 			   	switch( testRequest.getAssertionStatus() )
305 			   	{
306 			   		case FAILED : testStepResult.setStatus( TestStepStatus.FAILED); break; 
307 			   		case VALID : testStepResult.setStatus( TestStepStatus.OK); break; 
308 			   		case UNKNOWN : testStepResult.setStatus( TestStepStatus.UNKNOWN); break; 
309 			   	}
310 				}
311 			}
312 			else
313 			{
314 				testStepResult.setStatus( TestStepStatus.CANCELED );
315 				testStepResult.addMessage( "Request was canceled" );
316 			}
317 			
318 			if( response != null )
319 				testStepResult.setRequestContent( response.getRequestContent() );
320 			else
321 				testStepResult.setRequestContent( testRequest.getRequestContent() );
322 		}
323 		catch (SubmitException e)
324 		{
325 			testStepResult.setStatus( TestStepStatus.FAILED );
326 			testStepResult.addMessage( "SubmitException: " + e );
327 		}
328 		finally
329 		{
330 			submit = null;
331 		}
332 		
333 		testStepResult.setDomain( PropertyExpansionUtils.expandProperties( runContext,testRequest.getDomain() ));
334 		testStepResult.setUsername( PropertyExpansionUtils.expandProperties( runContext,testRequest.getUsername() ));
335 		testStepResult.setPassword( PropertyExpansionUtils.expandProperties( runContext,testRequest.getPassword() ));
336 		testStepResult.setEndpoint( PropertyExpansionUtils.expandProperties( runContext, testRequest.getEndpoint() ));
337 		testStepResult.setEncoding( PropertyExpansionUtils.expandProperties( runContext,testRequest.getEncoding() ));
338    	
339 		if( testStepResult.getStatus() != TestStepStatus.CANCELED )
340 		{
341 	   	AssertionStatus assertionStatus = testRequest.getAssertionStatus();
342 			switch( assertionStatus )
343 	   	{
344 	   		case FAILED : 
345 				{
346 					testStepResult.setStatus( TestStepStatus.FAILED );
347 					if( getAssertionCount() == 0 )
348 					{
349 						testStepResult.addMessage( "Invalid/empty response" );
350 					}
351 					else for( int c = 0; c < getAssertionCount(); c++ )
352 					{
353 						AssertionError[] errors = getAssertionAt( c ).getErrors();
354 						if( errors != null )
355 						{
356 							for( AssertionError error : errors )
357 							{
358 								testStepResult.addMessage( error.getMessage() );
359 							}
360 						}
361 					}
362 					
363 					break;
364 				}
365 	   	//	default : testStepResult.setStatus( TestStepStatus.OK ); break;
366 	   	}
367 		}
368    	
369 		return testStepResult;
370 	}
371 	
372 	public WsdlMessageAssertion getAssertionAt(int index)
373 	{
374 		return testRequest.getAssertionAt( index );
375 	}
376 
377 	public int getAssertionCount()
378 	{
379 		return testRequest.getAssertionCount();
380 	}
381 	
382 	public class InternalProjectListener extends ProjectListenerAdapter 
383 	{
384 		@Override
385       public void interfaceRemoved(Interface iface)
386 		{
387 			if( wsdlOperation != null && wsdlOperation.getInterface().equals( iface ))
388 			{
389 				log.debug( "Removing test step due to removed interface" );
390 				(getTestCase()).removeTestStep( WsdlTestRequestStep.this );
391 			}
392 		}
393 	}
394 
395 	public class InternalInterfaceListener extends InterfaceListenerAdapter
396 	{
397 		@Override
398 		public void operationRemoved(Operation operation)
399 		{
400 			if( operation == wsdlOperation )
401 			{
402 				log.debug( "Removing test step due to removed operation" );
403 				(getTestCase()).removeTestStep( WsdlTestRequestStep.this );
404 			}
405 		}
406 
407 		@Override
408 		public void operationUpdated( Operation operation )
409 		{
410 			if( operation == wsdlOperation )
411 			{
412 				requestStepConfig.setOperation( operation.getName() );
413 			}
414 		}
415 	}
416 	
417 	@Override
418    public boolean cancel()
419 	{
420 		if( submit == null )
421 			return false;
422 		
423 		submit.cancel();
424 		
425 		return true;
426 	}
427 
428 	@Override
429 	public Collection<WsdlInterface> getRequiredInterfaces()
430 	{
431 		ArrayList<WsdlInterface> result = new ArrayList<WsdlInterface>( );
432 		result.add( findWsdlOperation().getInterface() );
433 		return result;
434 	}
435 
436 	@Override
437    public boolean dependsOn( AbstractWsdlModelItem modelItem )
438 	{
439 		if( modelItem instanceof Interface && testRequest.getOperation().getInterface() == modelItem )
440 		{
441 			return true;
442 		}
443 		else if( modelItem instanceof Operation && testRequest.getOperation() == modelItem )
444 		{
445 			return true;
446 		}
447 		
448 		return false;
449 	}
450 
451 	@Override
452 	public void beforeSave()
453 	{
454 		super.beforeSave();
455 		
456 		testRequest.beforeSave();
457 	}
458 
459 	@Override
460    public String getDescription()
461 	{
462 		return testRequest.getDescription();
463 	}
464 
465 	@Override
466    public void setDescription( String description )
467 	{
468 		testRequest.setDescription( description );
469 	}
470 
471 	public void setOperation( WsdlOperation operation )
472 	{
473 		if( wsdlOperation == operation )
474 			return;
475 		
476 		WsdlOperation oldOperation = wsdlOperation;
477 		wsdlOperation = operation;
478 		requestStepConfig.setInterface( operation.getInterface().getName() );
479 		requestStepConfig.setOperation( operation.getName() );
480 		
481 		oldOperation.removePropertyChangeListener( this );
482 		wsdlOperation.addPropertyChangeListener( this );
483 		
484 		testRequest.setOperation( wsdlOperation );
485 	}
486 
487    @Override
488    public List<? extends ModelItem> getChildren()
489    {
490       return testRequest.getAssertionList();
491    }
492 
493 	public PropertyExpansion[] getPropertyExpansions()
494 	{
495 		PropertyExpansionsResult result = new PropertyExpansionsResult( this, testRequest );
496 		
497 		result.extractAndAddAll( "requestContent" );
498 		result.extractAndAddAll( "endpoint" );
499 		result.extractAndAddAll( "username" );
500 		result.extractAndAddAll( "password" );
501 		result.extractAndAddAll( "domain" );
502 		
503 		StringToStringMap requestHeaders = testRequest.getRequestHeaders();
504 		for( String key : requestHeaders.keySet())
505 		{
506 			result.extractAndAddAll( new RequestHeaderHolder( requestHeaders, key ), "value" );
507 		}
508 		
509 //		result.addAll( testRequest.getWssContainer().getPropertyExpansions() );
510 		
511 		return result.toArray( new PropertyExpansion[result.size()] );
512 	}
513 	
514 	public class RequestHeaderHolder
515 	{
516 		private final StringToStringMap valueMap;
517 		private final String key;
518 
519 		public RequestHeaderHolder( StringToStringMap valueMap, String key )
520 		{
521 			this.valueMap = valueMap;
522 			this.key = key;
523 		}
524 
525 		public String getValue()
526 		{
527 			return valueMap.get( key );
528 		}
529 
530 		public void setValue( String value )
531 		{
532 			valueMap.put( key, value );
533 			testRequest.setRequestHeaders( valueMap );
534 		}
535 	}
536 
537 	public TestAssertion addAssertion( String selection )
538 	{
539 		WsdlMessageAssertion result = testRequest.addAssertion( selection );
540 		return result;
541 	}
542 
543 	public void addAssertionsListener( AssertionsListener listener )
544 	{
545 		testRequest.addAssertionsListener( listener );
546 	}
547 
548 	public TestAssertion cloneAssertion( TestAssertion source, String name )
549 	{
550 		return testRequest.cloneAssertion( source, name );
551 	}
552 
553 	public String getAssertableContent()
554 	{
555 		return testRequest.getAssertableContent();
556 	}
557 
558 	public AssertableType getAssertableType()
559 	{
560 		return testRequest.getAssertableType();
561 	}
562 
563 	public TestAssertion getAssertionByName( String name )
564 	{
565 		return testRequest.getAssertionByName( name );
566 	}
567 
568 	public List<TestAssertion> getAssertionList()
569 	{
570 		return testRequest.getAssertionList();
571 	}
572 
573 	public AssertionStatus getAssertionStatus()
574 	{
575 		return testRequest.getAssertionStatus();
576 	}
577 
578 	public Interface getInterface()
579 	{
580 		return getOperation().getInterface();
581 	}
582 
583 	public Operation getOperation()
584 	{
585 		return wsdlOperation;
586 	}
587 
588 	public TestStep getTestStep()
589 	{
590 		return this;
591 	}
592 
593 	public void removeAssertion( TestAssertion assertion )
594 	{
595 		testRequest.removeAssertion( assertion );
596 	}
597 
598 	public void removeAssertionsListener( AssertionsListener listener )
599 	{
600 		testRequest.removeAssertionsListener( listener );
601 	}
602 	
603 	public Map<String,TestAssertion> getAssertions()
604 	{
605 		return testRequest.getAssertions();
606 	}
607 }