View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 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.ArrayList;
17  import java.util.Collection;
18  import java.util.List;
19  import java.util.Map;
20  
21  import javax.swing.ImageIcon;
22  import javax.xml.namespace.QName;
23  
24  import org.apache.log4j.Logger;
25  
26  import com.eviware.soapui.config.RestRequestStepConfig;
27  import com.eviware.soapui.config.TestStepConfig;
28  import com.eviware.soapui.impl.rest.RestMethod;
29  import com.eviware.soapui.impl.rest.RestRequest;
30  import com.eviware.soapui.impl.rest.RestResource;
31  import com.eviware.soapui.impl.rest.RestService;
32  import com.eviware.soapui.impl.rest.support.RestParamProperty;
33  import com.eviware.soapui.impl.rest.support.RestRequestConverter;
34  import com.eviware.soapui.impl.support.AbstractHttpRequest;
35  import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
36  import com.eviware.soapui.impl.wsdl.WsdlProject;
37  import com.eviware.soapui.impl.wsdl.WsdlSubmit;
38  import com.eviware.soapui.impl.wsdl.submit.transports.http.HttpResponse;
39  import com.eviware.soapui.impl.wsdl.support.assertions.AssertedXPathsContainer;
40  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
41  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
42  import com.eviware.soapui.impl.wsdl.teststeps.assertions.TestAssertionRegistry.AssertableType;
43  import com.eviware.soapui.impl.wsdl.teststeps.registry.RestRequestStepFactory.ItemDeletedException;
44  import com.eviware.soapui.model.ModelItem;
45  import com.eviware.soapui.model.iface.Interface;
46  import com.eviware.soapui.model.iface.Operation;
47  import com.eviware.soapui.model.iface.Submit;
48  import com.eviware.soapui.model.iface.Request.SubmitException;
49  import com.eviware.soapui.model.project.Project;
50  import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
51  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
52  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionsResult;
53  import com.eviware.soapui.model.support.InterfaceListenerAdapter;
54  import com.eviware.soapui.model.support.ModelSupport;
55  import com.eviware.soapui.model.support.ProjectListenerAdapter;
56  import com.eviware.soapui.model.support.TestPropertyListenerAdapter;
57  import com.eviware.soapui.model.support.TestStepBeanProperty;
58  import com.eviware.soapui.model.testsuite.AssertionError;
59  import com.eviware.soapui.model.testsuite.AssertionsListener;
60  import com.eviware.soapui.model.testsuite.TestAssertion;
61  import com.eviware.soapui.model.testsuite.TestCaseRunContext;
62  import com.eviware.soapui.model.testsuite.TestCaseRunner;
63  import com.eviware.soapui.model.testsuite.TestProperty;
64  import com.eviware.soapui.model.testsuite.TestStep;
65  import com.eviware.soapui.model.testsuite.TestStepProperty;
66  import com.eviware.soapui.model.testsuite.TestStepResult;
67  import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
68  import com.eviware.soapui.support.resolver.ChangeRestMethodResolver;
69  import com.eviware.soapui.support.resolver.ImportInterfaceResolver;
70  import com.eviware.soapui.support.resolver.RemoveTestStepResolver;
71  import com.eviware.soapui.support.resolver.ResolveContext;
72  import com.eviware.soapui.support.resolver.ResolveContext.PathToResolve;
73  import com.eviware.soapui.support.types.StringToStringMap;
74  
75  public class RestTestRequestStep extends WsdlTestStepWithProperties implements RestTestRequestStepInterface
76  {
77  	private final static Logger log = Logger.getLogger( RestTestRequestStep.class );
78  	private RestRequestStepConfig restRequestStepConfig;
79  	private RestTestRequest testRequest;
80  	private RestResource restResource;
81  	private RestMethod restMethod;
82  	private final InternalProjectListener projectListener = new InternalProjectListener();
83  	private final InternalInterfaceListener interfaceListener = new InternalInterfaceListener();
84  	private WsdlSubmit<RestRequest> submit;
85  
86  	public RestTestRequestStep( WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest )
87  			throws ItemDeletedException
88  	{
89  		super( testCase, config, true, forLoadTest );
90  
91  		if( getConfig().getConfig() != null )
92  		{
93  			restRequestStepConfig = ( RestRequestStepConfig )getConfig().getConfig().changeType(
94  					RestRequestStepConfig.type );
95  
96  			testRequest = buildTestRequest( forLoadTest );
97  			if( testRequest == null )
98  				throw new ItemDeletedException();
99  
100 			// testRequest = new RestTestRequest( null,
101 			// requestStepConfig.getRestRequest(), this, forLoadTest );
102 			testRequest.addPropertyChangeListener( this );
103 			testRequest.addTestPropertyListener( new InternalTestPropertyListener() );
104 
105 			if( config.isSetName() )
106 				testRequest.setName( config.getName() );
107 			else
108 				config.setName( testRequest.getName() );
109 		}
110 		else
111 		{
112 			restRequestStepConfig = ( RestRequestStepConfig )getConfig().addNewConfig().changeType(
113 					RestRequestStepConfig.type );
114 		}
115 
116 		for( TestProperty property : testRequest.getProperties().values() )
117 		{
118 			addProperty( new RestTestStepProperty( ( RestParamProperty )property ) );
119 		}
120 
121 		// init default properties
122 		addProperty( new TestStepBeanProperty( "Endpoint", false, testRequest, "endpoint", this ) );
123 		addProperty( new TestStepBeanProperty( "Username", false, testRequest, "username", this ) );
124 		addProperty( new TestStepBeanProperty( "Password", false, testRequest, "password", this ) );
125 		addProperty( new TestStepBeanProperty( "Domain", false, testRequest, "domain", this ) );
126 
127 		// init properties
128 		addProperty( new TestStepBeanProperty( "Request", false, testRequest, "requestContent", this )
129 		{
130 			@Override
131 			public String getDefaultValue()
132 			{
133 				return createDefaultRequestContent();
134 			}
135 		} );
136 
137 		addProperty( new TestStepBeanProperty( "ResponseAsXml", true, testRequest, "responseContentAsXml", this )
138 		{
139 			@Override
140 			public String getDefaultValue()
141 			{
142 				return createDefaultResponseXmlContent();
143 			}
144 		} );
145 
146 		addProperty( new TestStepBeanProperty( "Response", true, testRequest, "responseContentAsString", this )
147 		{
148 			@Override
149 			public String getDefaultValue()
150 			{
151 				return createDefaultRawResponseContent();
152 			}
153 		} );
154 
155 		initRestTestRequest();
156 
157 		if( !forLoadTest && restResource != null )
158 		{
159 			getResource().getInterface().getProject().addProjectListener( projectListener );
160 			getResource().getInterface().addInterfaceListener( interfaceListener );
161 
162 			// we need to listen for name changes which happen when interfaces
163 			// are
164 			getResource().getInterface().addPropertyChangeListener( this );
165 			getResource().addPropertyChangeListener( this );
166 		}
167 
168 		if( getRestMethod() != null )
169 		{
170 			getRestMethod().addPropertyChangeListener( this );
171 		}
172 	}
173 
174 	public void beforeSave()
175 	{
176 		super.beforeSave();
177 
178 		if( testRequest != null )
179 			testRequest.beforeSave();
180 	}
181 
182 	public RestRequestStepConfig getRequestStepConfig()
183 	{
184 		return restRequestStepConfig;
185 	}
186 
187 	protected RestTestRequest buildTestRequest( boolean forLoadTest )
188 	{
189 		if( getRestMethod() == null )
190 			return null;
191 		return new RestTestRequest( getRestMethod(), getRequestStepConfig().getRestRequest(), this, forLoadTest );
192 	}
193 
194 	private void initRestTestRequest()
195 	{
196 		if( getResource() == null )
197 			setDisabled( true );
198 		else
199 			getTestRequest().setResource( getResource() );
200 		if( getRestMethod() == null )
201 			setDisabled( true );
202 		else
203 			getTestRequest().setRestMethod( getRestMethod() );
204 	}
205 
206 	public String getService()
207 	{
208 		return getRequestStepConfig().getService();
209 	}
210 
211 	public String getResourcePath()
212 	{
213 		return getRequestStepConfig().getResourcePath();
214 	}
215 
216 	protected String createDefaultRawResponseContent()
217 	{
218 		return getResource() == null ? null : getResource().createResponse( true );
219 	}
220 
221 	protected String createDefaultResponseXmlContent()
222 	{
223 		return getResource() == null ? null : getResource().createResponse( true );
224 	}
225 
226 	protected String createDefaultRequestContent()
227 	{
228 		return getResource() == null ? null : getResource().createRequest( true );
229 	}
230 
231 	@Override
232 	public Collection<Interface> getRequiredInterfaces()
233 	{
234 		ArrayList<Interface> result = new ArrayList<Interface>();
235 		result.add( findRestResource().getInterface() );
236 		return result;
237 	}
238 
239 	private RestResource findRestResource()
240 	{
241 		Project project = ModelSupport.getModelItemProject( this );
242 		RestService restService = ( RestService )project.getInterfaceByName( getRequestStepConfig().getService() );
243 		if( restService != null )
244 		{
245 			return restService.getResourceByFullPath( getRequestStepConfig().getResourcePath() );
246 		}
247 		return null;
248 	}
249 
250 	private RestMethod findRestMethod()
251 	{
252 		if( !restRequestStepConfig.isSetMethodName() )
253 		{
254 			RestRequestConverter.updateRestTestRequest( this );
255 			
256 			// Must be an old version RestRequest...
257 			if( getResource() == null )
258 			{
259 				restResource = RestRequestConverter.resolveResource( this );
260 				if( restResource == null )
261 					return null;
262 				getRequestStepConfig().setService( restResource.getInterface().getName() );
263 				getRequestStepConfig().setResourcePath( restResource.getFullPath() );
264 			}
265 			RestMethod method = RestRequestConverter.getMethod( getResource(), getRequestStepConfig().getRestRequest()
266 					.selectAttribute( null, "method" ).newCursor().getTextValue(), getRequestStepConfig().getRestRequest()
267 					.getName() );
268 			restRequestStepConfig.setMethodName( method.getName() );
269 			return method;
270 		}
271 		return ( RestMethod )getWsdlModelItemByName( getResource().getRestMethodList(), getRequestStepConfig()
272 				.getMethodName() );
273 	}
274 
275 	public RestMethod getRestMethod()
276 	{
277 		if( restMethod == null )
278 			restMethod = findRestMethod();
279 		return restMethod;
280 	}
281 
282 	public RestResource getResource()
283 	{
284 		if( restResource == null )
285 			restResource = findRestResource();
286 		return restResource;
287 	}
288 
289 	public Operation getOperation()
290 	{
291 		return getResource();
292 	}
293 
294 	@Override
295 	public void release()
296 	{
297 		super.release();
298 
299 		if( restResource != null )
300 		{
301 			restResource.removePropertyChangeListener( this );
302 			restResource.getInterface().getProject().removeProjectListener( projectListener );
303 			restResource.getInterface().removeInterfaceListener( interfaceListener );
304 			restResource.getInterface().removePropertyChangeListener( this );
305 		}
306 	}
307 
308 	@Override
309 	public void resetConfigOnMove( TestStepConfig config )
310 	{
311 		super.resetConfigOnMove( config );
312 
313 		restRequestStepConfig = ( RestRequestStepConfig )config.getConfig().changeType( RestRequestStepConfig.type );
314 		testRequest.updateConfig( restRequestStepConfig.getRestRequest() );
315 	}
316 
317 	public void propertyChange( PropertyChangeEvent evt )
318 	{
319 		if( evt.getSource() == restResource )
320 		{
321 			if( evt.getPropertyName().equals( RestResource.PATH_PROPERTY ) )
322 			{
323 				getRequestStepConfig().setResourcePath( restResource.getFullPath() );
324 			}
325 			else if( evt.getPropertyName().equals( "childMethods" ) && restMethod == evt.getOldValue() )
326 			{
327 				// TODO: Convert to HttpTestRequestStep
328 				log.debug( "Removing test step due to removed Rest method" );
329 				getTestCase().removeTestStep( RestTestRequestStep.this );
330 			}
331 		}
332 		else if( restResource != null && evt.getSource() == restResource.getInterface() )
333 		{
334 			if( evt.getPropertyName().equals( Interface.NAME_PROPERTY ) )
335 			{
336 				getRequestStepConfig().setService( ( String )evt.getNewValue() );
337 			}
338 		}
339 		else if( evt.getSource() == restMethod )
340 		{
341 			if( evt.getPropertyName().equals( RestMethod.NAME_PROPERTY ) )
342 			{
343 				getRequestStepConfig().setMethodName( ( String )evt.getNewValue() );
344 			}
345 		}
346 		if( evt.getPropertyName().equals( TestAssertion.CONFIGURATION_PROPERTY )
347 				|| evt.getPropertyName().equals( TestAssertion.DISABLED_PROPERTY ) )
348 		{
349 			if( getTestRequest().getResponse() != null )
350 			{
351 				getTestRequest().assertResponse( new WsdlTestRunContext( this ) );
352 			}
353 		}
354 		else
355 		{
356 			if( evt.getSource() == testRequest && evt.getPropertyName().equals( WsdlTestRequest.NAME_PROPERTY ) )
357 			{
358 				if( !super.getName().equals( ( String )evt.getNewValue() ) )
359 					super.setName( ( String )evt.getNewValue() );
360 			}
361 
362 			notifyPropertyChanged( evt.getPropertyName(), evt.getOldValue(), evt.getNewValue() );
363 		}
364 
365 		// TODO copy from HttpTestRequestStep super.propertyChange( evt );
366 	}
367 
368 	public class InternalProjectListener extends ProjectListenerAdapter
369 	{
370 		@Override
371 		public void interfaceRemoved( Interface iface )
372 		{
373 			if( restResource != null && restResource.getInterface().equals( iface ) )
374 			{
375 				log.debug( "Removing test step due to removed interface" );
376 				( getTestCase() ).removeTestStep( RestTestRequestStep.this );
377 			}
378 		}
379 	}
380 
381 	public class InternalInterfaceListener extends InterfaceListenerAdapter
382 	{
383 		@Override
384 		public void operationRemoved( Operation operation )
385 		{
386 			if( operation == restResource )
387 			{
388 				log.debug( "Removing test step due to removed operation" );
389 				( getTestCase() ).removeTestStep( RestTestRequestStep.this );
390 			}
391 		}
392 
393 		@Override
394 		public void operationUpdated( Operation operation )
395 		{
396 			if( operation == restResource )
397 			{
398 				// requestStepConfig.setResourcePath( operation.get );
399 			}
400 		}
401 	}
402 
403 	@Override
404 	public boolean dependsOn( AbstractWsdlModelItem<?> modelItem )
405 	{
406 		if( modelItem instanceof Interface && getTestRequest().getOperation() != null
407 				&& getTestRequest().getOperation().getInterface() == modelItem )
408 		{
409 			return true;
410 		}
411 		else if( modelItem instanceof Operation && getTestRequest().getOperation() == modelItem )
412 		{
413 			return true;
414 		}
415 
416 		return false;
417 	}
418 
419 	public void setRestMethod( RestMethod method )
420 	{
421 		if( restMethod == method )
422 			return;
423 
424 		RestMethod oldMethod = restMethod;
425 		restMethod = method;
426 		getRequestStepConfig().setService( method.getInterface().getName() );
427 		getRequestStepConfig().setResourcePath( method.getResource().getFullPath() );
428 		getRequestStepConfig().setMethodName( method.getName() );
429 
430 		if( oldMethod != null )
431 			oldMethod.removePropertyChangeListener( this );
432 
433 		restMethod.addPropertyChangeListener( this );
434 		getTestRequest().setRestMethod( restMethod );
435 	}
436 
437 	public void setResource( RestResource operation )
438 	{
439 		if( restResource == operation )
440 			return;
441 
442 		RestResource oldOperation = restResource;
443 		restResource = operation;
444 		getRequestStepConfig().setService( operation.getInterface().getName() );
445 		getRequestStepConfig().setResourcePath( operation.getFullPath() );
446 
447 		if( oldOperation != null )
448 			oldOperation.removePropertyChangeListener( this );
449 
450 		restResource.addPropertyChangeListener( this );
451 		getTestRequest().setResource( restResource );
452 	}
453 
454 	public RestTestRequest getTestRequest()
455 	{
456 		return testRequest;
457 	}
458 
459 	public Interface getInterface()
460 	{
461 		return getResource() == null ? null : getResource().getInterface();
462 	}
463 
464 	@Override
465 	public ImageIcon getIcon()
466 	{
467 		return testRequest == null ? null : testRequest.getIcon();
468 	}
469 
470 	public TestStep getTestStep()
471 	{
472 		return this;
473 	}
474 
475 	@SuppressWarnings( "unchecked" )
476 	public void resolve( ResolveContext<?> context )
477 	{
478 		super.resolve( context );
479 
480 		if( getRestMethod() == null )
481 		{
482 			if( context.hasThisModelItem( this, "Missing REST Method in Project", getRequestStepConfig().getService()
483 					+ "/" + getRequestStepConfig().getMethodName() ) )
484 				return;
485 			context.addPathToResolve( this, "Missing REST Method in Project",
486 					getRequestStepConfig().getService() + "/" + getRequestStepConfig().getMethodName() ).addResolvers(
487 					new RemoveTestStepResolver( this ), new ImportInterfaceResolver( this )
488 					{
489 						@Override
490 						protected boolean update()
491 						{
492 							RestMethod restMethod = findRestMethod();
493 							if( restMethod == null )
494 								return false;
495 
496 							setRestMethod( restMethod );
497 							initRestTestRequest();
498 							setDisabled( false );
499 							return true;
500 						}
501 
502 					}, new ChangeRestMethodResolver( this )
503 					{
504 						@Override
505 						public boolean update()
506 						{
507 							RestMethod restMethod = getSelectedRestMethod();
508 							if( restMethod == null )
509 								return false;
510 
511 							setRestMethod( restMethod );
512 							initRestTestRequest();
513 							setDisabled( false );
514 							return true;
515 						}
516 
517 						protected Interface[] getInterfaces( WsdlProject project )
518 						{
519 							List<RestService> interfaces = ModelSupport.getChildren( project, RestService.class );
520 							return interfaces.toArray( new Interface[interfaces.size()] );
521 						}
522 					} );
523 		}
524 		else
525 		{
526 			getRestMethod().resolve( context );
527 			if( context.hasThisModelItem( this, "Missing REST Method in Project", getRequestStepConfig().getService()
528 					+ "/" + getRequestStepConfig().getMethodName() ) )
529 			{
530 				PathToResolve path = context.getPath( this, "Missing REST Method in Project", getRequestStepConfig()
531 						.getService()
532 						+ "/" + getRequestStepConfig().getMethodName() );
533 				path.setSolved( true );
534 			}
535 		}
536 	}
537 	
538 	@Override
539 	public void prepare( TestCaseRunner testRunner, TestCaseRunContext testRunContext ) throws Exception
540 	{
541 		super.prepare( testRunner, testRunContext );
542 
543 		testRequest.setResponse( null, testRunContext );
544 
545 		for( TestAssertion assertion : testRequest.getAssertionList() )
546 		{
547 			assertion.prepare( testRunner, testRunContext );
548 		}
549 	}
550 
551 	/*
552 	 * @SuppressWarnings("unchecked") public void resolve(ResolveContext<?> context)
553 	 * { super.resolve(context);
554 	 * 
555 	 * if (getResource() == null) { if (context.hasThisModelItem(this,
556 	 * "Missing REST Resource in Project", getRequestStepConfig() .getService() +
557 	 * "/" + getRequestStepConfig().getResourcePath())) return;
558 	 * context.addPathToResolve( this, "Missing REST Resource in Project",
559 	 * getRequestStepConfig().getService() + "/" +
560 	 * getRequestStepConfig().getResourcePath()) .addResolvers(new
561 	 * RemoveTestStepResolver(this), new ImportInterfaceResolver(this) {
562 	 * 
563 	 * @Override protected boolean update() { RestResource restResource =
564 	 * findRestResource(); if (restResource == null) return false;
565 	 * 
566 	 * setResource(restResource); initRestTestRequest(); setDisabled(false);
567 	 * return true; }
568 	 * 
569 	 * }, new ChangeOperationResolver(this, "Resource") {
570 	 * 
571 	 * @Override public boolean update() { RestResource restResource =
572 	 * (RestResource) getSelectedOperation(); if (restResource == null) return
573 	 * false;
574 	 * 
575 	 * setResource(restResource); initRestTestRequest(); setDisabled(false);
576 	 * return true; }
577 	 * 
578 	 * protected Interface[] getInterfaces( WsdlProject project) {
579 	 * List<RestService> interfaces = ModelSupport .getChildren(project,
580 	 * RestService.class); return interfaces .toArray(new Interface[interfaces
581 	 * .size()]); } }); } else { getResource().resolve(context); if
582 	 * (context.hasThisModelItem(this, "Missing REST Resource in Project",
583 	 * getRequestStepConfig() .getService() + "/" +
584 	 * getRequestStepConfig().getResourcePath())) { PathToResolve path =
585 	 * context.getPath(this, "Missing REST Resource in Project",
586 	 * getRequestStepConfig().getService() + "/" +
587 	 * getRequestStepConfig().getResourcePath()); path.setSolved(true); } } }
588 	 */
589 
590 	public PropertyExpansion[] getPropertyExpansions()
591 	{
592 		PropertyExpansionsResult result = new PropertyExpansionsResult( this, testRequest );
593 
594 		result.extractAndAddAll( "requestContent" );
595 		result.extractAndAddAll( "endpoint" );
596 		result.extractAndAddAll( "username" );
597 		result.extractAndAddAll( "password" );
598 		result.extractAndAddAll( "domain" );
599 
600 		StringToStringMap requestHeaders = testRequest.getRequestHeaders();
601 		for( String key : requestHeaders.keySet() )
602 		{
603 			result.extractAndAddAll( new RequestHeaderHolder( requestHeaders, key ), "value" );
604 		}
605 
606 		// result.addAll( testRequest.getWssContainer().getPropertyExpansions()
607 		// );
608 
609 		return result.toArray( new PropertyExpansion[result.size()] );
610 	}
611 
612 	public class RequestHeaderHolder
613 	{
614 		private final StringToStringMap valueMap;
615 		private final String key;
616 
617 		public RequestHeaderHolder( StringToStringMap valueMap, String key )
618 		{
619 			this.valueMap = valueMap;
620 			this.key = key;
621 		}
622 
623 		public String getValue()
624 		{
625 			return valueMap.get( key );
626 		}
627 
628 		public void setValue( String value )
629 		{
630 			valueMap.put( key, value );
631 			testRequest.setRequestHeaders( valueMap );
632 		}
633 	}
634 
635 	public AbstractHttpRequest<?> getHttpRequest()
636 	{
637 		return testRequest;
638 	}
639 
640 	public TestAssertion addAssertion( String type )
641 	{
642 		WsdlMessageAssertion result = testRequest.addAssertion( type );
643 		return result;
644 	}
645 
646 	public void addAssertionsListener( AssertionsListener listener )
647 	{
648 		testRequest.addAssertionsListener( listener );
649 	}
650 
651 	public TestAssertion cloneAssertion( TestAssertion source, String name )
652 	{
653 		return testRequest.cloneAssertion( source, name );
654 	}
655 
656 	public String getAssertableContent()
657 	{
658 		return testRequest.getAssertableContent();
659 	}
660 
661 	public AssertableType getAssertableType()
662 	{
663 		return testRequest.getAssertableType();
664 	}
665 
666 	public TestAssertion getAssertionByName( String name )
667 	{
668 		return testRequest.getAssertionByName( name );
669 	}
670 
671 	public List<TestAssertion> getAssertionList()
672 	{
673 		return testRequest.getAssertionList();
674 	}
675 
676 	public AssertionStatus getAssertionStatus()
677 	{
678 		return testRequest.getAssertionStatus();
679 	}
680 
681 	public void removeAssertion( TestAssertion assertion )
682 	{
683 		testRequest.removeAssertion( assertion );
684 	}
685 
686 	public void removeAssertionsListener( AssertionsListener listener )
687 	{
688 		testRequest.removeAssertionsListener( listener );
689 	}
690 
691 	public TestAssertion moveAssertion( int ix, int offset )
692 	{
693 		return testRequest.moveAssertion( ix, offset );
694 	}
695 
696 	public Map<String, TestAssertion> getAssertions()
697 	{
698 		return testRequest.getAssertions();
699 	}
700 
701 	public WsdlMessageAssertion getAssertionAt( int index )
702 	{
703 		return testRequest.getAssertionAt( index );
704 	}
705 
706 	public int getAssertionCount()
707 	{
708 		return testRequest == null ? 0 : testRequest.getAssertionCount();
709 	}
710 
711 	public String getDefaultAssertableContent()
712 	{
713 		return testRequest.getDefaultAssertableContent();
714 	}
715 
716 	public TestStepResult run( TestCaseRunner runner, TestCaseRunContext runContext )
717 	{
718 		RestRequestStepResult testStepResult = new RestRequestStepResult( this );
719 
720 		try
721 		{
722 			submit = testRequest.submit( runContext, false );
723 			HttpResponse response = ( HttpResponse )submit.getResponse();
724 
725 			if( submit.getStatus() != Submit.Status.CANCELED )
726 			{
727 				if( submit.getStatus() == Submit.Status.ERROR )
728 				{
729 					testStepResult.setStatus( TestStepStatus.FAILED );
730 					testStepResult.addMessage( submit.getError().toString() );
731 
732 					testRequest.setResponse( null, runContext );
733 				}
734 				else if( response == null )
735 				{
736 					testStepResult.setStatus( TestStepStatus.FAILED );
737 					testStepResult.addMessage( "Request is missing response" );
738 
739 					testRequest.setResponse( null, runContext );
740 				}
741 				else
742 				{
743 					runContext.setProperty( AssertedXPathsContainer.ASSERTEDXPATHSCONTAINER_PROPERTY, testStepResult );
744 					testRequest.setResponse( response, runContext );
745 
746 					testStepResult.setTimeTaken( response.getTimeTaken() );
747 					testStepResult.setSize( response.getContentLength() );
748 					testStepResult.setResponse( response );
749 
750 					switch( testRequest.getAssertionStatus() )
751 					{
752 					case FAILED :
753 						testStepResult.setStatus( TestStepStatus.FAILED );
754 						break;
755 					case VALID :
756 						testStepResult.setStatus( TestStepStatus.OK );
757 						break;
758 					case UNKNOWN :
759 						testStepResult.setStatus( TestStepStatus.UNKNOWN );
760 						break;
761 					}
762 				}
763 			}
764 			else
765 			{
766 				testStepResult.setStatus( TestStepStatus.CANCELED );
767 				testStepResult.addMessage( "Request was canceled" );
768 			}
769 
770 			if( response != null )
771 			{
772 				testStepResult.setRequestContent( response.getRequestContent() );
773 				testStepResult.addProperty( "URL", response.getURL() == null ? "<missing>" : response.getURL().toString() );
774 				testStepResult.addProperty( "Method", String.valueOf( response.getMethod() ) );
775 				testStepResult.addProperty( "StatusCode", String.valueOf( response.getStatusCode() ) );
776 				testStepResult.addProperty( "HTTP Version", response.getHttpVersion() );
777 			}
778 			else
779 				testStepResult.setRequestContent( testRequest.getRequestContent() );
780 		}
781 		catch( SubmitException e )
782 		{
783 			testStepResult.setStatus( TestStepStatus.FAILED );
784 			testStepResult.addMessage( "SubmitException: " + e );
785 		}
786 		finally
787 		{
788 			submit = null;
789 		}
790 
791 		testStepResult.setDomain( PropertyExpander.expandProperties( runContext, testRequest.getDomain() ) );
792 		testStepResult.setUsername( PropertyExpander.expandProperties( runContext, testRequest.getUsername() ) );
793 		testStepResult.setEndpoint( PropertyExpander.expandProperties( runContext, testRequest.getEndpoint() ) );
794 		testStepResult.setPassword( PropertyExpander.expandProperties( runContext, testRequest.getPassword() ) );
795 		testStepResult.setEncoding( PropertyExpander.expandProperties( runContext, testRequest.getEncoding() ) );
796 
797 		if( testStepResult.getStatus() != TestStepStatus.CANCELED )
798 		{
799 			AssertionStatus assertionStatus = testRequest.getAssertionStatus();
800 			switch( assertionStatus )
801 			{
802 			case FAILED :
803 			{
804 				testStepResult.setStatus( TestStepStatus.FAILED );
805 				if( getAssertionCount() == 0 )
806 				{
807 					testStepResult.addMessage( "Invalid/empty response" );
808 				}
809 				else
810 					for( int c = 0; c < getAssertionCount(); c++ )
811 					{
812 						AssertionError[] errors = getAssertionAt( c ).getErrors();
813 						if( errors != null )
814 						{
815 							for( AssertionError error : errors )
816 							{
817 								testStepResult.addMessage( error.getMessage() );
818 							}
819 						}
820 					}
821 
822 				break;
823 			}
824 			}
825 		}
826 
827 		return testStepResult;
828 	}
829 
830 	private class InternalTestPropertyListener extends TestPropertyListenerAdapter
831 	{
832 		@Override
833 		public void propertyAdded( String name )
834 		{
835 			RestTestRequestStep.this.addProperty( new RestTestStepProperty( getTestRequest().getProperty( name ) ), true );
836 		}
837 
838 		@Override
839 		public void propertyRemoved( String name )
840 		{
841 			RestTestRequestStep.this.deleteProperty( name, true );
842 		}
843 
844 		@Override
845 		public void propertyRenamed( String oldName, String newName )
846 		{
847 			RestTestRequestStep.this.propertyRenamed( oldName );
848 		}
849 
850 		@Override
851 		public void propertyValueChanged( String name, String oldValue, String newValue )
852 		{
853 			RestTestRequestStep.this.firePropertyValueChanged( name, oldValue, newValue );
854 		}
855 
856 		@Override
857 		public void propertyMoved( String name, int oldIndex, int newIndex )
858 		{
859 			RestTestRequestStep.this.firePropertyMoved( name, oldIndex, newIndex );
860 		}
861 	}
862 
863 	private class RestTestStepProperty implements TestStepProperty
864 	{
865 		private RestParamProperty property;
866 
867 		public RestTestStepProperty( RestParamProperty property )
868 		{
869 			this.property = property;
870 		}
871 
872 		public TestStep getTestStep()
873 		{
874 			return RestTestRequestStep.this;
875 		}
876 
877 		public String getName()
878 		{
879 			return property.getName();
880 		}
881 
882 		public String getDescription()
883 		{
884 			return property.getDescription();
885 		}
886 
887 		public String getValue()
888 		{
889 			return property.getValue();
890 		}
891 
892 		public String getDefaultValue()
893 		{
894 			return property.getDefaultValue();
895 		}
896 
897 		public void setValue( String value )
898 		{
899 			property.setValue( value );
900 		}
901 
902 		public boolean isReadOnly()
903 		{
904 			return false;
905 		}
906 
907 		public QName getType()
908 		{
909 			return property.getType();
910 		}
911 
912 		public ModelItem getModelItem()
913 		{
914 			return getTestRequest();
915 		}
916 	}
917 }