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 org.apache.xmlbeans.XmlCursor;
27 import org.apache.xmlbeans.XmlException;
28 import org.apache.xmlbeans.XmlObject;
29 import org.apache.xmlbeans.XmlOptions;
30 import org.w3c.dom.Document;
31 import org.w3c.dom.Element;
32 import org.w3c.dom.Node;
33 import org.w3c.dom.NodeList;
34
35 import com.eviware.soapui.impl.rest.RestMethod;
36 import com.eviware.soapui.impl.rest.RestRepresentation;
37 import com.eviware.soapui.impl.rest.RestRequestInterface;
38 import com.eviware.soapui.impl.rest.RestResource;
39 import com.eviware.soapui.impl.rest.RestService;
40 import com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder.ParameterStyle;
41 import com.eviware.soapui.impl.wsdl.support.Constants;
42 import com.eviware.soapui.impl.wsdl.support.UrlSchemaLoader;
43 import com.eviware.soapui.impl.wsdl.support.xsd.SchemaUtils;
44 import com.eviware.soapui.support.StringUtils;
45 import com.eviware.soapui.support.Tools;
46 import com.eviware.soapui.support.UISupport;
47 import com.eviware.soapui.support.xml.XmlUtils;
48
49 import net.java.dev.wadl.x2009.x02.ApplicationDocument;
50 import net.java.dev.wadl.x2009.x02.ParamStyle;
51 import net.java.dev.wadl.x2009.x02.RepresentationDocument;
52 import net.java.dev.wadl.x2009.x02.ResourceTypeDocument;
53 import net.java.dev.wadl.x2009.x02.ApplicationDocument.Application;
54 import net.java.dev.wadl.x2009.x02.DocDocument.Doc;
55 import net.java.dev.wadl.x2009.x02.MethodDocument.Method;
56 import net.java.dev.wadl.x2009.x02.ParamDocument.Param;
57 import net.java.dev.wadl.x2009.x02.RepresentationDocument.Representation;
58 import net.java.dev.wadl.x2009.x02.ResourceDocument.Resource;
59 import net.java.dev.wadl.x2009.x02.ResourcesDocument.Resources;
60 import net.java.dev.wadl.x2009.x02.ResponseDocument.Response;
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 = baseResource == null ? service.addNewResource( name, path ) : baseResource
137 .addNewChildResource( name, path );
138 initResourceFromWadlResource( newResource, resource );
139
140 addSubResources( newResource, resource );
141 }
142 }
143 }
144 catch( Exception e )
145 {
146 UISupport.showErrorMessage( e );
147 }
148 }
149
150 private void addSubResources( RestResource newResource, Resource resource )
151 {
152 for( Resource res : resource.getResourceList() )
153 {
154 String name = getFirstTitle( res.getDocList(), res.getPath() );
155 String path = res.getPath();
156
157 RestResource newRes = newResource.addNewChildResource( name, path );
158 initResourceFromWadlResource( newRes, res );
159
160 addSubResources( newRes, res );
161 }
162 }
163
164 private String getFirstTitle( List<Doc> list, String defaultTitle )
165 {
166 for( Doc doc : list )
167 {
168 if( StringUtils.hasContent( doc.getTitle() ) )
169 {
170 return doc.getTitle();
171 }
172 }
173 return defaultTitle;
174 }
175
176 private void initResourceFromWadlResource( RestResource newResource, Resource resource )
177 {
178 for( Param param : resource.getParamList() )
179 {
180 String nm = param.getName();
181 RestParamProperty prop = newResource.hasProperty( nm ) ? newResource.getProperty( nm ) : newResource
182 .addProperty( nm );
183
184 initParam( param, prop );
185 }
186
187 for( Method method : resource.getMethodList() )
188 {
189 method = resolveMethod( method );
190 initMethod( newResource, method );
191 }
192
193 List types = resource.getType();
194 if( types != null && types.size() > 0 )
195 {
196 for( Object obj : types )
197 {
198 ResourceTypeDocument.ResourceType type = resolveResource( obj.toString() );
199 if( type != null )
200 {
201 for( Method method : type.getMethodList() )
202 {
203 method = resolveMethod( method );
204 RestMethod restMethod = initMethod( newResource, method );
205
206 for( Param param : type.getParamList() )
207 {
208 String nm = param.getName();
209 RestParamProperty prop = restMethod.hasProperty( nm ) ? restMethod.getProperty( nm ) : restMethod
210 .addProperty( nm );
211
212 initParam( param, prop );
213 }
214 }
215 }
216 }
217 }
218 }
219
220 private RestMethod initMethod( RestResource newResource, Method method )
221 {
222 String name = method.getName();
223 if( StringUtils.hasContent( method.getId() ) )
224 name += " - " + method.getId();
225
226 RestMethod restMethod = newResource.addNewMethod( getFirstTitle( method.getDocList(), name ) );
227 restMethod.setMethod( RestRequestInterface.RequestMethod.valueOf( method.getName() ) );
228
229 if( method.getRequest() != null )
230 {
231 for( Param param : method.getRequest().getParamList() )
232 {
233 RestParamProperty p = restMethod.addProperty( param.getName() );
234 initParam( param, p );
235 }
236
237 for( Representation representation : method.getRequest().getRepresentationList() )
238 {
239 representation = resolveRepresentation( representation );
240 addRepresentationFromConfig( restMethod, representation, RestRepresentation.Type.REQUEST, null );
241 }
242 }
243
244 for( Response response : method.getResponseList() )
245 {
246 for( Representation representation : response.getRepresentationList() )
247 {
248 addRepresentation(response, restMethod, representation);
249 }
250 if(!isWADL11)
251 {
252 NodeList children = response.getDomNode().getChildNodes();
253 for(int i=0; i<children.getLength(); i++)
254 {
255 Node n = children.item( i );
256 if( "fault".equals(n.getNodeName()) ) {
257 String content = XmlUtils.serialize( n, false );
258 try
259 {
260 Map<Object,Object> map = new HashMap<Object, Object>();
261 XmlCursor cursor = response.newCursor();
262 cursor.getAllNamespaces( map );
263 cursor.dispose();
264 XmlOptions options = new XmlOptions();
265 options.setLoadAdditionalNamespaces( map );
266 XmlObject obj = XmlObject.Factory.parse( content.replaceFirst( "<(([a-z]+:)?)fault ", "<$1representation " ), options );
267 RepresentationDocument representation = ( RepresentationDocument )obj.changeType( RepresentationDocument.type );
268 addRepresentation(response, restMethod, representation.getRepresentation());
269 }
270 catch( XmlException e )
271 {
272 }
273 }
274 }
275 }
276 }
277
278 RestRequestInterface request = restMethod.addNewRequest( "Request 1" );
279
280 return restMethod;
281 }
282
283 private void addRepresentation(Response response, RestMethod restMethod, Representation representation)
284 {
285 representation = resolveRepresentation( representation );
286 List<Long> status = null;
287 if( isWADL11 )
288 status = response.getStatus();
289 else
290 {
291 Node n = representation.getDomNode().getAttributes().getNamedItem( "status" );
292 if(n != null)
293 {
294 status = new ArrayList<Long>();
295 for(String s : n.getNodeValue().split( " " ) )
296 {
297 status.add( Long.parseLong( s ) );
298 }
299 }
300 }
301 boolean fault = false;
302 if(status != null && status.size() > 0)
303 {
304 fault = true;
305 for( Long s : status )
306 {
307 if(s < 400)
308 {
309 fault = false;
310 break;
311 }
312 }
313 }
314 RestRepresentation.Type type = fault ? RestRepresentation.Type.FAULT : RestRepresentation.Type.RESPONSE;
315 addRepresentationFromConfig( restMethod, representation, type, status );
316 }
317
318 private void addRepresentationFromConfig( RestMethod restMethod, Representation representation,
319 RestRepresentation.Type type, List<?> status )
320 {
321 RestRepresentation restRepresentation = restMethod.addNewRepresentation( type );
322 restRepresentation.setMediaType( representation.getMediaType() );
323 restRepresentation.setElement( representation.getElement() );
324 if( status != null )
325 restRepresentation.setStatus( status );
326 restRepresentation.setId( representation.getId() );
327 restRepresentation.setDescription( getFirstTitle( representation.getDocList(), null ) );
328 }
329
330 private void initParam( Param param, RestParamProperty prop )
331 {
332 prop.setDefaultValue( param.getDefault() );
333 prop.setValue( param.getDefault() );
334 ParamStyle.Enum paramStyle = param.getStyle();
335 if( paramStyle == null )
336 paramStyle = ParamStyle.QUERY;
337
338 prop.setStyle( ParameterStyle.valueOf( paramStyle.toString().toUpperCase() ) );
339 prop.setRequired( param.getRequired() );
340 prop.setType( param.getType() );
341
342 String[] options = new String[param.sizeOfOptionArray()];
343 for( int c = 0; c < options.length; c++ )
344 options[c] = param.getOptionArray( c ).getValue();
345
346 if( options.length > 0 )
347 prop.setOptions( options );
348 }
349
350 private Method resolveMethod( Method method )
351 {
352 String href = method.getHref();
353 if( !StringUtils.hasContent( href ) )
354 return method;
355
356 for( Method m : application.getMethodList() )
357 {
358 if( m.getId().equals( href.substring( 1 ) ) )
359 return m;
360 }
361
362 try
363 {
364 ApplicationDocument applicationDocument = loadReferencedWadl( href );
365 if( applicationDocument != null )
366 {
367 int ix = href.lastIndexOf( '#' );
368 if( ix > 0 )
369 href = href.substring( ix + 1 );
370
371 for( Method m : application.getMethodList() )
372 {
373 if( m.getId().equals( href ) )
374 return m;
375 }
376 }
377 }
378 catch( Exception e )
379 {
380 e.printStackTrace();
381 }
382
383 return method;
384 }
385
386 private Representation resolveRepresentation( Representation representation )
387 {
388 String href = representation.getHref();
389 if( !StringUtils.hasContent( href ) )
390 return representation;
391
392 try
393 {
394 ApplicationDocument applicationDocument = loadReferencedWadl( href );
395 if( applicationDocument != null )
396 {
397 int ix = href.lastIndexOf( '#' );
398 if( ix > 0 )
399 href = href.substring( ix + 1 );
400
401 for( Representation m : application.getRepresentationList() )
402 {
403 if( m.getId().equals( href ) )
404 return m;
405 }
406 }
407 }
408 catch( Exception e )
409 {
410 e.printStackTrace();
411 }
412
413 return representation;
414 }
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432 private ResourceTypeDocument.ResourceType resolveResource( String id )
433 {
434 for( ResourceTypeDocument.ResourceType resourceType : application.getResourceTypeList() )
435 {
436 if( resourceType.getId().equals( id ) )
437 return resourceType;
438 }
439
440 try
441 {
442 ApplicationDocument applicationDocument = loadReferencedWadl( id );
443 if( applicationDocument != null )
444 {
445 int ix = id.lastIndexOf( '#' );
446 if( ix > 0 )
447 id = id.substring( ix + 1 );
448
449 for( ResourceTypeDocument.ResourceType resourceType : applicationDocument.getApplication()
450 .getResourceTypeList() )
451 {
452 if( resourceType.getId().equals( id ) )
453 return resourceType;
454 }
455 }
456 }
457 catch( Exception e )
458 {
459 e.printStackTrace();
460 }
461
462 return null;
463 }
464
465 private ApplicationDocument loadReferencedWadl( String id ) throws URISyntaxException, XmlException, IOException
466 {
467 int ix = id.indexOf( '#' );
468 if( ix != -1 )
469 id = id.substring( 0, ix );
470 ApplicationDocument applicationDocument = refCache.get( id );
471
472 if( applicationDocument == null )
473 {
474 URI uri = new URI( id );
475 applicationDocument = ApplicationDocument.Factory.parse( uri.toURL() );
476 refCache.put( id, applicationDocument );
477 }
478
479 return applicationDocument;
480 }
481
482 public static Map<String, XmlObject> getDefinitionParts( String wadlUrl )
483 {
484 Map<String, XmlObject> result = new HashMap<String, XmlObject>();
485
486 try
487 {
488 return SchemaUtils.getSchemas( wadlUrl, new UrlSchemaLoader( wadlUrl ) );
489
490
491
492
493
494 }
495 catch( Exception e )
496 {
497 e.printStackTrace();
498 }
499
500 return result;
501 }
502
503 public static String extractParams( URL param, RestParamsPropertyHolder params )
504 {
505 String path = param.getPath();
506 String[] items = path.split( "/" );
507
508 int templateParamCount = 0;
509 StringBuffer resultPath = new StringBuffer();
510
511 for( int i = 0; i < items.length; i++ )
512 {
513 String item = items[i];
514 try
515 {
516 String[] matrixParams = item.split( ";" );
517 if( matrixParams.length > 0 )
518 {
519 item = matrixParams[0];
520 for( int c = 1; c < matrixParams.length; c++ )
521 {
522 String matrixParam = matrixParams[c];
523
524 int ix = matrixParam.indexOf( '=' );
525 if( ix == -1 )
526 {
527 params.addProperty( URLDecoder.decode( matrixParam, "Utf-8" ) ).setStyle( ParameterStyle.MATRIX );
528 }
529 else
530 {
531 String name = matrixParam.substring( 0, ix );
532 RestParamProperty property = params.addProperty( URLDecoder.decode( name, "Utf-8" ) );
533 property.setStyle( ParameterStyle.MATRIX );
534 property.setValue( URLDecoder.decode( matrixParam.substring( ix + 1 ), "Utf-8" ) );
535 }
536 }
537 }
538
539 Integer.parseInt( item );
540 RestParamProperty prop = params.addProperty( "param" + templateParamCount++ );
541 prop.setStyle( ParameterStyle.TEMPLATE );
542 prop.setValue( item );
543
544 item = "{" + prop.getName() + "}";
545 }
546 catch( Exception e )
547 {
548 }
549
550 if( StringUtils.hasContent( item ) )
551 resultPath.append( '/' ).append( item );
552 }
553
554 String query = ( ( URL )param ).getQuery();
555 if( StringUtils.hasContent( query ) )
556 {
557 items = query.split( "&" );
558 for( String item : items )
559 {
560 try
561 {
562 int ix = item.indexOf( '=' );
563 if( ix == -1 )
564 {
565 params.addProperty( URLDecoder.decode( item, "Utf-8" ) ).setStyle( ParameterStyle.QUERY );
566 }
567 else
568 {
569 String name = item.substring( 0, ix );
570 RestParamProperty property = params.addProperty( URLDecoder.decode( name, "Utf-8" ) );
571 property.setStyle( ParameterStyle.QUERY );
572 property.setValue( URLDecoder.decode( item.substring( ix + 1 ), "Utf-8" ) );
573 }
574 }
575 catch( UnsupportedEncodingException e )
576 {
577 e.printStackTrace();
578 }
579 }
580 }
581
582 return resultPath.toString();
583 }
584 }