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 TParam output = abstractOp.getOutput();
143 message = getMessage( output.getMessage().getLocalPart(), defs );
144
145 xParts = message.getPartArray();
146 for ( int i = 0; i < xParts.length; i++ )
147 {
148 Parameter p = new Parameter();
149 p.setName(xParts[i].getName());
150 p.setType( loader.findDocumentType(xParts[i].getElement()) );
151
152 m.addResponseParameter(p);
153 }
154
155
156 return m;
157 }
158
159 private TMessage getMessage(String name, TDefinitions defs)
160 {
161 TMessage[] xMessages = defs.getMessageArray();
162 for ( int i = 0; i < xMessages.length; i ++ )
163 {
164 if ( xMessages[i].getName().equals(name) )
165 return xMessages[i];
166 }
167 return null;
168 }
169
170 private TOperation getAbstractOperation(String name, TPortType portType)
171 {
172 TOperation[] xOperations = portType.getOperationArray();
173
174 for ( int j = 0; j < xOperations.length; j++ )
175 {
176 if ( xOperations[j].getName().equals(name) )
177 return xOperations[j];
178 }
179 return null;
180 }
181
182 private TPortType getPortType(TDefinitions defs, QName portType)
183 {
184 TPortType[] portTypes = defs.getPortTypeArray();
185 for ( int i = 0; i < portTypes.length; i++ )
186 {
187 if ( portTypes[i].getName().equals(portType.getLocalPart()) )
188 return portTypes[i];
189 }
190
191 return null;
192 }
193
194 private TBinding getBinding(TDefinitions defs, QName binding)
195 {
196 TBinding[] bindings = defs.getBindingArray();
197 for ( int i = 0; i < bindings.length; i++ )
198 {
199 if ( bindings[i].getName().equals(binding.getLocalPart()) )
200 return bindings[i];
201 }
202
203 return null;
204 }
205
206 public class Service
207 {
208 private String name;
209 private String url;
210 private List methods;
211 private String encoding = "UTF-8";
212 private XmlObject xmlObject;
213 private QName binding;
214 private QName portType;
215 private boolean isRest;
216 private String soapVersion;
217
218 public Set getImports()
219 {
220 Set imports = new HashSet();
221
222 if ( methods != null )
223 {
224 for ( Iterator itr = methods.iterator(); itr.hasNext(); )
225 {
226 ServiceMethod m = (ServiceMethod) itr.next();
227
228 if ( m.getRequestParameters() != null )
229 {
230 for ( Iterator pitr = m.getRequestParameters().iterator(); pitr.hasNext(); )
231 {
232 Parameter p = (Parameter) pitr.next();
233 imports.add( p.getType() );
234 }
235 }
236
237 if ( m.getResponseParameters() != null )
238 {
239 for ( Iterator pitr = m.getResponseParameters().iterator(); pitr.hasNext(); )
240 {
241 Parameter p = (Parameter) pitr.next();
242 imports.add( p.getType() );
243 }
244 }
245 }
246 }
247 return imports;
248 }
249
250 public String getSoapVersion()
251 {
252 return soapVersion;
253 }
254 public void setSoapVersion(String soapVersion)
255 {
256 this.soapVersion = soapVersion;
257 }
258 public boolean isRest()
259 {
260 return isRest;
261 }
262 public void setRest(boolean isRest)
263 {
264 this.isRest = isRest;
265 }
266 public QName getPortType()
267 {
268 return portType;
269 }
270 public void setPortType(QName portType)
271 {
272 this.portType = portType;
273 }
274 public QName getBinding()
275 {
276 return binding;
277 }
278 public void setBinding(QName binding)
279 {
280 this.binding = binding;
281 }
282 public XmlObject getXmlObject()
283 {
284 return xmlObject;
285 }
286 public void setXmlObject(XmlObject xmlObject)
287 {
288 this.xmlObject = xmlObject;
289 }
290 public void addMethod( ServiceMethod m )
291 {
292 if ( methods == null )
293 methods = new ArrayList();
294
295 methods.add(m);
296 }
297
298 public String getEncoding()
299 {
300 return encoding;
301 }
302 public void setEncoding(String encoding)
303 {
304 this.encoding = encoding;
305 }
306 public List getMethods()
307 {
308 return methods;
309 }
310 public void setMethods(List methods)
311 {
312 this.methods = methods;
313 }
314 public String getName()
315 {
316 return name;
317 }
318 public void setName(String name)
319 {
320 this.name = name;
321 }
322 public String getUrl()
323 {
324 return url;
325 }
326 public void setUrl(String url)
327 {
328 this.url = url;
329 }
330 }
331
332 public class ServiceMethod
333 {
334 private String soapAction;
335 private String name;
336 private List requestParameters;
337 private List responseParameters;
338 private XmlObject xmlObject;
339
340 public void addRequestParameter( Parameter parameter )
341 {
342 if ( requestParameters == null )
343 requestParameters = new ArrayList();
344
345 requestParameters.add(parameter);
346 }
347 public void addResponseParameter( Parameter parameter )
348 {
349 if ( responseParameters == null )
350 responseParameters = new ArrayList();
351
352 responseParameters.add(parameter);
353 }
354 public List getRequestParameters()
355 {
356 return requestParameters;
357 }
358 public void setRequestParameters(List requestParameters)
359 {
360 this.requestParameters = requestParameters;
361 }
362 public List getResponseParameters()
363 {
364 return responseParameters;
365 }
366 public void setResponseParameters(List responseParameters)
367 {
368 this.responseParameters = responseParameters;
369 }
370 public String getSoapAction()
371 {
372 return soapAction;
373 }
374 public XmlObject getXmlObject()
375 {
376 return xmlObject;
377 }
378 public void setXmlObject(XmlObject xmlObject)
379 {
380 this.xmlObject = xmlObject;
381 }
382 public String getName()
383 {
384 return name;
385 }
386 public void setName(String name)
387 {
388 this.name = name;
389 }
390 public void setSoapAction(String soapAction)
391 {
392 this.soapAction = soapAction;
393 }
394 }
395
396 public class Parameter
397 {
398 private SchemaType type;
399 private String name;
400
401 public String getName()
402 {
403 return name;
404 }
405 public void setName(String name)
406 {
407 this.name = name;
408 }
409 public SchemaType getType()
410 {
411 return type;
412 }
413 public void setType(SchemaType type)
414 {
415 this.type = type;
416 }
417 }
418 }