1 package org.codehaus.xfire.xmlbeans.generator;
2
3 import java.net.URL;
4 import java.util.ArrayList;
5 import java.util.HashSet;
6 import java.util.Iterator;
7 import java.util.List;
8 import java.util.Set;
9
10 import javax.xml.namespace.QName;
11
12 import org.apache.xmlbeans.SchemaType;
13 import org.apache.xmlbeans.SchemaTypeLoader;
14 import org.apache.xmlbeans.XmlAnySimpleType;
15 import org.apache.xmlbeans.XmlBeans;
16 import org.apache.xmlbeans.XmlObject;
17 import org.apache.xmlbeans.XmlOptions;
18 import org.xml.sax.EntityResolver;
19 import org.xmlsoap.schemas.wsdl.DefinitionsDocument;
20 import org.xmlsoap.schemas.wsdl.TBinding;
21 import org.xmlsoap.schemas.wsdl.TBindingOperation;
22 import org.xmlsoap.schemas.wsdl.TDefinitions;
23 import org.xmlsoap.schemas.wsdl.TMessage;
24 import org.xmlsoap.schemas.wsdl.TOperation;
25 import org.xmlsoap.schemas.wsdl.TParam;
26 import org.xmlsoap.schemas.wsdl.TPart;
27 import org.xmlsoap.schemas.wsdl.TPortType;
28 import org.xmlsoap.schemas.wsdl.TService;
29
30 /***
31 * Inspects WSDL documents and provide handy classes to examine the
32 * content.
33 *
34 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
35 * @since Oct 27, 2004
36 */
37 public class WSDLInspector
38 {
39 public final static String schemaNS =
40 "declare namespace xs=\"http://www.w3.org/2001/XMLSchema\"";
41 public final static String wsdlNS =
42 "declare namespace wsdl=\"http://schemas.xmlsoap.org/wsdl/\"";
43 public final static String wsdlSoapNS =
44 "declare namespace soap=\"http://schemas.xmlsoap.org/wsdl/soap/\"";
45 public final static String httpNS =
46 "declare namespace http=\"http://schemas.xmlsoap.org/wsdl/http/";
47
48 SchemaTypeLoader loader =
49 XmlBeans.typeLoaderForClassLoader(XmlObject.class.getClassLoader());
50
51 public List generateServices(URL document) throws Exception
52 {
53 EntityResolver entResolver = null;
54
55 XmlOptions options = new XmlOptions();
56 options.setLoadLineNumbers();
57
58 options.setEntityResolver(entResolver);
59
60 SchemaTypeLoader wloader =
61 XmlBeans.typeLoaderForClassLoader(TDefinitions.class.getClassLoader());
62 XmlObject wsdldoc = wloader.parse(document, null, options);
63
64 TDefinitions defs = ((DefinitionsDocument)wsdldoc).getDefinitions();
65 XmlObject[] types = defs.getTypesArray();
66
67 ArrayList services = new ArrayList();
68
69 TService[] xServices = defs.getServiceArray();
70 for ( int i = 0; i < xServices.length; i++ )
71 {
72 TService xService = xServices[i];
73
74 Service service = new Service();
75
76 XmlObject[] xAddresses = xService.selectPath(wsdlSoapNS + " $this//soap:address");
77 if (xAddresses == null || xAddresses.length == 0)
78 {
79 xAddresses = xService.selectPath(httpNS + " $this//http:address");
80 if (xAddresses == null || xAddresses.length == 0)
81 break;
82
83 service.setRest(true);
84 break;
85 }
86
87 service.setName(xService.getName());
88 service.setUrl(xAddresses[0].selectAttribute("","location").newCursor().getTextValue());
89 service.setXmlObject(xService);
90 service.setBinding(xService.getPortArray(0).getBinding());
91
92 TBinding xBinding = getBinding( defs, service.getBinding() );
93 if ( xBinding == null )
94 throw new RuntimeException("Couldn't find binding!");
95
96 service.setPortType(xBinding.getType());
97
98 TPortType xPortType = getPortType( defs, service.getPortType() );
99 if ( xPortType == null )
100 throw new RuntimeException("Couldn't find port type!");
101
102 TBindingOperation[] xOperations = xBinding.getOperationArray();
103
104 for ( int j = 0; j < xOperations.length; j++ )
105 {
106 ServiceMethod m = createMethod( xOperations[j], xPortType, defs );
107
108 service.addMethod(m);
109 }
110
111 services.add(service);
112 }
113
114 return services;
115 }
116
117 private ServiceMethod createMethod(TBindingOperation xOperation, TPortType portType, TDefinitions defs)
118 {
119 ServiceMethod m = new ServiceMethod();
120 m.setName(xOperation.getName());
121
122 TOperation abstractOp = getAbstractOperation( m.getName(), portType );
123 TParam input = abstractOp.getInput();
124 TMessage message = getMessage( input.getMessage().getLocalPart(), defs );
125
126 TPart[] xParts = message.getPartArray();
127 for ( int i = 0; i < xParts.length; i++ )
128 {
129 Parameter p = new Parameter();
130 p.setName(xParts[i].getName());
131 SchemaType type = loader.findDocumentType(xParts[i].getElement());
132 if ( type == null )
133 {
134 System.out.println("Couldn't find type " + xParts[i].getElement().toString());
135 type = XmlAnySimpleType.type;
136 }
137 p.setType( type );
138
139 m.addRequestParameter(p);
140 }
141
142 XmlObject[] xHeaders = xOperation.getInput().selectPath(wsdlSoapNS + " $this//soap:header");
143 if ( xHeaders != null )
144 {
145 QName partQ = new QName("part");
146 QName messageQ = new QName("message");
147
148 for ( int i = 0; i < xHeaders.length; i++ )
149 {
150 String msgName = xHeaders[i].newCursor().getAttributeText(messageQ);
151 msgName = msgName.substring(msgName.indexOf(":")+1);
152
153 String partName = xHeaders[i].newCursor().getAttributeText(partQ);
154 TMessage hMessage = getMessage( msgName, defs );
155 TPart part = getPart(hMessage, partName);
156
157 Parameter p = new Parameter();
158 p.setName(part.getName() + "Header");
159 SchemaType type = loader.findDocumentType(part.getElement());
160 if ( type == null )
161 {
162 System.out.println("Couldn't find type " + xParts[i].getElement().toString());
163 type = XmlAnySimpleType.type;
164 }
165 p.setType( type );
166
167 m.addRequestHeader(p);
168 }
169 }
170
171 TParam output = abstractOp.getOutput();
172 message = getMessage( output.getMessage().getLocalPart(), defs );
173
174 xParts = message.getPartArray();
175 for ( int i = 0; i < xParts.length; i++ )
176 {
177 Parameter p = new Parameter();
178 p.setName(xParts[i].getName());
179 p.setType( loader.findDocumentType(xParts[i].getElement()) );
180
181 m.addResponseParameter(p);
182 }
183
184
185 return m;
186 }
187
188 private TPart getPart(TMessage message, String partName)
189 {
190 TPart[] parts = message.getPartArray();
191 for ( int i = 0; i < parts.length; i ++ )
192 {
193 if ( parts[i].getName().equals(partName) )
194 return parts[i];
195 }
196 return null;
197 }
198
199 private TMessage getMessage(String name, TDefinitions defs)
200 {
201 TMessage[] xMessages = defs.getMessageArray();
202 for ( int i = 0; i < xMessages.length; i ++ )
203 {
204 if ( xMessages[i].getName().equals(name) )
205 return xMessages[i];
206 }
207 return null;
208 }
209
210 private TOperation getAbstractOperation(String name, TPortType portType)
211 {
212 TOperation[] xOperations = portType.getOperationArray();
213
214 for ( int j = 0; j < xOperations.length; j++ )
215 {
216 if ( xOperations[j].getName().equals(name) )
217 return xOperations[j];
218 }
219 return null;
220 }
221
222 private TPortType getPortType(TDefinitions defs, QName portType)
223 {
224 TPortType[] portTypes = defs.getPortTypeArray();
225 for ( int i = 0; i < portTypes.length; i++ )
226 {
227 if ( portTypes[i].getName().equals(portType.getLocalPart()) )
228 return portTypes[i];
229 }
230
231 return null;
232 }
233
234 private TBinding getBinding(TDefinitions defs, QName binding)
235 {
236 TBinding[] bindings = defs.getBindingArray();
237 for ( int i = 0; i < bindings.length; i++ )
238 {
239 if ( bindings[i].getName().equals(binding.getLocalPart()) )
240 return bindings[i];
241 }
242
243 return null;
244 }
245
246 public class Service
247 {
248 private String name;
249 private String url;
250 private List methods;
251 private String encoding = "UTF-8";
252 private XmlObject xmlObject;
253 private QName binding;
254 private QName portType;
255 private boolean isRest;
256 private String soapVersion;
257
258 public Set getImports()
259 {
260 Set imports = new HashSet();
261
262 if ( methods != null )
263 {
264 for ( Iterator itr = methods.iterator(); itr.hasNext(); )
265 {
266 ServiceMethod m = (ServiceMethod) itr.next();
267
268 if ( m.getRequestParameters() != null )
269 {
270 for ( Iterator pitr = m.getRequestParameters().iterator(); pitr.hasNext(); )
271 {
272 Parameter p = (Parameter) pitr.next();
273 imports.add( p.getType() );
274 }
275 }
276
277 if ( m.getResponseParameters() != null )
278 {
279 for ( Iterator pitr = m.getResponseParameters().iterator(); pitr.hasNext(); )
280 {
281 Parameter p = (Parameter) pitr.next();
282 imports.add( p.getType() );
283 }
284 }
285
286 if ( m.getRequestHeaders() != null )
287 {
288 for ( Iterator pitr = m.getRequestHeaders().iterator(); pitr.hasNext(); )
289 {
290 Parameter p = (Parameter) pitr.next();
291 imports.add( p.getType() );
292 }
293 }
294 }
295 }
296 return imports;
297 }
298
299 public String getSoapVersion()
300 {
301 return soapVersion;
302 }
303 public void setSoapVersion(String soapVersion)
304 {
305 this.soapVersion = soapVersion;
306 }
307 public boolean isRest()
308 {
309 return isRest;
310 }
311 public void setRest(boolean isRest)
312 {
313 this.isRest = isRest;
314 }
315 public QName getPortType()
316 {
317 return portType;
318 }
319 public void setPortType(QName portType)
320 {
321 this.portType = portType;
322 }
323 public QName getBinding()
324 {
325 return binding;
326 }
327 public void setBinding(QName binding)
328 {
329 this.binding = binding;
330 }
331 public XmlObject getXmlObject()
332 {
333 return xmlObject;
334 }
335 public void setXmlObject(XmlObject xmlObject)
336 {
337 this.xmlObject = xmlObject;
338 }
339 public void addMethod( ServiceMethod m )
340 {
341 if ( methods == null )
342 methods = new ArrayList();
343
344 methods.add(m);
345 }
346
347 public String getEncoding()
348 {
349 return encoding;
350 }
351 public void setEncoding(String encoding)
352 {
353 this.encoding = encoding;
354 }
355 public List getMethods()
356 {
357 return methods;
358 }
359 public void setMethods(List methods)
360 {
361 this.methods = methods;
362 }
363 public String getName()
364 {
365 return name;
366 }
367 public void setName(String name)
368 {
369 this.name = name;
370 }
371 public String getUrl()
372 {
373 return url;
374 }
375 public void setUrl(String url)
376 {
377 this.url = url;
378 }
379 }
380
381 public class ServiceMethod
382 {
383 private String soapAction;
384 private String name;
385 private List requestParameters;
386 private List responseParameters;
387 private List requestHeaders;
388 private List responseHeaders;
389 private XmlObject xmlObject;
390
391 public void addRequestParameter( Parameter parameter )
392 {
393 if ( requestParameters == null )
394 requestParameters = new ArrayList();
395
396 requestParameters.add(parameter);
397 }
398 public void addResponseParameter( Parameter parameter )
399 {
400 if ( responseParameters == null )
401 responseParameters = new ArrayList();
402
403 responseParameters.add(parameter);
404 }
405
406 public void addRequestHeader( Parameter parameter )
407 {
408 if ( requestHeaders == null )
409 requestHeaders = new ArrayList();
410
411 requestHeaders.add(parameter);
412 }
413
414 public void addResponseHeader( Parameter parameter )
415 {
416 if ( responseHeaders == null )
417 responseHeaders = new ArrayList();
418
419 responseHeaders.add(parameter);
420 }
421
422 public List getRequestParameters()
423 {
424 return requestParameters;
425 }
426 public void setRequestParameters(List requestParameters)
427 {
428 this.requestParameters = requestParameters;
429 }
430 public List getResponseParameters()
431 {
432 return responseParameters;
433 }
434 public void setResponseParameters(List responseParameters)
435 {
436 this.responseParameters = responseParameters;
437 }
438 public List getRequestHeaders()
439 {
440 return requestHeaders;
441 }
442 public void setRequestHeaders(List requestHeaders)
443 {
444 this.requestHeaders = requestHeaders;
445 }
446 public List getResponseHeaders()
447 {
448 return responseHeaders;
449 }
450 public void setResponseHeaders(List responseHeaders)
451 {
452 this.responseHeaders = responseHeaders;
453 }
454 public String getSoapAction()
455 {
456 return soapAction;
457 }
458 public XmlObject getXmlObject()
459 {
460 return xmlObject;
461 }
462 public void setXmlObject(XmlObject xmlObject)
463 {
464 this.xmlObject = xmlObject;
465 }
466 public String getName()
467 {
468 return name;
469 }
470 public void setName(String name)
471 {
472 this.name = name;
473 }
474 public void setSoapAction(String soapAction)
475 {
476 this.soapAction = soapAction;
477 }
478 }
479
480 public class Parameter
481 {
482 private SchemaType type;
483 private String name;
484
485 public String getName()
486 {
487 return name;
488 }
489 public void setName(String name)
490 {
491 this.name = name;
492 }
493 public SchemaType getType()
494 {
495 return type;
496 }
497 public void setType(SchemaType type)
498 {
499 this.type = type;
500 }
501 }
502 }