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