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