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