View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 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.util.Collections;
17  import java.util.List;
18  import java.util.Map;
19  
20  import javax.swing.ImageIcon;
21  import javax.xml.namespace.QName;
22  
23  import org.apache.log4j.Logger;
24  
25  import com.eviware.soapui.config.HttpRequestConfig;
26  import com.eviware.soapui.config.RequestStepConfig;
27  import com.eviware.soapui.config.TestStepConfig;
28  import com.eviware.soapui.impl.rest.support.RestParamProperty;
29  import com.eviware.soapui.impl.rest.support.RestRequestConverter;
30  import com.eviware.soapui.impl.support.AbstractHttpRequest;
31  import com.eviware.soapui.impl.support.http.HttpRequest;
32  import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
33  import com.eviware.soapui.impl.wsdl.WsdlSubmit;
34  import com.eviware.soapui.impl.wsdl.submit.transports.http.HttpResponse;
35  import com.eviware.soapui.impl.wsdl.support.assertions.AssertedXPathsContainer;
36  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
37  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
38  import com.eviware.soapui.impl.wsdl.teststeps.assertions.TestAssertionRegistry.AssertableType;
39  import com.eviware.soapui.model.ModelItem;
40  import com.eviware.soapui.model.iface.Interface;
41  import com.eviware.soapui.model.iface.Submit;
42  import com.eviware.soapui.model.iface.Request.SubmitException;
43  import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
44  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
45  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionsResult;
46  import com.eviware.soapui.model.support.TestPropertyListenerAdapter;
47  import com.eviware.soapui.model.support.TestStepBeanProperty;
48  import com.eviware.soapui.model.testsuite.AssertionError;
49  import com.eviware.soapui.model.testsuite.AssertionsListener;
50  import com.eviware.soapui.model.testsuite.TestAssertion;
51  import com.eviware.soapui.model.testsuite.TestCaseRunContext;
52  import com.eviware.soapui.model.testsuite.TestCaseRunner;
53  import com.eviware.soapui.model.testsuite.TestProperty;
54  import com.eviware.soapui.model.testsuite.TestStep;
55  import com.eviware.soapui.model.testsuite.TestStepProperty;
56  import com.eviware.soapui.model.testsuite.TestStepResult;
57  import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
58  import com.eviware.soapui.support.resolver.ResolveContext;
59  import com.eviware.soapui.support.types.StringToStringMap;
60  
61  public class HttpTestRequestStep extends WsdlTestStepWithProperties implements HttpTestRequestStepInterface
62  {
63  	@SuppressWarnings( "unused" )
64  	private final static Logger log = Logger.getLogger( HttpTestRequestStep.class );
65  	private HttpRequestConfig httpRequestConfig;
66  	private HttpTestRequest testRequest;
67  	private WsdlSubmit<HttpRequest> submit;
68  
69  	public HttpTestRequestStep( WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest )
70  	{
71  		super( testCase, config, true, forLoadTest );
72  
73  		if( getConfig().getConfig() != null )
74  		{
75  			// httpRequestConfig = (HttpRequestConfig)
76  			// getConfig().getConfig().changeType( HttpRequestConfig.type );
77  			httpRequestConfig = RestRequestConverter.updateIfNeeded( getConfig().getConfig() );
78  			// if( httpRequestConfig != getConfig().getConfig() )
79  
80  				getConfig().setConfig( httpRequestConfig );
81  			httpRequestConfig = ( HttpRequestConfig )getConfig().getConfig();
82  			testRequest = buildTestRequest( forLoadTest );
83  			// testRequest = new RestTestRequest( null,
84  			// requestStepConfig.getRestRequest(), this, forLoadTest );
85  			testRequest.addPropertyChangeListener( this );
86  			testRequest.addTestPropertyListener( new InternalTestPropertyListener() );
87  
88  			if( config.isSetName() )
89  				testRequest.setName( config.getName() );
90  			else
91  				config.setName( testRequest.getName() );
92  
93  			// testRequest.setEndpoint( testRequest.getEndpoint() );
94  		}
95  		else
96  		{
97  			httpRequestConfig = ( HttpRequestConfig )getConfig().addNewConfig().changeType( HttpRequestConfig.type );
98  		}
99  
100 		for( TestProperty property : testRequest.getProperties().values() )
101 		{
102 			addProperty( new RestTestStepProperty( ( RestParamProperty )property ) );
103 		}
104 
105 		// init default properties
106 		addProperty( new TestStepBeanProperty( "Endpoint", false, testRequest, "endpoint", this ) );
107 		addProperty( new TestStepBeanProperty( "Username", false, testRequest, "username", this ) );
108 		addProperty( new TestStepBeanProperty( "Password", false, testRequest, "password", this ) );
109 		addProperty( new TestStepBeanProperty( "Domain", false, testRequest, "domain", this ) );
110 
111 		// init properties
112 		addProperty( new TestStepBeanProperty( "Request", false, testRequest, "requestContent", this )
113 		{
114 			@Override
115 			public String getDefaultValue()
116 			{
117 				return createDefaultRequestContent();
118 			}
119 		} );
120 
121 		addProperty( new TestStepBeanProperty( "ResponseAsXml", true, testRequest, "responseContentAsXml", this )
122 		{
123 			@Override
124 			public String getDefaultValue()
125 			{
126 				return createDefaultResponseXmlContent();
127 			}
128 		} );
129 
130 		addProperty( new TestStepBeanProperty( "Response", true, testRequest, "responseContentAsString", this )
131 		{
132 			@Override
133 			public String getDefaultValue()
134 			{
135 				return createDefaultRawResponseContent();
136 			}
137 		} );
138 	}
139 
140 	protected HttpTestRequest buildTestRequest( boolean forLoadTest )
141 	{
142 		return new HttpTestRequest( httpRequestConfig, this, forLoadTest );
143 	}
144 
145 	protected String createDefaultRawResponseContent()
146 	{
147 		return "";
148 	}
149 
150 	protected String createDefaultResponseXmlContent()
151 	{
152 		return "";
153 	}
154 
155 	protected String createDefaultRequestContent()
156 	{
157 		return "";
158 	}
159 
160 	public HttpRequestConfig getRequestStepConfig()
161 	{
162 		return httpRequestConfig;
163 	}
164 
165 	@Override
166 	public WsdlTestStep clone( WsdlTestCase targetTestCase, String name )
167 	{
168 		beforeSave();
169 
170 		TestStepConfig config = ( TestStepConfig )getConfig().copy();
171 		RequestStepConfig stepConfig = ( RequestStepConfig )config.getConfig().changeType( RequestStepConfig.type );
172 
173 		while( stepConfig.getRequest().sizeOfAttachmentArray() > 0 )
174 			stepConfig.getRequest().removeAttachment( 0 );
175 
176 		config.setName( name );
177 		stepConfig.getRequest().setName( name );
178 
179 		WsdlTestRequestStep result = ( WsdlTestRequestStep )targetTestCase.addTestStep( config );
180 		testRequest.copyAttachmentsTo( result.getTestRequest() );
181 
182 		return result;
183 	}
184 
185 	@Override
186 	public void release()
187 	{
188 		super.release();
189 
190 		// could be null if initialization failed..
191 		if( testRequest != null )
192 		{
193 			testRequest.removePropertyChangeListener( this );
194 			testRequest.release();
195 		}
196 	}
197 
198 	@Override
199 	public void resetConfigOnMove( TestStepConfig config )
200 	{
201 		super.resetConfigOnMove( config );
202 
203 		httpRequestConfig = ( HttpRequestConfig )config.getConfig().changeType( HttpRequestConfig.type );
204 		testRequest.updateConfig( httpRequestConfig );
205 	}
206 
207 	@Override
208 	public ImageIcon getIcon()
209 	{
210 		return testRequest == null ? null : testRequest.getIcon();
211 	}
212 
213 	public HttpTestRequest getTestRequest()
214 	{
215 		return testRequest;
216 	}
217 
218 	@Override
219 	public void setName( String name )
220 	{
221 		super.setName( name );
222 		testRequest.setName( name );
223 	}
224 
225 	public void propertyChange( PropertyChangeEvent evt )
226 	{
227 		if( evt.getPropertyName().equals( TestAssertion.CONFIGURATION_PROPERTY )
228 				|| evt.getPropertyName().equals( TestAssertion.DISABLED_PROPERTY ) )
229 		{
230 			if( getTestRequest().getResponse() != null )
231 			{
232 				getTestRequest().assertResponse( new WsdlTestRunContext( this ) );
233 			}
234 		}
235 		else
236 		{
237 			if( evt.getSource() == testRequest && evt.getPropertyName().equals( WsdlTestRequest.NAME_PROPERTY ) )
238 			{
239 				if( !super.getName().equals( ( String )evt.getNewValue() ) )
240 					super.setName( ( String )evt.getNewValue() );
241 			}
242 
243 			notifyPropertyChanged( evt.getPropertyName(), evt.getOldValue(), evt.getNewValue() );
244 		}
245 	}
246 
247 	public TestStepResult run( TestCaseRunner runner, TestCaseRunContext runContext )
248 	{
249 		RestRequestStepResult testStepResult = new RestRequestStepResult( this );
250 
251 		try
252 		{
253 			submit = testRequest.submit( runContext, false );
254 			HttpResponse response = ( HttpResponse )submit.getResponse();
255 
256 			if( submit.getStatus() != Submit.Status.CANCELED )
257 			{
258 				if( submit.getStatus() == Submit.Status.ERROR )
259 				{
260 					testStepResult.setStatus( TestStepStatus.FAILED );
261 					testStepResult.addMessage( submit.getError().toString() );
262 
263 					testRequest.setResponse( null, runContext );
264 				}
265 				else if( response == null )
266 				{
267 					testStepResult.setStatus( TestStepStatus.FAILED );
268 					testStepResult.addMessage( "Request is missing response" );
269 
270 					testRequest.setResponse( null, runContext );
271 				}
272 				else
273 				{
274 					runContext.setProperty( AssertedXPathsContainer.ASSERTEDXPATHSCONTAINER_PROPERTY, testStepResult );
275 					testRequest.setResponse( response, runContext );
276 
277 					testStepResult.setTimeTaken( response.getTimeTaken() );
278 					testStepResult.setSize( response.getContentLength() );
279 					testStepResult.setResponse( response );
280 
281 					switch( testRequest.getAssertionStatus() )
282 					{
283 					case FAILED :
284 						testStepResult.setStatus( TestStepStatus.FAILED );
285 						break;
286 					case VALID :
287 						testStepResult.setStatus( TestStepStatus.OK );
288 						break;
289 					case UNKNOWN :
290 						testStepResult.setStatus( TestStepStatus.UNKNOWN );
291 						break;
292 					}
293 				}
294 			}
295 			else
296 			{
297 				testStepResult.setStatus( TestStepStatus.CANCELED );
298 				testStepResult.addMessage( "Request was canceled" );
299 			}
300 
301 			if( response != null )
302 			{
303 				testStepResult.setRequestContent( response.getRequestContent() );
304 				testStepResult.addProperty( "URL", response.getURL() == null ? "<missing>" : response.getURL().toString() );
305 				testStepResult.addProperty( "Method", String.valueOf( response.getMethod() ) );
306 				testStepResult.addProperty( "StatusCode", String.valueOf( response.getStatusCode() ) );
307 				testStepResult.addProperty( "HTTP Version", response.getHttpVersion() );
308 			}
309 			else
310 			{
311 				testStepResult.addMessage( "Missing Response" );
312 				testStepResult.setRequestContent( testRequest.getRequestContent() );
313 			}
314 		}
315 		catch( SubmitException e )
316 		{
317 			testStepResult.setStatus( TestStepStatus.FAILED );
318 			testStepResult.addMessage( "SubmitException: " + e );
319 		}
320 		finally
321 		{
322 			submit = null;
323 		}
324 
325 		testStepResult.setDomain( PropertyExpander.expandProperties( runContext, testRequest.getDomain() ) );
326 		testStepResult.setUsername( PropertyExpander.expandProperties( runContext, testRequest.getUsername() ) );
327 		testStepResult.setEndpoint( PropertyExpander.expandProperties( runContext, testRequest.getEndpoint() ) );
328 		testStepResult.setPassword( PropertyExpander.expandProperties( runContext, testRequest.getPassword() ) );
329 		testStepResult.setEncoding( PropertyExpander.expandProperties( runContext, testRequest.getEncoding() ) );
330 
331 		if( testStepResult.getStatus() != TestStepStatus.CANCELED )
332 		{
333 			AssertionStatus assertionStatus = testRequest.getAssertionStatus();
334 			switch( assertionStatus )
335 			{
336 			case FAILED :
337 			{
338 				testStepResult.setStatus( TestStepStatus.FAILED );
339 				if( getAssertionCount() == 0 )
340 				{
341 					testStepResult.addMessage( "Invalid/empty response" );
342 				}
343 				else
344 					for( int c = 0; c < getAssertionCount(); c++ )
345 					{
346 						WsdlMessageAssertion assertion = getAssertionAt( c );
347 						AssertionError[] errors = assertion.getErrors();
348 						if( errors != null )
349 						{
350 							for( AssertionError error : errors )
351 							{
352 								testStepResult.addMessage( "[" + assertion.getName() + "] " + error.getMessage() );
353 							}
354 						}
355 					}
356 
357 				break;
358 			}
359 			}
360 		}
361 
362 		return testStepResult;
363 	}
364 
365 	public WsdlMessageAssertion getAssertionAt( int index )
366 	{
367 		return testRequest.getAssertionAt( index );
368 	}
369 
370 	public int getAssertionCount()
371 	{
372 		return testRequest == null ? 0 : testRequest.getAssertionCount();
373 	}
374 
375 	@Override
376 	public boolean cancel()
377 	{
378 		if( submit == null )
379 			return false;
380 
381 		submit.cancel();
382 
383 		return true;
384 	}
385 
386 	@Override
387 	public boolean dependsOn( AbstractWsdlModelItem<?> modelItem )
388 	{
389 		return false;
390 	}
391 
392 	@Override
393 	public void beforeSave()
394 	{
395 		super.beforeSave();
396 
397 		if( testRequest != null )
398 			testRequest.beforeSave();
399 	}
400 
401 	@Override
402 	public String getDescription()
403 	{
404 		return testRequest == null ? "<missing>" : testRequest.getDescription();
405 	}
406 
407 	@Override
408 	public void setDescription( String description )
409 	{
410 		if( testRequest != null )
411 			testRequest.setDescription( description );
412 	}
413 
414 	@SuppressWarnings( "unchecked" )
415 	@Override
416 	public List<? extends ModelItem> getChildren()
417 	{
418 		return testRequest == null ? Collections.EMPTY_LIST : testRequest.getAssertionList();
419 	}
420 
421 	public PropertyExpansion[] getPropertyExpansions()
422 	{
423 		if( testRequest == null )
424 			return new PropertyExpansion[0];
425 
426 		PropertyExpansionsResult result = new PropertyExpansionsResult( this, testRequest );
427 
428 		result.extractAndAddAll( "requestContent" );
429 		result.extractAndAddAll( "endpoint" );
430 		result.extractAndAddAll( "username" );
431 		result.extractAndAddAll( "password" );
432 		result.extractAndAddAll( "domain" );
433 
434 		StringToStringMap requestHeaders = testRequest.getRequestHeaders();
435 		for( String key : requestHeaders.keySet() )
436 		{
437 			result.extractAndAddAll( new RequestHeaderHolder( requestHeaders, key ), "value" );
438 		}
439 
440 		for( String key : testRequest.getParams().getPropertyNames() )
441 		{
442 			result.extractAndAddAll( new RequestParamHolder( key ), "value" );
443 		}
444 
445 		return result.toArray( new PropertyExpansion[result.size()] );
446 	}
447 
448 	public AbstractHttpRequest<?> getHttpRequest()
449 	{
450 		return testRequest;
451 	}
452 
453 	public class RequestHeaderHolder
454 	{
455 		private final StringToStringMap valueMap;
456 		private final String key;
457 
458 		public RequestHeaderHolder( StringToStringMap valueMap, String key )
459 		{
460 			this.valueMap = valueMap;
461 			this.key = key;
462 		}
463 
464 		public String getValue()
465 		{
466 			return valueMap.get( key );
467 		}
468 
469 		public void setValue( String value )
470 		{
471 			valueMap.put( key, value );
472 			testRequest.setRequestHeaders( valueMap );
473 		}
474 	}
475 
476 	public class RequestParamHolder
477 	{
478 		private final String name;
479 
480 		public RequestParamHolder( String name )
481 		{
482 			this.name = name;
483 		}
484 
485 		public String getValue()
486 		{
487 			return testRequest.getParams().getPropertyValue( name );
488 		}
489 
490 		public void setValue( String value )
491 		{
492 			testRequest.setPropertyValue( name, value );
493 		}
494 	}
495 
496 	public TestAssertion addAssertion( String type )
497 	{
498 		WsdlMessageAssertion result = testRequest.addAssertion( type );
499 		return result;
500 	}
501 
502 	public void addAssertionsListener( AssertionsListener listener )
503 	{
504 		testRequest.addAssertionsListener( listener );
505 	}
506 
507 	public TestAssertion cloneAssertion( TestAssertion source, String name )
508 	{
509 		return testRequest.cloneAssertion( source, name );
510 	}
511 
512 	public String getAssertableContent()
513 	{
514 		return testRequest.getAssertableContent();
515 	}
516 
517 	public AssertableType getAssertableType()
518 	{
519 		return testRequest.getAssertableType();
520 	}
521 
522 	public TestAssertion getAssertionByName( String name )
523 	{
524 		return testRequest.getAssertionByName( name );
525 	}
526 
527 	public List<TestAssertion> getAssertionList()
528 	{
529 		return testRequest.getAssertionList();
530 	}
531 
532 	public AssertionStatus getAssertionStatus()
533 	{
534 		return testRequest.getAssertionStatus();
535 	}
536 
537 	public Interface getInterface()
538 	{
539 		return null;
540 	}
541 
542 	public TestStep getTestStep()
543 	{
544 		return this;
545 	}
546 
547 	public void removeAssertion( TestAssertion assertion )
548 	{
549 		testRequest.removeAssertion( assertion );
550 	}
551 
552 	public void removeAssertionsListener( AssertionsListener listener )
553 	{
554 		testRequest.removeAssertionsListener( listener );
555 	}
556 
557 	public TestAssertion moveAssertion( int ix, int offset )
558 	{
559 		return testRequest.moveAssertion( ix, offset );
560 	}
561 
562 	public Map<String, TestAssertion> getAssertions()
563 	{
564 		return testRequest.getAssertions();
565 	}
566 
567 	@Override
568 	public void prepare( TestCaseRunner testRunner, TestCaseRunContext testRunContext ) throws Exception
569 	{
570 		super.prepare( testRunner, testRunContext );
571 
572 		testRequest.setResponse( null, testRunContext );
573 
574 		for( TestAssertion assertion : testRequest.getAssertionList() )
575 		{
576 			assertion.prepare( testRunner, testRunContext );
577 		}
578 	}
579 
580 	public String getDefaultSourcePropertyName()
581 	{
582 		return "ResponseAsXml";
583 	}
584 
585 	public String getDefaultTargetPropertyName()
586 	{
587 		return "Request";
588 	}
589 
590 	public String getDefaultAssertableContent()
591 	{
592 		return testRequest.getDefaultAssertableContent();
593 	}
594 
595 	public void resolve( ResolveContext<?> context )
596 	{
597 		super.resolve( context );
598 
599 		testRequest.resolve( context );
600 	}
601 
602 	private class InternalTestPropertyListener extends TestPropertyListenerAdapter
603 	{
604 		@Override
605 		public void propertyAdded( String name )
606 		{
607 			HttpTestRequestStep.this.addProperty( new RestTestStepProperty( getTestRequest().getProperty( name ) ), true );
608 		}
609 
610 		@Override
611 		public void propertyRemoved( String name )
612 		{
613 			HttpTestRequestStep.this.deleteProperty( name, true );
614 		}
615 
616 		@Override
617 		public void propertyRenamed( String oldName, String newName )
618 		{
619 			HttpTestRequestStep.this.propertyRenamed( oldName );
620 		}
621 
622 		@Override
623 		public void propertyValueChanged( String name, String oldValue, String newValue )
624 		{
625 			HttpTestRequestStep.this.firePropertyValueChanged( name, oldValue, newValue );
626 		}
627 
628 		@Override
629 		public void propertyMoved( String name, int oldIndex, int newIndex )
630 		{
631 			HttpTestRequestStep.this.firePropertyMoved( name, oldIndex, newIndex );
632 		}
633 	}
634 
635 	private class RestTestStepProperty implements TestStepProperty
636 	{
637 		private RestParamProperty property;
638 
639 		public RestTestStepProperty( RestParamProperty property )
640 		{
641 			this.property = property;
642 		}
643 
644 		public TestStep getTestStep()
645 		{
646 			return HttpTestRequestStep.this;
647 		}
648 
649 		public String getName()
650 		{
651 			return property.getName();
652 		}
653 
654 		public String getDescription()
655 		{
656 			return property.getDescription();
657 		}
658 
659 		public String getValue()
660 		{
661 			return property.getValue();
662 		}
663 
664 		public String getDefaultValue()
665 		{
666 			return property.getDefaultValue();
667 		}
668 
669 		public void setValue( String value )
670 		{
671 			property.setValue( value );
672 		}
673 
674 		public boolean isReadOnly()
675 		{
676 			return false;
677 		}
678 
679 		public QName getType()
680 		{
681 			return property.getType();
682 		}
683 
684 		public ModelItem getModelItem()
685 		{
686 			return getTestRequest();
687 		}
688 	}
689 
690 }