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