| Home | Trees | Indices | Help |
|
|---|
|
|
1 """
2 Code to expose our services via SOAP and WSDL.
3 """
4
5 #c Copyright 2008-2019, the GAVO project
6 #c
7 #c This program is free software, covered by the GNU GPL. See the
8 #c COPYING file in the source distribution.
9
10
11 import ZSI
12 from ZSI import TC
13
14 from gavo import base
15 from gavo.base import valuemappers
16 from gavo.utils.stanxml import (Element, schemaURL, registerPrefix)
17
18
19 SOAPNamespace = 'http://schemas.xmlsoap.org/wsdl/soap/'
20 HTTPNamespace = 'http://schemas.xmlsoap.org/wsdl/http/'
21 MIMENamespace = 'http://schemas.xmlsoap.org/wsdl/mime/'
22 WSDLNamespace = 'http://schemas.xmlsoap.org/wsdl/'
23 XSDNamespace = "http://www.w3.org/2001/XMLSchema"
24
25 registerPrefix("soap", SOAPNamespace,
26 schemaURL("wsdlsoap-1.1.xsd"))
27 registerPrefix("http", HTTPNamespace,
28 schemaURL("wsdlhttp-1.1.xsd"))
29 registerPrefix("mime", MIMENamespace,
30 schemaURL("wsdlmime-1.1.xsd"))
31 registerPrefix("wsdl", WSDLNamespace,
32 schemaURL("wsdl-1.1.xsd"))
33 registerPrefix("xsd", XSDNamespace,
34 schemaURL("XMLSchema.xsd"))
35
36
37
39 """is a container for elements from the wsdl 1.1 schema.
40 """
42 _prefix = "wsdl"
43
47
51
53 _additionalPrefixes = frozenset(["xsi"])
54 _a_name = None
55 _a_targetNamespace = None
56 _a_xmlns_tns = None
57 _name_a_xmlns_tns = "xmlns:tns"
58 _a_xmlns_xsd = XSDNamespace
59 _name_a_xmlns_xsd = "xmlns:xsd"
60
62
64 _a_name = None
65
70
72 _mayBeEmpty = True
73
75 _a_name = None
76
80
85
90
95
97 _a_name = None
98
100 _a_name = None
101
103
104
107 _prefix = "soap"
108
110 _mayBeEmpty = True
111 _a_style = "rpc"
112 _a_transport = "http://schemas.xmlsoap.org/soap/http"
113
115 _mayBeEmpty = True
116 _a_use = "encoded"
117 _a_namespace = None
118 _a_encodingStyle = "http://schemas.xmlsoap.org/soap/encoding"
119
124
128
129
131 """is a container for elements from XML schema.
132 """
136
140
145
147 _a_name = None
148
150
154
156 _a_name = None
157
158
160 """returns stanxml definitions for the (SOAP) type of service.
161
162 Only "atomic" input parameters are supported so far, so we can
163 skip those. The output type is always called outList and contains
164 of outRec elements.
165 """
166 return WSDL.types[
167 XSD.schema(targetNamespace=base.getMetaText(service, "identifier"))[
168 XSD.element(name="outRec")[
169 XSD.complexType[
170 XSD.all[[
171 XSD.element(name=f.name, type=base.sqltypeToXSD(
172 f.type))[
173 WSDL.documentation[f.description],
174 WSDL.documentation[f.unit]]
175 for f in service.getCurOutputFields(queryMeta)]]]],
176 XSD.element(name="outList")[
177 XSD.simpleType[
178 XSD.list(itemType="outRec")]]]]
179
180
182 """returns stanxml definitions for the SOAP messages exchanged when
183 using the service.
184
185 Basically, the input message (called srvInput) consists of some
186 combination of the service's input fields, the output message
187 (called srvOutput) is just an outArr.
188 """
189 return [
190 WSDL.message(name="srvInput")[[
191 WSDL.part(name=f.name, type="xsd:"+base.sqltypeToXSD(
192 f.type))[
193 WSDL.documentation[f.description],
194 WSDL.documentation[f.unit]]
195 for f in service.getInputKeysFor("soap")]],
196 WSDL.message(name="srvOutput")[
197 WSDL.part(name="srvOutput", type="tns:outList")]]
198
199
201 """returns stanxml for a port type named serviceSOAP.
202 """
203 parameterOrder = " ".join([f.name
204 for f in service.getInputKeysFor("soap")])
205 return WSDL.portType(name="serviceSOAP")[
206 WSDL.operation(name="useService", parameterOrder=parameterOrder) [
207 WSDL.input(name="inPars", message="tns:srvInput"),
208 WSDL.output(name="outPars", message="tns:srvOutput"),
209 # XXX TODO: Define fault
210 ]]
211
212
214 """returns stanxml for a SOAP binding of service.
215 """
216 tns = base.getMetaText(service, "identifier")
217 return WSDL.binding(name="soapBinding", type="tns:serviceSOAP")[
218 SOAP.binding,
219 WSDL.operation(name="useService")[
220 SOAP.operation(soapAction="", name="useService"),
221 WSDL.input(name="inPars")[
222 SOAP.body(use="encoded", namespace=tns)],
223 WSDL.output(name="inPars")[
224 SOAP.body(use="encoded", namespace=tns)],
225 ]
226 ]
227
228
230 """returns stanxml for a WSDL service definition of the SOAP interface
231 to service.
232 """
233 shortName = base.getMetaText(service, "shortName")
234 return WSDL.service(name=shortName)[
235 WSDL.port(name="soap_%s"%shortName, binding="tns:soapBinding")[
236 SOAP.address(location=service.getURL("soap")),
237 ]
238 ]
239
240
242 """returns an stanxml definitions element describing service.
243
244 The definitions element also introduces a namespace named after the
245 ivoa id of the service, accessible through the tns prefix.
246 """
247 serviceId = base.getMetaText(service, "identifier")
248 return WSDL.definitions(targetNamespace=serviceId,
249 xmlns_tns=serviceId,
250 name="%s_wsdl"%base.getMetaText(service, "shortName").replace(" ", "_"))[
251 WSDL.import_,
252 makeTypesForService(service, queryMeta),
253 makeMessagesForService(service),
254 makePortTypeForService(service),
255 makeSOAPBindingForService(service),
256 makeSOAPServiceForService(service),
257 ]
258
259
261 """is a quick and partial converter from SQL types to ZSI's type codes.
262 """
263 typeSystem = "ZSITypeCodes"
264 simpleMap = {
265 "smallint": TC.Integer,
266 "integer": TC.Integer,
267 "int": TC.Integer,
268 "bigint": TC.Integer,
269 "real": TC.FPfloat,
270 "float": TC.FPfloat,
271 "boolean": ("boolean", "1"),
272 "double precision": TC.FPdouble,
273 "double": TC.FPdouble,
274 "text": TC.String,
275 "char": TC.String,
276 "date": TC.gDate,
277 "timestamp": TC.gDateTime,
278 "time": TC.gTime,
279 "raw": TC.String,
280 }
281
285
286 sqltypeToTC = ToTcConverter().convert
287
288
289 # rather than fooling around with ZSI.SoapWriter's serialization, I use
290 # the machinery used for VOTables and HTML to serialize weird values.
291 # It's in place anyway.
292
293 _wsdlMFRegistry = valuemappers.ValueMapperFactoryRegistry()
294 _registerMF = _wsdlMFRegistry.registerFactory
295
296
298 """returns mapper for datetime objects to python time tuples.
299 """
300 if colProps["dbtype"] in ("date", "datetime"):
301 def mapper(val):
302 return val.timetuple()
303 return mapper
304 _registerMF(datetimeMapperFactory)
305
307 """returns a SOAP serialization of the DataSet data's primary table.
308 """
309 table = data.getPrimaryTable()
310 tns = base.getMetaText(service, "identifier")
311 class Row(TC.Struct):
312 def __init__(self):
313 TC.Struct.__init__(self, None, [
314 sqltypeToTC(f.type)(pname=(tns, f.name))
315 for f in table.tableDef],
316 pname=(tns, "outRow"))
317
318 class Table(list):
319 typecode = TC.Array((tns, 'outRow'), Row(),
320 pname=(tns, 'outList'))
321
322 mapped = Table(
323 base.SerManager(table, mfRegistry=_wsdlMFRegistry).getMappedValues())
324 sw = ZSI.SoapWriter(nsdict={"tns": tns})
325 sw.serialize(mapped).close()
326 return str(sw)
327
328
330 """returns an XML-clean version of obj's unicode representation.
331
332 I'd expect ZSI to worry about this, but clearly they don't.
333 """
334 return unicode(obj
335 ).replace("&", "&").replace("<", "<").replace(">", ">")
336
337
339 if isinstance(exc, base.ValidationError):
340 val = ZSI.Fault(ZSI.Fault.Client, unicodeXML(exc))
341 else:
342 val = ZSI.Fault(ZSI.Fault.Server, unicodeXML(exc))
343 return val.AsSOAP(
344 nsdict={"tns": base.getMetaText(service, "identifier")})
345
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Thu May 2 07:29:09 2019 | http://epydoc.sourceforge.net |