1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.rest.support;
14
15 import java.io.IOException;
16 import java.io.UnsupportedEncodingException;
17 import java.net.URI;
18 import java.net.URISyntaxException;
19 import java.net.URL;
20 import java.net.URLDecoder;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import net.java.dev.wadl.x2009.x02.ApplicationDocument;
27 import net.java.dev.wadl.x2009.x02.ParamStyle;
28 import net.java.dev.wadl.x2009.x02.RepresentationDocument;
29 import net.java.dev.wadl.x2009.x02.ResourceTypeDocument;
30 import net.java.dev.wadl.x2009.x02.ApplicationDocument.Application;
31 import net.java.dev.wadl.x2009.x02.DocDocument.Doc;
32 import net.java.dev.wadl.x2009.x02.MethodDocument.Method;
33 import net.java.dev.wadl.x2009.x02.ParamDocument.Param;
34 import net.java.dev.wadl.x2009.x02.RepresentationDocument.Representation;
35 import net.java.dev.wadl.x2009.x02.ResourceDocument.Resource;
36 import net.java.dev.wadl.x2009.x02.ResourcesDocument.Resources;
37 import net.java.dev.wadl.x2009.x02.ResponseDocument.Response;
38
39 import org.apache.xmlbeans.XmlCursor;
40 import org.apache.xmlbeans.XmlException;
41 import org.apache.xmlbeans.XmlObject;
42 import org.apache.xmlbeans.XmlOptions;
43 import org.w3c.dom.Document;
44 import org.w3c.dom.Element;
45 import org.w3c.dom.Node;
46 import org.w3c.dom.NodeList;
47
48 import com.eviware.soapui.impl.rest.RestMethod;
49 import com.eviware.soapui.impl.rest.RestRepresentation;
50 import com.eviware.soapui.impl.rest.RestRequestInterface;
51 import com.eviware.soapui.impl.rest.RestResource;
52 import com.eviware.soapui.impl.rest.RestService;
53 import com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder.ParameterStyle;
54 import com.eviware.soapui.impl.wsdl.support.Constants;
55 import com.eviware.soapui.impl.wsdl.support.UrlSchemaLoader;
56 import com.eviware.soapui.impl.wsdl.support.xsd.SchemaUtils;
57 import com.eviware.soapui.support.StringUtils;
58 import com.eviware.soapui.support.Tools;
59 import com.eviware.soapui.support.UISupport;
60 import com.eviware.soapui.support.xml.XmlUtils;
61
62 public class WadlImporter
63 {
64 private RestService service;
65 private Application application;
66 private List<Resources> resourcesList;
67 private Map<String, ApplicationDocument> refCache = new HashMap<String, ApplicationDocument>();
68 private boolean isWADL11 = true;
69
70 public WadlImporter( RestService service )
71 {
72 this.service = service;
73 }
74
75 public void initFromWadl( String wadlUrl )
76 {
77 try
78 {
79 XmlObject xmlObject = XmlObject.Factory.parse( new URL( wadlUrl ) );
80
81 Element element = ( ( Document )xmlObject.getDomNode() ).getDocumentElement();
82
83
84 if( element.getLocalName().equals( "application" )
85 && element.getNamespaceURI().startsWith( "http://research.sun.com/wadl" ) )
86 {
87 isWADL11 = false;
88 String content = xmlObject.xmlText();
89 content = content.replaceAll( "\"" + element.getNamespaceURI() + "\"", "\"" + Constants.WADL11_NS + "\"" );
90 xmlObject = ApplicationDocument.Factory.parse( content );
91 }
92 else if( !element.getLocalName().equals( "application" )
93 || !element.getNamespaceURI().equals( Constants.WADL11_NS ) )
94 {
95 throw new Exception( "Document is not a WADL application with " + Constants.WADL11_NS + " namespace" );
96 }
97
98 ApplicationDocument applicationDocument = ( ApplicationDocument )xmlObject
99 .changeType( ApplicationDocument.type );
100 application = applicationDocument.getApplication();
101
102 resourcesList = application.getResourcesList();
103
104 service.setName( getFirstTitle( application.getDocList(), service.getName() ) );
105
106 String base = resourcesList.size() == 1 ? resourcesList.get( 0 ).getBase() : "";
107
108 try
109 {
110 URL baseUrl = new URL( base );
111 service.setBasePath( baseUrl.getPath() );
112
113 service.addEndpoint( Tools.getEndpointFromUrl( baseUrl ) );
114 }
115 catch( Exception e )
116 {
117 service.setBasePath( base );
118 }
119
120 service.setWadlUrl( wadlUrl );
121 service.getConfig().setWadlVersion( isWADL11 ? Constants.WADL11_NS : Constants.WADL10_NS );
122
123 for( Resources resources : resourcesList )
124 {
125 RestResource baseResource = null;
126 if( resourcesList.size() > 1 )
127 {
128 String path = resources.getBase();
129 baseResource = service.addNewResource( path, path );
130 }
131 for( Resource resource : resources.getResourceList() )
132 {
133 String name = getFirstTitle( resource.getDocList(), resource.getPath() );
134 String path = resource.getPath();
135
136 RestResource newResource = null;
137
138 if( baseResource != null )
139 {
140 for( RestResource res : baseResource.getChildResourceList() )
141 {
142 if( res.getPath().equals( path ) )
143 {
144 newResource = res;
145 break;
146 }
147 }
148
149 if( newResource == null )
150 {
151 newResource = baseResource.addNewChildResource( name, path );
152 }
153 }
154 else
155 {
156 for( RestResource res : service.getResourceList() )
157 {
158 if( res.getPath().equals( path ) )
159 {
160 newResource = res;
161 break;
162 }
163 }
164
165 if( newResource == null )
166 {
167 newResource = service.addNewResource( name, path );
168 }
169 }
170
171 initResourceFromWadlResource( newResource, resource );
172 addSubResources( newResource, resource );
173 }
174 }
175 }
176 catch( Exception e )
177 {
178 UISupport.showErrorMessage( e );
179 }
180 }
181
182 private void addSubResources( RestResource newResource, Resource resource )
183 {
184 for( Resource res : resource.getResourceList() )
185 {
186 String name = getFirstTitle( res.getDocList(), res.getPath() );
187 String path = res.getPath();
188
189 RestResource newRes = newResource.addNewChildResource( name, path );
190 initResourceFromWadlResource( newRes, res );
191
192 addSubResources( newRes, res );
193 }
194 }
195
196 private String getFirstTitle( List<Doc> list, String defaultTitle )
197 {
198 for( Doc doc : list )
199 {
200 if( StringUtils.hasContent( doc.getTitle() ) )
201 {
202 return doc.getTitle();
203 }
204 }
205 return defaultTitle;
206 }
207
208 private void initResourceFromWadlResource( RestResource newResource, Resource resource )
209 {
210 for( Param param : resource.getParamList() )
211 {
212 String nm = param.getName();
213 RestParamProperty prop = newResource.hasProperty( nm ) ? newResource.getProperty( nm ) : newResource
214 .addProperty( nm );
215
216 initParam( param, prop );
217 }
218
219 for( Method method : resource.getMethodList() )
220 {
221 method = resolveMethod( method );
222 initMethod( newResource, method );
223 }
224
225 List<?> types = resource.getType();
226 if( types != null && types.size() > 0 )
227 {
228 for( Object obj : types )
229 {
230 ResourceTypeDocument.ResourceType type = resolveResource( obj.toString() );
231 if( type != null )
232 {
233 for( Method method : type.getMethodList() )
234 {
235 method = resolveMethod( method );
236 RestMethod restMethod = initMethod( newResource, method );
237
238 for( Param param : type.getParamList() )
239 {
240 String nm = param.getName();
241 RestParamProperty prop = restMethod.hasProperty( nm ) ? restMethod.getProperty( nm ) : restMethod
242 .addProperty( nm );
243
244 initParam( param, prop );
245 }
246 }
247 }
248 }
249 }
250 }
251
252 private RestMethod initMethod( RestResource newResource, Method method )
253 {
254
255 String name = getFirstTitle( method.getDocList(), method.getName() );
256 if( StringUtils.hasContent( method.getId() ) )
257 name += " - " + method.getId();
258
259
260 if( newResource.getRestMethodByName( name ) != null )
261 {
262 int cnt = 0;
263 String orgName = name;
264
265 while( newResource.getRestMethodByName( name ) != null )
266 {
267 cnt++ ;
268 name = orgName + "-" + cnt;
269 }
270 }
271
272
273 RestMethod restMethod = newResource.addNewMethod( name );
274 restMethod.setMethod( RestRequestInterface.RequestMethod.valueOf( method.getName() ) );
275
276 if( method.getRequest() != null )
277 {
278 for( Param param : method.getRequest().getParamList() )
279 {
280 RestParamProperty p = restMethod.addProperty( param.getName() );
281 initParam( param, p );
282 }
283
284 for( Representation representation : method.getRequest().getRepresentationList() )
285 {
286 representation = resolveRepresentation( representation );
287 addRepresentationFromConfig( restMethod, representation, RestRepresentation.Type.REQUEST, null );
288 }
289 }
290
291 for( Response response : method.getResponseList() )
292 {
293 for( Representation representation : response.getRepresentationList() )
294 {
295 addRepresentation( response, restMethod, representation );
296 }
297 if( !isWADL11 )
298 {
299 NodeList children = response.getDomNode().getChildNodes();
300 for( int i = 0; i < children.getLength(); i++ )
301 {
302 Node n = children.item( i );
303 if( "fault".equals( n.getNodeName() ) )
304 {
305 String content = XmlUtils.serialize( n, false );
306 try
307 {
308 Map<Object, Object> map = new HashMap<Object, Object>();
309 XmlCursor cursor = response.newCursor();
310 cursor.getAllNamespaces( map );
311 cursor.dispose();
312 XmlOptions options = new XmlOptions();
313 options.setLoadAdditionalNamespaces( map );
314 XmlObject obj = XmlObject.Factory.parse( content.replaceFirst( "<(([a-z]+:)?)fault ",
315 "<$1representation " ), options );
316 RepresentationDocument representation = ( RepresentationDocument )obj
317 .changeType( RepresentationDocument.type );
318 addRepresentation( response, restMethod, representation.getRepresentation() );
319 }
320 catch( XmlException e )
321 {
322 }
323 }
324 }
325 }
326 }
327
328 restMethod.addNewRequest( "Request 1" );
329 return restMethod;
330 }
331
332 private void addRepresentation( Response response, RestMethod restMethod, Representation representation )
333 {
334 representation = resolveRepresentation( representation );
335 List<Long> status = null;
336 if( isWADL11 )
337 status = response.getStatus();
338 else
339 {
340 Node n = representation.getDomNode().getAttributes().getNamedItem( "status" );
341 if( n != null )
342 {
343 status = new ArrayList<Long>();
344 for( String s : n.getNodeValue().split( " " ) )
345 {
346 status.add( Long.parseLong( s ) );
347 }
348 }
349 }
350 boolean fault = false;
351 if( status != null && status.size() > 0 )
352 {
353 fault = true;
354 for( Long s : status )
355 {
356 if( s < 400 )
357 {
358 fault = false;
359 break;
360 }
361 }
362 }
363 RestRepresentation.Type type = fault ? RestRepresentation.Type.FAULT : RestRepresentation.Type.RESPONSE;
364 addRepresentationFromConfig( restMethod, representation, type, status );
365 }
366
367 private void addRepresentationFromConfig( RestMethod restMethod, Representation representation,
368 RestRepresentation.Type type, List<?> status )
369 {
370 RestRepresentation restRepresentation = restMethod.addNewRepresentation( type );
371 restRepresentation.setMediaType( representation.getMediaType() );
372 restRepresentation.setElement( representation.getElement() );
373 if( status != null )
374 restRepresentation.setStatus( status );
375 restRepresentation.setId( representation.getId() );
376 restRepresentation.setDescription( getFirstTitle( representation.getDocList(), null ) );
377 }
378
379 private void initParam( Param param, RestParamProperty prop )
380 {
381 prop.setDefaultValue( param.getDefault() );
382 prop.setValue( param.getDefault() );
383 ParamStyle.Enum paramStyle = param.getStyle();
384 if( paramStyle == null )
385 paramStyle = ParamStyle.QUERY;
386
387 prop.setStyle( ParameterStyle.valueOf( paramStyle.toString().toUpperCase() ) );
388 prop.setRequired( param.getRequired() );
389 prop.setType( param.getType() );
390
391 String[] options = new String[param.sizeOfOptionArray()];
392 for( int c = 0; c < options.length; c++ )
393 options[c] = param.getOptionArray( c ).getValue();
394
395 if( options.length > 0 )
396 prop.setOptions( options );
397 }
398
399 private Method resolveMethod( Method method )
400 {
401 String href = method.getHref();
402 if( !StringUtils.hasContent( href ) )
403 return method;
404
405 for( Method m : application.getMethodList() )
406 {
407 if( m.getId().equals( href.substring( 1 ) ) )
408 return m;
409 }
410
411 try
412 {
413 ApplicationDocument applicationDocument = loadReferencedWadl( href );
414 if( applicationDocument != null )
415 {
416 int ix = href.lastIndexOf( '#' );
417 if( ix > 0 )
418 href = href.substring( ix + 1 );
419
420 for( Method m : application.getMethodList() )
421 {
422 if( m.getId().equals( href ) )
423 return m;
424 }
425 }
426 }
427 catch( Exception e )
428 {
429 e.printStackTrace();
430 }
431
432 return method;
433 }
434
435 private Representation resolveRepresentation( Representation representation )
436 {
437 String href = representation.getHref();
438 if( !StringUtils.hasContent( href ) )
439 return representation;
440
441 try
442 {
443 ApplicationDocument applicationDocument = loadReferencedWadl( href );
444 if( applicationDocument != null )
445 {
446 int ix = href.lastIndexOf( '#' );
447 if( ix > 0 )
448 href = href.substring( ix + 1 );
449
450 for( Representation m : application.getRepresentationList() )
451 {
452 if( m.getId().equals( href ) )
453 return m;
454 }
455 }
456 }
457 catch( Exception e )
458 {
459 e.printStackTrace();
460 }
461
462 return representation;
463 }
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481 private ResourceTypeDocument.ResourceType resolveResource( String id )
482 {
483 for( ResourceTypeDocument.ResourceType resourceType : application.getResourceTypeList() )
484 {
485 if( resourceType.getId().equals( id ) )
486 return resourceType;
487 }
488
489 try
490 {
491 ApplicationDocument applicationDocument = loadReferencedWadl( id );
492 if( applicationDocument != null )
493 {
494 int ix = id.lastIndexOf( '#' );
495 if( ix > 0 )
496 id = id.substring( ix + 1 );
497
498 for( ResourceTypeDocument.ResourceType resourceType : applicationDocument.getApplication()
499 .getResourceTypeList() )
500 {
501 if( resourceType.getId().equals( id ) )
502 return resourceType;
503 }
504 }
505 }
506 catch( Exception e )
507 {
508 e.printStackTrace();
509 }
510
511 return null;
512 }
513
514 private ApplicationDocument loadReferencedWadl( String id ) throws URISyntaxException, XmlException, IOException
515 {
516 int ix = id.indexOf( '#' );
517 if( ix != -1 )
518 id = id.substring( 0, ix );
519 ApplicationDocument applicationDocument = refCache.get( id );
520
521 if( applicationDocument == null )
522 {
523 URI uri = new URI( id );
524 applicationDocument = ApplicationDocument.Factory.parse( uri.toURL() );
525 refCache.put( id, applicationDocument );
526 }
527
528 return applicationDocument;
529 }
530
531 public static Map<String, XmlObject> getDefinitionParts( String wadlUrl )
532 {
533 Map<String, XmlObject> result = new HashMap<String, XmlObject>();
534
535 try
536 {
537 return SchemaUtils.getSchemas( wadlUrl, new UrlSchemaLoader( wadlUrl ) );
538
539
540
541
542
543 }
544 catch( Exception e )
545 {
546 e.printStackTrace();
547 }
548
549 return result;
550 }
551
552 public static String extractParams( URL param, RestParamsPropertyHolder params )
553 {
554 String path = param.getPath();
555 String[] items = path.split( "/" );
556
557 int templateParamCount = 0;
558 StringBuffer resultPath = new StringBuffer();
559
560 for( int i = 0; i < items.length; i++ )
561 {
562 String item = items[i];
563 try
564 {
565 String[] matrixParams = item.split( ";" );
566 if( matrixParams.length > 0 )
567 {
568 item = matrixParams[0];
569 for( int c = 1; c < matrixParams.length; c++ )
570 {
571 String matrixParam = matrixParams[c];
572
573 int ix = matrixParam.indexOf( '=' );
574 if( ix == -1 )
575 {
576 params.addProperty( URLDecoder.decode( matrixParam, "Utf-8" ) ).setStyle( ParameterStyle.MATRIX );
577 }
578 else
579 {
580 String name = matrixParam.substring( 0, ix );
581 RestParamProperty property = params.addProperty( URLDecoder.decode( name, "Utf-8" ) );
582 property.setStyle( ParameterStyle.MATRIX );
583 property.setValue( URLDecoder.decode( matrixParam.substring( ix + 1 ), "Utf-8" ) );
584 }
585 }
586 }
587
588 Integer.parseInt( item );
589 RestParamProperty prop = params.addProperty( "param" + templateParamCount++ );
590 prop.setStyle( ParameterStyle.TEMPLATE );
591 prop.setValue( item );
592
593 item = "{" + prop.getName() + "}";
594 }
595 catch( Exception e )
596 {
597 }
598
599 if( StringUtils.hasContent( item ) )
600 resultPath.append( '/' ).append( item );
601 }
602
603 String query = ( ( URL )param ).getQuery();
604 if( StringUtils.hasContent( query ) )
605 {
606 items = query.split( "&" );
607 for( String item : items )
608 {
609 try
610 {
611 int ix = item.indexOf( '=' );
612 if( ix == -1 )
613 {
614 params.addProperty( URLDecoder.decode( item, "Utf-8" ) ).setStyle( ParameterStyle.QUERY );
615 }
616 else
617 {
618 String name = item.substring( 0, ix );
619 RestParamProperty property = params.addProperty( URLDecoder.decode( name, "Utf-8" ) );
620 property.setStyle( ParameterStyle.QUERY );
621 property.setValue( URLDecoder.decode( item.substring( ix + 1 ), "Utf-8" ) );
622 }
623 }
624 catch( UnsupportedEncodingException e )
625 {
626 e.printStackTrace();
627 }
628 }
629 }
630
631 return resultPath.toString();
632 }
633 }