(no commit message)
[sfa.git] / wsdl / gw2wsdl.py
1 #!/usr/bin/python
2 #
3 # Sapan Bhatia <sapanb@cs.princeton.edu>
4 #
5 # Generates a WSDL for geniwrapper
6 # Current limitations:
7 # - Invalid for the following reasons 
8 # - The types are python types, not WSDL types
9
10 import os, sys
11 import time
12 import pdb
13 import xml.dom.minidom
14 import xml.dom.ext
15 import globals
16 import apistub
17 from types import *
18
19 from geni.util.auth import Auth
20 from geni.util.parameter import Parameter,Mixed
21
22 complex_types = {}
23 services = {}
24
25 num_types = 0
26
27 class SoapError(Exception):
28      def __init__(self, value):
29          self.value = value
30      def __str__(self):
31          return repr(self.value)
32 try:
33     set
34 except NameError:
35     from sets import Set
36     set = Set
37
38
39 def name_vector_type(acc,arg):
40     global complex_types
41     name = name_complex_type(arg)
42     complex_types[arg]=name
43     if (type(arg)==list):
44         acc.append(name)
45     else:
46         python_is_f_braindead = name_complex_type(acc)
47         acc = [python_is_f_braindead,name]
48     return acc
49
50 def name_complex_type(arg):
51     global num_types
52     global types
53     types_section = types.firstChild.firstChild
54     if (isinstance(arg, Mixed)):
55         inner_types = reduce(name_vector_type, arg)
56         if (inner_types[-1]=="None"):
57             inner_types=inner_types[:-1]
58             min_args = 0
59         else:
60             min_args = 1
61     
62         num_types=num_types+1
63         type_name = "Type%d"%num_types
64         complex_type = types_section.appendChild(types.createElement("wsdl:complexType"))
65         complex_type.setAttribute("name", type_name)
66
67         choice = complex_type.appendChild(types.createElement("xsd:choice"))
68         for i in inner_types:
69             element = choice.appendChild(types.createElement("element"))
70             element.setAttribute("name", "Foobar")
71             element.setAttribute("type", "tns:%s"%i)
72             element.setAttribute("minOccurs","%d"%min_args)
73         return type_name
74     elif (isinstance(arg, Parameter)):
75         return (name_simple_type(arg.type))
76     elif type(arg) == ListType or type(arg) == TupleType:
77         return "sequence"
78     elif type(arg) == DictType or arg == DictType:
79         return "dict"
80     else:
81         return (name_simple_type(arg))
82
83 def name_simple_type(arg_type):
84     if arg_type == None:
85         return "none"
86     if arg_type == DictType:
87         return "dict"
88     elif arg_type == IntType or arg_type == LongType:
89         return "int"
90     elif arg_type == bool:
91         return "boolean"
92     elif arg_type == FloatType:
93         return "double"
94     elif arg_type in StringTypes:
95         return "string"
96     else:
97        #pdb.set_trace()
98         raise SoapError, "Cannot handle %s objects" % arg_type
99
100 def param_type(arg):
101     return (name_complex_type(arg))
102
103 def add_wsdl_ports_and_bindings (wsdl):
104     for method in apistub.methods:
105         # Skip system. methods
106         if "system." in method:
107             continue
108
109         function = apistub.callable(method) # Commented documentation
110         #lines = ["// " + line.strip() for line in function.__doc__.strip().split("\n")]
111         #print "\n".join(lines)
112         #print
113
114         
115         in_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:message"))
116         in_el.setAttribute("name", method + "_in")
117
118         for service_name in function.interfaces:
119             if (services.has_key(service_name)):
120                 if (not method in services[service_name]):
121                     services[service_name].append(method)
122             else:
123                 services[service_name]=[method]
124
125         # Arguments
126
127         if (function.accepts):
128             (min_args, max_args, defaults) = function.args()
129             for (argname,argtype) in zip(max_args,function.accepts):
130                 arg_part = in_el.appendChild(wsdl.createElement("wsdl:part"))
131                 arg_part.setAttribute("name", argname)
132                 arg_part.setAttribute("type", param_type(argtype))
133                 
134         # Return type            
135         return_type = function.returns
136         out_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:message"))
137         out_el.setAttribute("name", method + "_out")
138         ret_part = out_el.appendChild(wsdl.createElement("wsdl:part"))
139         ret_part.setAttribute("name", "returnvalue")
140         ret_part.setAttribute("type", param_type(return_type))
141
142         # Port connecting arguments with return type
143
144         port_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:portType"))
145         port_el.setAttribute("name", method + "_port")
146         
147         op_el = port_el.appendChild(wsdl.createElement("wsdl:operation"))
148         op_el.setAttribute("name", method)
149         op_el.appendChild(wsdl.createElement("wsdl:input")).setAttribute("message","tns:" + method + "_in")
150         op_el.appendChild(wsdl.createElement("wsdl:output")).setAttribute("message","tns:" + method + "_out")
151
152         # Bindings
153
154         bind_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:binding"))
155         bind_el.setAttribute("name", method + "_binding")
156         bind_el.setAttribute("type", "tns:" + method + "_port")
157         
158         soap_bind = bind_el.appendChild(wsdl.createElement("soap:binding"))
159         soap_bind.setAttribute("style", "rpc")
160         soap_bind.setAttribute("transport","http://schemas.xmlsoap.org/soap/http")
161
162         
163         wsdl_op = bind_el.appendChild(wsdl.createElement("wsdl:operation"))
164         wsdl_op.setAttribute("name", method)
165         wsdl_op.appendChild(wsdl.createElement("soap:operation")).setAttribute("soapAction",
166                 "urn:" + method)
167
168         
169         wsdl_input = wsdl_op.appendChild(wsdl.createElement("wsdl:input"))
170         input_soap_body = wsdl_input.appendChild(wsdl.createElement("soap:body"))
171         input_soap_body.setAttribute("use", "encoded")
172         input_soap_body.setAttribute("namespace", "urn:" + method)
173         input_soap_body.setAttribute("encodingStyle","http://schemas.xmlsoap.org/soap/encoding/")
174
175         
176         wsdl_output = wsdl_op.appendChild(wsdl.createElement("wsdl:output"))
177         output_soap_body = wsdl_output.appendChild(wsdl.createElement("soap:body"))
178         output_soap_body.setAttribute("use", "encoded")
179         output_soap_body.setAttribute("namespace", "urn:" + method)
180         output_soap_body.setAttribute("encodingStyle","http://schemas.xmlsoap.org/soap/encoding/")
181         
182
183 def add_wsdl_service(wsdl):
184     for service in services.keys():
185         service_el = wsdl.firstChild.appendChild(wsdl.createElement("wsdl:service"))
186         service_el.setAttribute("name", service)
187
188         for method in services[service]:
189             name=method
190             servport_el = service_el.appendChild(wsdl.createElement("wsdl:port"))
191             servport_el.setAttribute("name", name + "_port")
192             servport_el.setAttribute("binding", "tns:" + name + "_binding")
193
194             soapaddress = servport_el.appendChild(wsdl.createElement("soap:address"))
195             soapaddress.setAttribute("location", "%s/%s" % (globals.plc_ns,service))
196
197
198 def get_wsdl_definitions():
199     wsdl_text_header = """
200         <wsdl:definitions
201         name="auto_generated"
202         targetNamespace="%s"
203         xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
204         xmlns:tns="xmlns:%s"
205         xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
206         xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"/>
207         """ % (globals.plc_ns,globals.plc_ns)
208         
209     wsdl = xml.dom.minidom.parseString(wsdl_text_header)
210     
211     return wsdl
212     
213
214 types = get_wsdl_definitions()
215 types.firstChild.appendChild(types.createElement("wsdl:types"))
216 wsdl = get_wsdl_definitions()
217 add_wsdl_ports_and_bindings(wsdl)
218 wsdl_types = wsdl.importNode(types.firstChild.firstChild, True)
219 wsdl.firstChild.appendChild(wsdl_types)
220 add_wsdl_service(wsdl)
221
222 xml.dom.ext.PrettyPrint(wsdl)