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 RestRequestParamsPropertyHolder 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.extractPropertyExpansions( modelItem, jmsHeaderConfig,
240 				JMSHeader.DURABLE_SUBSCRIPTION_NAME ) );
241 		result
242 				.addAll( PropertyExpansionUtils.extractPropertyExpansions( modelItem, jmsHeaderConfig, JMSHeader.CLIENT_ID ) );
243 		result.addAll( PropertyExpansionUtils.extractPropertyExpansions( modelItem, jmsHeaderConfig,
244 				JMSHeader.SEND_AS_BYTESMESSAGE ) );
245 		result.addAll( PropertyExpansionUtils.extractPropertyExpansions( modelItem, jmsHeaderConfig,
246 				JMSHeader.SOAP_ACTION_ADD ) );
247 
248 	}
249 
250 	public TestProperty addProperty( String name )
251 	{
252 		return params.addProperty( name );
253 	}
254 
255 	public void moveProperty( String propertyName, int targetIndex )
256 	{
257 		params.moveProperty( propertyName, targetIndex );
258 	}
259 
260 	public TestProperty removeProperty( String propertyName )
261 	{
262 		return params.removeProperty( propertyName );
263 	}
264 
265 	public boolean renameProperty( String name, String newName )
266 	{
267 		return params.renameProperty( name, newName );
268 	}
269 
270 	public void addTestPropertyListener( TestPropertyListener listener )
271 	{
272 		params.addTestPropertyListener( listener );
273 	}
274 
275 	public ModelItem getModelItem()
276 	{
277 		return this;
278 	}
279 
280 	@Override
281 	public RestResource getOperation()
282 	{
283 		return ( RestResource )method.getOperation();
284 	}
285 
286 	public Map<String, TestProperty> getProperties()
287 	{
288 		return params.getProperties();
289 	}
290 
291 	public RestParamProperty getProperty( String name )
292 	{
293 		return params.getProperty( name );
294 	}
295 
296 	public RestParamProperty getPropertyAt( int index )
297 	{
298 		return params.getPropertyAt( index );
299 	}
300 
301 	public int getPropertyCount()
302 	{
303 		return params.getPropertyCount();
304 	}
305 
306 	public String[] getPropertyNames()
307 	{
308 		return params.getPropertyNames();
309 	}
310 
311 	public String getPropertyValue( String name )
312 	{
313 		return params.getPropertyValue( name );
314 	}
315 
316 	public boolean hasProperty( String name )
317 	{
318 		return params.hasProperty( name );
319 	}
320 
321 	public void removeTestPropertyListener( TestPropertyListener listener )
322 	{
323 		params.removeTestPropertyListener( listener );
324 	}
325 
326 	public void setPropertyValue( String name, String value )
327 	{
328 		params.setPropertyValue( name, value );
329 	}
330 
331 	public void resetPropertyValues()
332 	{
333 		params.clear();
334 		for( String name : params.getPropertyNames() )
335 		{
336 			params.getProperty( name ).setValue( params.getProperty( name ).getDefaultValue() );
337 		}
338 	}
339 
340 	public void propertyChange( PropertyChangeEvent evt )
341 	{
342 		if( evt.getPropertyName().equals( "path" ) )
343 		{
344 			notifyPropertyChanged( "path", null, getPath() );
345 		}
346 		else if( evt.getPropertyName().equals( "method" ) )
347 		{
348 			notifyPropertyChanged( "method", evt.getOldValue(), evt.getNewValue() );
349 		}
350 	}
351 
352 	public String[] getResponseMediaTypes()
353 	{
354 		StringList result = new StringList();
355 
356 		for( RestRepresentation representation : getRepresentations( Type.RESPONSE, null ) )
357 		{
358 			if( !result.contains( representation.getMediaType() ) )
359 				result.add( representation.getMediaType() );
360 		}
361 
362 		return result.toStringArray();
363 	}
364 
365 	public boolean isPostQueryString()
366 	{
367 		return hasRequestBody() && getConfig().getPostQueryString();
368 	}
369 
370 	public void setPostQueryString( boolean b )
371 	{
372 		boolean old = isPostQueryString();
373 		getConfig().setPostQueryString( b );
374 		notifyPropertyChanged( "postQueryString", old, b );
375 
376 		if( !"multipart/form-data".equals( getMediaType() ) )
377 		{
378 			setMediaType( b ? "application/x-www-form-urlencoded" : getMediaType() );
379 		}
380 	}
381 
382 	public final static class ParameterMessagePart extends MessagePart.ParameterPart
383 	{
384 		private String name;
385 
386 		public ParameterMessagePart( TestProperty propertyAt )
387 		{
388 			this.name = propertyAt.getName();
389 		}
390 
391 		@Override
392 		public SchemaType getSchemaType()
393 		{
394 			return XmlString.type;
395 		}
396 
397 		@Override
398 		public SchemaGlobalElement getPartElement()
399 		{
400 			return null;
401 		}
402 
403 		@Override
404 		public QName getPartElementName()
405 		{
406 			return new QName( getName() );
407 		}
408 
409 		public String getDescription()
410 		{
411 			return null;
412 		}
413 
414 		public String getName()
415 		{
416 			return name;
417 		}
418 	}
419 
420 	public String getPropertiesLabel()
421 	{
422 		return "Request Params";
423 	}
424 
425 	public RestParamsPropertyHolder getParams()
426 	{
427 		return params;
428 	}
429 
430 	public HttpAttachmentPart getAttachmentPart( String partName )
431 	{
432 		return null;
433 	}
434 
435 	public HttpAttachmentPart[] getDefinedAttachmentParts()
436 	{
437 		return new HttpAttachmentPart[0];
438 	}
439 
440 	public class RestContentPart extends ContentPart implements MessagePart
441 	{
442 		@Override
443 		public SchemaGlobalElement getPartElement()
444 		{
445 			return null;
446 		}
447 
448 		@Override
449 		public QName getPartElementName()
450 		{
451 			return null;
452 		}
453 
454 		@Override
455 		public SchemaType getSchemaType()
456 		{
457 			return null;
458 		}
459 
460 		public String getDescription()
461 		{
462 			return null;
463 		}
464 
465 		public String getName()
466 		{
467 			return null;
468 		}
469 
470 		public String getMediaType()
471 		{
472 			return getConfig().getMediaType();
473 		}
474 	}
475 
476 	public boolean hasRequestBody()
477 	{
478 		return getRestMethod().hasRequestBody();
479 	}
480 
481 	public RestResource getResource()
482 	{
483 		return getOperation();
484 	}
485 
486 	public String getPath()
487 	{
488 		if( !StringUtils.isNullOrEmpty( getConfig().getFullPath() ) || getResource() == null )
489 			return getConfig().getFullPath();
490 		else
491 			return getResource().getFullPath();
492 	}
493 
494 	public void setPath( String fullPath )
495 	{
496 		String old = getPath();
497 
498 		if( getResource() != null && getResource().getFullPath().equals( fullPath ) )
499 			getConfig().unsetFullPath();
500 		else
501 			getConfig().setFullPath( fullPath );
502 
503 		notifyPropertyChanged( "path", old, fullPath );
504 	}
505 
506 	public String getResponseContentAsXml()
507 	{
508 		HttpResponse response = getResponse();
509 		if( response == null )
510 			return null;
511 
512 		return response.getContentAsXml();
513 	}
514 
515 	@Override
516 	public void release()
517 	{
518 		super.release();
519 
520 		if( method != null )
521 			method.removePropertyChangeListener( this );
522 
523 		params.removeTestPropertyListener( paramUpdater );
524 		params.release();
525 	}
526 
527 	public void updateConfig( RestRequestConfig request )
528 	{
529 		setConfig( request );
530 
531 		updateParams();
532 
533 		List<AttachmentConfig> attachmentConfigs = getConfig().getAttachmentList();
534 		for( int i = 0; i < attachmentConfigs.size(); i++ )
535 		{
536 			AttachmentConfig config = attachmentConfigs.get( i );
537 			getAttachmentsList().get( i ).updateConfig( config );
538 		}
539 
540 		if( jmsHeaderConfig != null )
541 		{
542 			jmsHeaderConfig.setJMSHeaderConfConfig( request.getJmsConfig() );
543 		}
544 
545 		if( jmsPropertyConfig != null )
546 		{
547 			jmsPropertyConfig.setJmsPropertyConfConfig( request.getJmsPropertyConfig() );
548 		}
549 	}
550 
551 	protected void updateParams()
552 	{
553 		StringToStringMap paramValues = StringToStringMap.fromXml( getConfig().getParameters() );
554 		params.reset( getRestMethod().getOverlayParams(), paramValues );
555 		paramUpdater.setValues( paramValues );
556 	}
557 
558 	public boolean hasEndpoint()
559 	{
560 		return super.hasEndpoint() || PathUtils.isHttpPath( getPath() );
561 	}
562 
563 	private class ParamUpdater implements TestPropertyListener
564 	{
565 		private StringToStringMap values;
566 
567 		public ParamUpdater( StringToStringMap paramValues )
568 		{
569 			values = paramValues;
570 		}
571 
572 		public void setValues( StringToStringMap paramValues )
573 		{
574 			values = paramValues;
575 		}
576 
577 		private void sync()
578 		{
579 			try
580 			{
581 				getConfig().setParameters( StringToStringMapConfig.Factory.parse( values.toXml() ) );
582 			}
583 			catch( XmlException e )
584 			{
585 				e.printStackTrace();
586 			}
587 		}
588 
589 		public void propertyAdded( String name )
590 		{
591 			sync();
592 		}
593 
594 		public void propertyMoved( String name, int oldIndex, int newIndex )
595 		{
596 			sync();
597 		}
598 
599 		public void propertyRemoved( String name )
600 		{
601 			sync();
602 		}
603 
604 		public void propertyRenamed( String oldName, String newName )
605 		{
606 			sync();
607 		}
608 
609 		public void propertyValueChanged( String name, String oldValue, String newValue )
610 		{
611 			sync();
612 		}
613 	}
614 
615 	public List<TestProperty> getPropertyList()
616 	{
617 		return params.getPropertyList();
618 	}
619 
620 	protected void setRestMethod( RestMethod restMethod )
621 	{
622 		if( this.method != null )
623 			this.method.removePropertyChangeListener( this );
624 
625 		this.method = restMethod;
626 
627 		if( method != null )
628 			method.addPropertyChangeListener( this );
629 
630 		updateParams();
631 	}
632 
633 	private JMSHeaderConfig jmsHeaderConfig;
634 	private JMSPropertiesConfig jmsPropertyConfig;
635 
636 	public JMSHeaderConfig getJMSHeaderConfig()
637 	{
638 		if( jmsHeaderConfig == null )
639 		{
640 			if( !getConfig().isSetJmsConfig() )
641 			{
642 				getConfig().addNewJmsConfig();
643 			}
644 			jmsHeaderConfig = new JMSHeaderConfig( getConfig().getJmsConfig(), this );
645 		}
646 		return jmsHeaderConfig;
647 	}
648 
649 	public JMSPropertiesConfig getJMSPropertiesConfig()
650 	{
651 		if( jmsPropertyConfig == null )
652 		{
653 			if( !getConfig().isSetJmsPropertyConfig() )
654 			{
655 				getConfig().addNewJmsPropertyConfig();
656 			}
657 			jmsPropertyConfig = new JMSPropertiesConfig( getConfig().getJmsPropertyConfig(), this );
658 		}
659 		return jmsPropertyConfig;
660 	}
661 
662 }