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.rest;
14  
15  import java.beans.PropertyChangeEvent;
16  import java.net.MalformedURLException;
17  import java.net.URL;
18  import java.util.ArrayList;
19  import java.util.List;
20  import java.util.Map;
21  
22  import javax.xml.namespace.QName;
23  
24  import org.apache.xmlbeans.SchemaGlobalElement;
25  import org.apache.xmlbeans.SchemaType;
26  import org.apache.xmlbeans.XmlException;
27  import org.apache.xmlbeans.XmlString;
28  
29  import com.eviware.soapui.config.AttachmentConfig;
30  import com.eviware.soapui.config.RestRequestConfig;
31  import com.eviware.soapui.config.StringToStringMapConfig;
32  import com.eviware.soapui.impl.rest.RestRepresentation.Type;
33  import com.eviware.soapui.impl.rest.support.RestParamProperty;
34  import com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder;
35  import com.eviware.soapui.impl.rest.support.RestRequestParamsPropertyHolder;
36  import com.eviware.soapui.impl.support.AbstractHttpRequest;
37  import com.eviware.soapui.impl.wsdl.HttpAttachmentPart;
38  import com.eviware.soapui.impl.wsdl.WsdlSubmit;
39  import com.eviware.soapui.impl.wsdl.submit.RequestTransportRegistry;
40  import com.eviware.soapui.impl.wsdl.submit.transports.http.HttpResponse;
41  import com.eviware.soapui.impl.wsdl.support.PathUtils;
42  import com.eviware.soapui.model.ModelItem;
43  import com.eviware.soapui.model.iface.MessagePart;
44  import com.eviware.soapui.model.iface.SubmitContext;
45  import com.eviware.soapui.model.iface.MessagePart.ContentPart;
46  import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
47  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
48  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionsResult;
49  import com.eviware.soapui.model.testsuite.TestProperty;
50  import com.eviware.soapui.model.testsuite.TestPropertyListener;
51  import com.eviware.soapui.support.StringUtils;
52  import com.eviware.soapui.support.UISupport;
53  import com.eviware.soapui.support.types.StringList;
54  import com.eviware.soapui.support.types.StringToStringMap;
55  
56  /***
57   * Request implementation holding a SOAP request
58   * 
59   * @author Ole.Matzura
60   */
61  
62  public class RestRequest extends AbstractHttpRequest<RestRequestConfig> implements RestRequestInterface
63  {
64  	private RestMethod method;
65  	private RestParamsPropertyHolder params;
66  	private ParamUpdater paramUpdater;
67  
68  	public RestRequest( RestMethod method, RestRequestConfig requestConfig, boolean forLoadTest )
69  	{
70  		super( requestConfig, method.getOperation(), "/rest_request.gif", false );
71  		this.method = method;
72  
73  		if( requestConfig.getParameters() == null )
74  			requestConfig.addNewParameters();
75  
76  		StringToStringMap paramValues = StringToStringMap.fromXml( requestConfig.getParameters() );
77  		params = new RestRequestParamsPropertyHolder( method.getOverlayParams(), this, paramValues );
78  		paramUpdater = new ParamUpdater( paramValues );
79  		params.addTestPropertyListener( paramUpdater );
80  
81  		if( method != null )
82  			method.addPropertyChangeListener( this );
83  	}
84  
85  	public ModelItem getParent()
86  	{
87  		return getRestMethod();
88  	}
89  
90  	public RestMethod getRestMethod()
91  	{
92  		return method;
93  	}
94  
95  	protected RequestIconAnimator<?> initIconAnimator()
96  	{
97  		return new RequestIconAnimator<AbstractHttpRequest<?>>( this, "/rest_request.gif", "/exec_rest_request", 4, "gif" );
98  	}
99  
100 	public MessagePart[] getRequestParts()
101 	{
102 		List<MessagePart> result = new ArrayList<MessagePart>();
103 
104 		for( int c = 0; c < getPropertyCount(); c++ )
105 		{
106 			result.add( new ParameterMessagePart( getPropertyAt( c ) ) );
107 		}
108 
109 		if( getMethod() == RestRequestInterface.RequestMethod.POST
110 				|| getMethod() == RestRequestInterface.RequestMethod.PUT )
111 		{
112 			result.add( new RestContentPart() );
113 		}
114 
115 		return result.toArray( new MessagePart[result.size()] );
116 	}
117 
118 	public RestRepresentation[] getRepresentations()
119 	{
120 		return getRepresentations( null, null );
121 	}
122 
123 	public RestRepresentation[] getRepresentations( RestRepresentation.Type type )
124 	{
125 		return getRepresentations( type, null );
126 	}
127 
128 	public RestRepresentation[] getRepresentations( RestRepresentation.Type type, String mediaType )
129 	{
130 		return getRestMethod().getRepresentations( type, mediaType );
131 	}
132 
133 	public MessagePart[] getResponseParts()
134 	{
135 		return new MessagePart[0];
136 	}
137 
138 	public RestRequestInterface.RequestMethod getMethod()
139 	{
140 		return getRestMethod().getMethod();
141 	}
142 
143 	public String getAccept()
144 	{
145 		String accept = getConfig().getAccept();
146 		return accept == null ? "" : accept;
147 	}
148 
149 	public void setAccept( String acceptEncoding )
150 	{
151 		String old = getAccept();
152 		getConfig().setAccept( acceptEncoding );
153 		notifyPropertyChanged( "accept", old, acceptEncoding );
154 	}
155 
156 	public void setMediaType( String mediaType )
157 	{
158 		String old = getMediaType();
159 		getConfig().setMediaType( mediaType );
160 		notifyPropertyChanged( "mediaType", old, mediaType );
161 	}
162 
163 	public String getMediaType()
164 	{
165 		if( getConfig().getMediaType() == null )
166 		{
167 			String mediaType = getRestMethod().getDefaultRequestMediaType();
168 			getConfig().setMediaType( mediaType );
169 			notifyPropertyChanged( "mediaType", null, mediaType );
170 		}
171 		return getConfig().getMediaType();
172 	}
173 
174 	public void setMethod( RequestMethod method )
175 	{
176 		getRestMethod().setMethod( method );
177 	}
178 
179 	public WsdlSubmit<RestRequest> submit( SubmitContext submitContext, boolean async ) throws SubmitException
180 	{
181 		String endpoint = PropertyExpander.expandProperties( submitContext, getEndpoint() );
182 
183 		if( StringUtils.isNullOrEmpty( endpoint ) )
184 		{
185 			try
186 			{
187 				endpoint = new URL( getPath() ).toString();
188 			}
189 			catch( MalformedURLException e )
190 			{
191 			}
192 		}
193 
194 		if( StringUtils.isNullOrEmpty( endpoint ) )
195 		{
196 			UISupport.showErrorMessage( "Missing endpoint for request [" + getName() + "]" );
197 			return null;
198 		}
199 
200 		try
201 		{
202 			WsdlSubmit<RestRequest> submitter = new WsdlSubmit<RestRequest>( this, getSubmitListeners(),
203 					RequestTransportRegistry.getTransport( endpoint, submitContext ) );
204 			submitter.submitRequest( submitContext, async );
205 			return submitter;
206 		}
207 		catch( Exception e )
208 		{
209 			throw new SubmitException( e.toString() );
210 		}
211 	}
212 
213 	public PropertyExpansion[] getPropertyExpansions()
214 	{
215 		PropertyExpansionsResult result = new PropertyExpansionsResult( this, this );
216 		result.addAll( super.getPropertyExpansions() );
217 		result.addAll( getRestMethod().getPropertyExpansions() );
218 
219 		return result.toArray();
220 	}
221 
222 	public TestProperty addProperty( String name )
223 	{
224 		return params.addProperty( name );
225 	}
226 
227 	public void moveProperty( String propertyName, int targetIndex )
228 	{
229 		params.moveProperty( propertyName, targetIndex );
230 	}
231 
232 	public TestProperty removeProperty( String propertyName )
233 	{
234 		return params.removeProperty( propertyName );
235 	}
236 
237 	public boolean renameProperty( String name, String newName )
238 	{
239 		return params.renameProperty( name, newName );
240 	}
241 
242 	public void addTestPropertyListener( TestPropertyListener listener )
243 	{
244 		params.addTestPropertyListener( listener );
245 	}
246 
247 	public ModelItem getModelItem()
248 	{
249 		return this;
250 	}
251 
252 	@Override
253 	public RestResource getOperation()
254 	{
255 		return ( RestResource )method.getOperation();
256 	}
257 
258 	public Map<String, TestProperty> getProperties()
259 	{
260 		return params.getProperties();
261 	}
262 
263 	public RestParamProperty getProperty( String name )
264 	{
265 		return params.getProperty( name );
266 	}
267 
268 	public RestParamProperty getPropertyAt( int index )
269 	{
270 		return params.getPropertyAt( index );
271 	}
272 
273 	public int getPropertyCount()
274 	{
275 		return params.getPropertyCount();
276 	}
277 
278 	public String[] getPropertyNames()
279 	{
280 		return params.getPropertyNames();
281 	}
282 
283 	public String getPropertyValue( String name )
284 	{
285 		return params.getPropertyValue( name );
286 	}
287 
288 	public boolean hasProperty( String name )
289 	{
290 		return params.hasProperty( name );
291 	}
292 
293 	public void removeTestPropertyListener( TestPropertyListener listener )
294 	{
295 		params.removeTestPropertyListener( listener );
296 	}
297 
298 	public void setPropertyValue( String name, String value )
299 	{
300 		params.setPropertyValue( name, value );
301 	}
302 
303 	public void resetPropertyValues()
304 	{
305 		params.clear();
306 		for( String name : params.getPropertyNames() )
307 		{
308 			params.getProperty( name ).setValue( params.getProperty( name ).getDefaultValue() );
309 		}
310 	}
311 
312 	public void propertyChange( PropertyChangeEvent evt )
313 	{
314 		if( evt.getPropertyName().equals( "path" ) )
315 		{
316 			notifyPropertyChanged( "path", null, getPath() );
317 		}
318 		else if( evt.getPropertyName().equals( "method" ) )
319 		{
320 			notifyPropertyChanged( "method", evt.getOldValue(), evt.getNewValue() );
321 		}
322 	}
323 
324 	public String[] getResponseMediaTypes()
325 	{
326 		StringList result = new StringList();
327 
328 		for( RestRepresentation representation : getRepresentations( Type.RESPONSE, null ) )
329 		{
330 			if( !result.contains( representation.getMediaType() ) )
331 				result.add( representation.getMediaType() );
332 		}
333 
334 		return result.toStringArray();
335 	}
336 
337 	public boolean isPostQueryString()
338 	{
339 		return hasRequestBody() && getConfig().getPostQueryString();
340 	}
341 
342 	public void setPostQueryString( boolean b )
343 	{
344 		boolean old = isPostQueryString();
345 		getConfig().setPostQueryString( b );
346 		notifyPropertyChanged( "postQueryString", old, b );
347 
348 		if( !"multipart/form-data".equals( getMediaType() ) )
349 		{
350 			setMediaType( b ? "application/x-www-form-urlencoded" : getMediaType() );
351 		}
352 	}
353 
354 	public final static class ParameterMessagePart extends MessagePart.ParameterPart
355 	{
356 		private String name;
357 
358 		public ParameterMessagePart( TestProperty propertyAt )
359 		{
360 			this.name = propertyAt.getName();
361 		}
362 
363 		@Override
364 		public SchemaType getSchemaType()
365 		{
366 			return XmlString.type;
367 		}
368 
369 		@Override
370 		public SchemaGlobalElement getPartElement()
371 		{
372 			return null;
373 		}
374 
375 		@Override
376 		public QName getPartElementName()
377 		{
378 			return new QName( getName() );
379 		}
380 
381 		public String getDescription()
382 		{
383 			return null;
384 		}
385 
386 		public String getName()
387 		{
388 			return name;
389 		}
390 	}
391 
392 	public String getPropertiesLabel()
393 	{
394 		return "Request Params";
395 	}
396 
397 	public RestParamsPropertyHolder getParams()
398 	{
399 		return params;
400 	}
401 
402 	public HttpAttachmentPart getAttachmentPart( String partName )
403 	{
404 		return null;
405 	}
406 
407 	public HttpAttachmentPart[] getDefinedAttachmentParts()
408 	{
409 		return new HttpAttachmentPart[0];
410 	}
411 
412 	public class RestContentPart extends ContentPart implements MessagePart
413 	{
414 		@Override
415 		public SchemaGlobalElement getPartElement()
416 		{
417 			return null;
418 		}
419 
420 		@Override
421 		public QName getPartElementName()
422 		{
423 			return null;
424 		}
425 
426 		@Override
427 		public SchemaType getSchemaType()
428 		{
429 			return null;
430 		}
431 
432 		public String getDescription()
433 		{
434 			return null;
435 		}
436 
437 		public String getName()
438 		{
439 			return null;
440 		}
441 
442 		public String getMediaType()
443 		{
444 			return getConfig().getMediaType();
445 		}
446 	}
447 
448 	public boolean hasRequestBody()
449 	{
450 		return getRestMethod().hasRequestBody();
451 	}
452 
453 	public RestResource getResource()
454 	{
455 		return getOperation();
456 	}
457 
458 	public String getPath()
459 	{
460 		if( !StringUtils.isNullOrEmpty( getConfig().getFullPath() ) || getResource() == null )
461 			return getConfig().getFullPath();
462 		else
463 			return getResource().getFullPath();
464 	}
465 
466 	public void setPath( String fullPath )
467 	{
468 		String old = getPath();
469 
470 		if( getResource() != null && getResource().getFullPath().equals( fullPath ) )
471 			getConfig().unsetFullPath();
472 		else
473 			getConfig().setFullPath( fullPath );
474 
475 		notifyPropertyChanged( "path", old, fullPath );
476 	}
477 
478 	public String getResponseContentAsXml()
479 	{
480 		HttpResponse response = getResponse();
481 		if( response == null )
482 			return null;
483 
484 		return response.getContentAsXml();
485 	}
486 
487 	@Override
488 	public void release()
489 	{
490 		super.release();
491 
492 		if( getResource() != null )
493 			getResource().removePropertyChangeListener( this );
494 		
495 		
496 	}
497 
498 	public void updateConfig( RestRequestConfig request )
499 	{
500 		setConfig( request );
501 		
502 		updateParams();
503 
504 		List<AttachmentConfig> attachmentConfigs = getConfig().getAttachmentList();
505 		for( int i = 0; i < attachmentConfigs.size(); i++ )
506 		{
507 			AttachmentConfig config = attachmentConfigs.get( i );
508 			getAttachmentsList().get( i ).updateConfig( config );
509 		}
510 	}
511 
512 	protected void updateParams()
513 	{
514 		if( params != null && paramUpdater != null )
515 			params.removeTestPropertyListener( paramUpdater );
516 		
517 		StringToStringMap paramValues = StringToStringMap.fromXml( getConfig().getParameters() );
518 		params = new RestRequestParamsPropertyHolder( getRestMethod().getOverlayParams(), this, paramValues );
519 		paramUpdater = new ParamUpdater( paramValues );
520 		params.addTestPropertyListener( paramUpdater );
521 	}
522 
523 	public boolean hasEndpoint()
524 	{
525 		return super.hasEndpoint() || PathUtils.isHttpPath( getPath() );
526 	}
527 
528 	private class ParamUpdater implements TestPropertyListener
529 	{
530 		private StringToStringMap values;
531 
532 		public ParamUpdater( StringToStringMap paramValues )
533 		{
534 			values = paramValues;
535 		}
536 
537 		private void sync()
538 		{
539 			try
540 			{
541 				getConfig().setParameters( StringToStringMapConfig.Factory.parse( values.toXml() ) );
542 			}
543 			catch( XmlException e )
544 			{
545 				e.printStackTrace();
546 			}
547 		}
548 
549 		public void propertyAdded( String name )
550 		{
551 			sync();
552 		}
553 
554 		public void propertyMoved( String name, int oldIndex, int newIndex )
555 		{
556 			sync();
557 		}
558 
559 		public void propertyRemoved( String name )
560 		{
561 			sync();
562 		}
563 
564 		public void propertyRenamed( String oldName, String newName )
565 		{
566 			sync();
567 		}
568 
569 		public void propertyValueChanged( String name, String oldValue, String newValue )
570 		{
571 			sync();
572 		}
573 	}
574 
575 	public List<TestProperty> getPropertyList()
576 	{
577 		return params.getPropertyList();
578 	}
579 	
580 	protected void setRestMethod( RestMethod restMethod )
581 	{
582 		if( this.method != null )
583 			this.method.removePropertyChangeListener( this );
584 	
585 		this.method = restMethod;
586 		
587 		if( method != null )
588 			method.addPropertyChangeListener( this );
589 		
590 		updateParams();
591 	}
592 }