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