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