Qore WSDL Module Reference  0.3.4
 All Classes Namespaces Functions Variables Pages
WSDL.qm.dox.h
1 // -*- mode: c++; indent-tabs-mode: nil -*-
3 
4 /* WSDL.qm Copyright 2012 David Nichols
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23 */
24 
25 // make sure we have the required qore version
26 
27 // requires XML functionality
28 
29 // need mime definitions
30 
31 
32 
33 /* Version History
34  * 2012-05-31 v0.3.4: David Nichols <david@qore.org>: updated to a user module
35  * v0.3.3: added initial support for the anyAttribute element of complexType
36  added initial support for SOAP header processing
37  added initial support for multiple portType and bindings in a WSDL
38 
39  * v0.3.2: fixed bugs de/serializing negative values for "int" and "short"
40  * v0.3.1: improved XSD imports and namespace handling
41 
42  * v0.3.0: implemented WSDLLib class of helper functions
43  implemented support for xsd import statements in WSDLs
44 
45  * v0.2.0: use parseXMLAsData() instead of parseXML()
46  implemented initial simpleType support
47  fixed xsd:date serialization and deserialization
48 
49 
50  WSDL classes
51  provides some minimal WSDL and XSD support for SOAP messaging used by the SoapClient class and the SoapHandler
52 
53  not complete, needs namespace verification, improved XSD support, element groups, etc
54 */
55 
74 
75 namespace WSDL {
77  const version = "0.3.4";
78 
79  const XET_ALL = "ALL";
80  const XET_CHOICE = "CHOICE";
81  const XET_SEQUENCE = "SEQUENCE";
82 
84  const SOAP_11_ENV = "http://schemas.xmlsoap.org/soap/envelope/";
86  const SOAP_12_ENV = "http://www.w3.org/2003/05/soap-envelope";
87 
89  const SOAP_12_NS = "http://schemas.xmlsoap.org/wsdl/soap12/";
90 
92  const XSD_NS = "http://www.w3.org/2001/XMLSchema";
94  const XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";
95 
97  const HTTP_NS = "http://schemas.xmlsoap.org/wsdl/http/";
99  const MIME_NS = "http://schemas.xmlsoap.org/wsdl/mime/";
100 
102  const ENVELOPE_11_NS =
103  ( "soapenv:Envelope" :
104  ( "^attributes^" :
105  ( "xmlns:soapenv" : SOAP_11_ENV,
106  "xmlns:xsd" : XSD_NS,
107  "xmlns:xsi" : XSI_NS ) ) );
108 
110  const ENVELOPE_12_NS =
111  ( "soapenv:Envelope" :
112  ( "^attributes^" :
113  ( "xmlns:soapenv" : SOAP_12_ENV,
114  "xmlns:xsd" : XSD_NS,
115  "xmlns:xsi" : XSI_NS ) ) );
116 
118  const SOAP_ENCODING = "http://schemas.xmlsoap.org/soap/encoding/";
119 
121  const any_type_map =
122  ( Type::String : "string",
123  Type::Int : "long",
124  Type::Boolean : "boolean",
125  Type::Date : "dateTime",
126  Type::Float : "decimal",
127  Type::NothingType : "string",
128  Type::NullType : "string",
129  Type::Binary : "base64Binary" );
130 
131  // error codes
132  const SOAP_SERIALIZATION_ERROR = "SOAP-SERIALIZATION-ERROR";
133  const SOAP_DESERIALIZATION_ERROR = "SOAP-DESERIALIZATION-ERROR";
134  const WSDL_ERROR = "WSDL-ERROR";
135 
137  const SOAP_TRANSPORT_HTTP = "http://schemas.xmlsoap.org/soap/http";
138 
140  const RANGE_SHORT = (-32768, 32767);
141 
143  const RANGE_INT = (-2147483648, 2147483647);
144 };
145 
148 
149 public:
151  const SoapMimeTypes = (MimeTypeSoapXml, MimeTypeXml, MimeTypeXmlApp);
152 
154 
155  static string getFile(string $fn) {
156  my File $f();
157  $f.open2($fn);
158  return $f.read(-1);
159  }
160 
161  #! retrieves a file from a URL with HTTP and returns the file's contents as a string
162 
163  static string getHTTP(string url, any path, any hc, any headers);
164 
166 
167  static binary getFTP(string $url, string $path) {
168  my string $file = basename($path);
169  if (!exists $file)
170  throw "WSDL-LIB-ERROR", sprintf("missing file name in URL %n", $url);
171 
172  my FtpClient $f($url);
173  $f.connect();
174 
175  my string $dir = dirname($path);
176  if (exists $dir)
177  $f.cwd($dir);
178 
179  return $f.getAsBinary($file);
180  }
181 
182  #! retrieves a file from a URL
183  static any getFileFromURL(string $url, string $def_protocol, any $http_client, any $http_headers) {
184  my hash $u = parse_url($url);
185 
186  if (!exists $u.protocol)
187  $u.protocol = exists $def_protocol ? $def_protocol : "file";
188 
189  switch ($u.protocol) {
190  case "file":
191  return WSDLLib::getFile($u.host + $u.path);
192 
193  case /^http(s)?$/:
194  return WSDLLib::getHTTP($url, $u.path, $http_client, $http_headers);
195 
196  case /^ftp(s)?$/:
197  return WSDLLib::getFTP($url, $u.path);
198 
199  default:
200  throw "WSDL-LIB-ERROR", sprintf("do not know how to retrieve data with protocol %n given in URL %n", $u.protocol, $url);
201  }
202  }
203 
204  #! returns the argument
205  static WebService getWSDL(WebService $wsdl) {
206  return $wsdl;
207  }
208 
209  #! returns a WSDL string form a file name, optional HTTPClient object and optional header hash
210  static string getWSDL(string $wsdl, *HTTPClient $http_client, *hash $http_headers) {
211  if (strlen($wsdl) > 256 && $wsdl !~ /^\w+:\/\/.*$/)
212  return $wsdl;
213  return WSDLLib::getFileFromURL($wsdl, "file", $http_client, $http_headers);
214  }
215 
216  #! takes a hash representation of a SOAP message and parses it to a Qore data structure; handles multipart messages, checks the content-type, and handles hrefs in the message
217  static hash parseSOAPMessage(hash $msg) {
218  if (exists $msg."_qore_multipart") {
219  if ($msg."_qore_multipart" != "related")
220  throw "SOAP-MESSAGE-ERROR", sprintf("don't understand multipart/%s messages, expected multipart/related", $msg."_qore_multipart");
221 
222  my any $bdry = $msg."_qore_multipart_boundary";
223  if (!strlen($bdry))
224  throw "SOAP-MESSAGE-ERROR", sprintf("multipart message received without multipart boundary; headers=%n", $msg - "body");
225 
226  my hash $mpmsg;
227  my list $l = split("\r\n--" + $bdry, $msg.body);
228 
229  #printf("l=%N\n", $l);
230  #my File $f(); $f.open2("t.bin", O_CREAT|O_WRONLY|O_TRUNC); $f.write(binary($l[3])); exit();
231  #my File $f(); $f.open2("t.bin", O_CREAT|O_WRONLY|O_TRUNC); $f.write(binary($msg.body)); exit();
232 
233  for (my int $i = 1; $i < (elements $l - 1); ++$i) {
234  my string $m = $l[$i];
235 
236  my int $ie = index($m, "\r\n\r\n");
237  if ($ie == -1) {
238  throw "SOAP-MESSAGE-ERROR", sprintf("part %d has no headers: %n", $i, $m);
239  }
240  my hash $hh;
241  foreach my string $hl in (split("\r\n", substr($m, 2, $ie))) {
242  trim $hl;
243  my (string $hi, any $ignore, string $ha) = $hl =~ x/^(.*):([ \t])*(.*)$/;
244  $hi = tolower($hi);
245  #printf("hl=%n hi=%n ha=%n\n", $hl, $hi, $ha);exit();
246  $hh.$hi = $ha;
247  }
248  if (!exists $hh."content-id")
249  throw "SOAP-MESSAGE-ERROR", sprintf("expecting part header Content-ID in part %d; headers: %n", $i, $hh);
250 
251  my any $b;
252  if ($hh."content-transfer-encoding" == "binary") {
253  # unfortunately we have to do some tricks to get the binary data out here
254  # FIXME: tricks probably not necessary with qore 0.8.1+
255  $m = force_encoding($m, "ascii");
256  # recalculate byte offset
257  $ie = index($m, "\r\n\r\n");
258  #printf("ie=%d m=%d\n", $ie, strlen($m));exit();
259  $b = binary(substr($m, $ie + 4));
260 
261  #my File $f(); $f.open2("t.bin", O_CREAT|O_WRONLY|O_TRUNC); $f.write($b); exit();
262  }
263  else {
264  $b = substr($m, $ie + 4);
265 
266  if ($hh."content-type" =~ /charset=/) {
267  my string $c = ($hh."content-type" =~ x/charset=([^;]+)/)[0];
268  $b = force_encoding($b, $c);
269  }
270  }
271 
272  if ($hh."content-id" !~ /^\<.*\>$/)
273  throw "SOAP-MESSAGE-ERROR", sprintf("expected part ID to have the following format: <id>, instead got %s", $hh."content-id");
274 
275  my hash $p = ( "hdr" : $hh,
276  "body" : $b );
277 
278  if ((!exists $msg."_qore_multipart_start" && $i == 1)
279  @htmlonly <style><!-- td.qore { background-color: #5b9409; color: white; } --></style> @endhtmlonly
280  <table>
281  <tr>
282  <td></td>
283  <td>(exists $msg."_qore_multipart_start" && $msg."_qore_multipart_start" == $hh."content-id")) {</td>
284  </tr>
285  </table>
286  $mpmsg.body = $p;
287  }
288  else {
289  my string $id = substr($hh."content-id", 1, -1);
290  $mpmsg.part.$id = $p;
291  }
292  }
293  # check content-type
294  WSDLLib::checkSOAPContentType($mpmsg.body.hdr."content-type");
295 
296  #printf("part %d hh=%N\nbody=%s (%d)\n", $i, $hh, type($b), elements($b)); #exit();
297  my hash $xmldata = parseXMLAsData($mpmsg.body.body);
298 
299  # parse entire data structure to find "href"s or href attributes
300  WSDLLib::substHref(\$xmldata, $mpmsg.part);
301  return $xmldata;
302  }
303 
304  WSDLLib::checkSOAPContentType($msg."content-type");
305 
306  return parseXMLAsData($msg.body);
307  }
308 
309  private static checkSOAPContentType(string $ct) {
310  foreach my string $sct in (SoapMimeTypes) {
311  if (bindex($ct, $sct) != -1)
312  return;
313  }
314 
315  throw "SOAP-MESSAGE-ERROR", sprintf("don't know how to handle content-type %n (expecting one of: %y)", $ct, SoapMimeTypes);
316  }
317 
318  private static processHref(reference $xmldata, string $hr, hash $parts) {
319  if ($hr !~ /^cid:/)
320  throw "SOAP-MESSAGE-ERROR", sprintf("messages references non-local part %n; cannot handle non-local parts", $hr);
321  $hr = substr($hr, 4);
322  if (!exists $parts.$hr)
323  throw "SOAP-MESSAGE-ERROR", sprintf("message references non-existent part %n", $hr);
324  $xmldata = $parts.$hr.body;
325  }
326 
327  private static substHref(reference $xmldata, hash $parts) {
328  foreach my string $k in (keys $xmldata) {
329  if (exists $xmldata.$k."^attributes^".href)
330  WSDLLib::processHref(\$xmldata.$k, $xmldata.$k."^attributes^".href, $parts);
331  else if (exists $xmldata.$k.href)
332  WSDLLib::processHref(\$xmldata.$k, $xmldata.$k.href, $parts);
333  else if ($xmldata.$k.typeCode() == NT_LIST) {
334  foreach my any $e in (\$xmldata.$k)
335  WSDLLib::substHref(\$e, $parts);
336  }
337  else if ($xmldata.$k.typeCode() == NT_HASH)
338  WSDLLib::substHref(\$xmldata.$k, $parts);
339  }
340  }
341 }
342 
343 # abstract class providing helper methods to subclasses
344 public class WSDL::XSDBase {
345  static private hash doType(string $t) {
346  #printf("DEBUG: XSDBase::doType(%n, %n)\n", $t, $nsinfo);
347  my (*string $ns, *string $type) = $t =~ x/(\w+):(\w+)/;
348  return !exists $type ? ("val": $t) : ("ns": $ns, "val": $type);
349  }
350 
351  static private any doType(string $t, hash $nsinfo) {
352  #printf("DEBUG: XSDBase::doType(%n, %n)\n", $t, $nsinfo);
353  my (*string $ns, *string $type) = $t =~ x/(\w+):(\w+)/;
354  if (!exists $type)
355  return ( "val" : $t );
356 
357  # if this is in the XML Schema namespace, then it's a base type
358  if ($nsinfo.xml_schema.$ns)
359  return new XSDBaseType($type);
360 
361  return ( "ns" : $ns,
362  "val" : $type );
363  }
364 
365  static removeNS(reference $h) {
366  foreach my string $k in (keys $h) {
367  my (*string $ns, *string $name) = $k =~ x/(\w+):(\w+)/;
368  if (exists $ns) {
369  if ($h.$k.typeCode() == NT_HASH)
370  $h.$k.ns = $ns;
371  $h.$name = $h.$k;
372  $h -= $k;
373  }
374  }
375  }
376 
377  static removeNS2(reference $h) {
378  foreach my string $k in (keys $h) {
379  my (*string $ns, *string $name) = $k =~ x/(\w+):(\w+)/;
380  if (exists $ns) {
381  if ($h.$k.typeCode() == NT_HASH)
382  $h.$k.".ns" = $ns;
383  $h.$name = $h.$k;
384  $h -= $k;
385  }
386  }
387  }
388 }
389 
390 # abstract type common to all XSD classes
391 public class WSDL::XSDData inherits XSDBase {
392  any getValue(any $mrh, any $val) {
393  if (exists $val."^attributes^".href) {
394  my string $href = substr($val."^attributes^".href, 1);
395 
396  if (!exists $mrh.$href)
397  throw "INVALID-REFERENCE", sprintf("multiRef id=%n does not exist", $href);
398 
399  return $mrh.$href;
400  }
401  return $val;
402  }
403 }
404 
405 # abstract type common to all XSD classes with a "name" attribute
406 public class WSDL::XSDNamedData inherits XSDData {
407  public {
408  *string $.name;
409  *string $.ns;
410  }
411  constructor(reference $e) {
412  WSDL::XSDBase::removeNS(\$e);
413 
414  $.name = $e."^attributes^".name;
415  }
416 
417  string getName() {
418  return exists $.name ? $.name : "<unnamed type>";
419  }
420 
421  any getNS() {
422  return $.ns;
423  }
424 }
425 
426 # class for XSD base types
427 public class WSDL::XSDBaseType inherits XSDData {
428  public {
429  string $.type;
430  string $.nstype;
431  }
432  constructor(string $t) {
433  $.type = $t;
434  $.nstype = "xsd:" + $t;
435  }
436 
437  any serialize(any $val, *softbool $omit_type, *softbool $omit_ns) {
438  my (any $type, string $nstype);
439  # set type according to Qore type if xsd type is anyType
440  if ($.type == "anyType") {
441  # we have to specify the type in this case
442  $omit_type = False;
443  $type = any_type_map{type($val)};
444  $nstype = "xsd:" + $type;
445  if (!exists $type)
446  throw SOAP_SERIALIZATION_ERROR, sprintf("cannot serialize xsd type anyType from Qore type %n", type($val));
447  }
448  else {
449  $type = $.type;
450  $nstype = $.nstype;
451  }
452 
453  switch ($type) {
454  case "byte": {
455  my int $v = int($val);
456  if (($v & 0xff) != $v)
457  throw SOAP_SERIALIZATION_ERROR, sprintf("value %d is out of range for type %n", $v, $type);
458  break;
459  }
460 
461  case "short": {
462  my int $v = int($val);
463  if ($v < RANGE_SHORT[0] || $v > RANGE_SHORT[1])
464  throw SOAP_SERIALIZATION_ERROR, sprintf("value %d is out of range for type %n", $v, $type);
465  break;
466  }
467 
468  case "int": {
469  my int $v = int($val);
470  if ($v < RANGE_INT[0] || $v > RANGE_INT[1])
471  throw SOAP_SERIALIZATION_ERROR, sprintf("value %d is out of range for type %n", $v, $type);
472  break;
473  }
474 
475  case "unsignedByte": {
476  my int $v = int($val);
477  if (($v & 0xff) != $v)
478  throw SOAP_SERIALIZATION_ERROR, sprintf("value %d is out of range for type %n", $v, $type);
479  if ($v < 0)
480  throw SOAP_SERIALIZATION_ERROR, sprintf("type %n does not accept negative values (value supplied: %d)", $type, $v);
481  break;
482  }
483 
484  case "unsignedShort": {
485  my int $v = int($val);
486  if ($v < 0 || $v > RANGE_SHORT[1])
487  throw SOAP_SERIALIZATION_ERROR, sprintf("value %d is out of range for type %n", $v, $type);
488  break;
489  }
490 
491  case "unsignedInt": {
492  my int $v = int($val);
493  if ($v < 0 || $v > RANGE_INT[1])
494  throw SOAP_SERIALIZATION_ERROR, sprintf("value %d is out of range for type %n", $v, $type);
495  break;
496  }
497 
498  case "unsignedLong": {
499  my int $v = int($val);
500  if ($v < 0)
501  throw SOAP_SERIALIZATION_ERROR, sprintf("type %n does not accept negative values (value supplied: %d)", $type, $v);
502  break;
503  }
504 
505  case "positiveInteger":
506  if ($val <= 0)
507  throw SOAP_SERIALIZATION_ERROR, sprintf("type %n only accepts positive values (value supplied: %d)", $type, $val);
508  break;
509 
510  case "date":
511  $val = format_date("YYYY-MM-DD", date($val));
512  break;
513 
514  case "dateTime":
515  $val = format_date("YYYY-MM-DDTHH:mm:SS", date($val));
516  break;
517 
518  case "boolean":
519  $val = $val ? "true" : "false";
520  break;
521 
522  case "time":
523  $val = format_date("hh:mm:ss.ms", date($val));
524  break;
525 
526  case "base64Binary":
527  $val = makeBase64String($val);
528  break;
529 
530  case "hexBinary":
531  $val = makeHexString($val);
532  break;
533  }
534 
535  #printf("DEBUG: FORCE: type=%n, nstype=%n, val=%n\n", $type, $.nstype, $val);
536  if ($omit_type == "ns")
537  return ( "^attributes^" : ( "xmlns:xsi" : XSI_NS, "xsi:type" : $nstype ), "^value^" : $val );
538  return $omit_type ? $val : ( "^attributes^" : ( "xsi:type" : $nstype ), "^value^" : $val );
539  }
540 
541  any deserialize(any $types, any $mrh, any $val) {
542  my string $type;
543  if ($val.typeCode() == NT_HASH) {
544  $type = $val."^attributes^"."xsi:type";
545  my string $t = ($type =~ x/\w+:(\w+)/)[0];
546  if (exists $t)
547  $type = $t;
548 
549  if ($.type != "anyType" && $type != $.type)
550  throw SOAP_DESERIALIZATION_ERROR, sprintf("expecting base type %n, got %n", $.type, $val."^attributes^"."xsi:type");
551  if (exists $val."^value^")
552  $val = $val."^value^";
553  }
554  else
555  $type = $.type;
556 
557  switch ($type) {
558  case "string":
559  case "anyURI":
560  # note that we do not convert xsd:integer to a qore integer to avoid losing precision
561  case "integer":
562  return $val;
563 
564  case "byte":
565  $val = int($val);
566  if (($val & 0xff) != $val)
567  throw SOAP_DESERIALIZATION_ERROR, sprintf("value %d is out of range for type %n", $val, $.type);
568  return $val;
569 
570  case "short":
571  $val = int($val);
572  if ($val < RANGE_SHORT[0] || $val > RANGE_SHORT[1])
573  throw SOAP_DESERIALIZATION_ERROR, sprintf("value %d is out of range for type %n", $val, $.type);
574  return $val;
575 
576  case "int":
577  $val = int($val);
578  if ($val < RANGE_INT[0] || $val > RANGE_INT[1])
579  throw SOAP_DESERIALIZATION_ERROR, sprintf("value %d is out of range for type %n", $val, $.type);
580  return $val;
581 
582  case "long":
583  return int($val);
584 
585  case "unsignedByte":
586  $val = int($val);
587  if (($val & 0xff) != $val)
588  throw SOAP_DESERIALIZATION_ERROR, sprintf("value %d is out of range for type %n", $val, $.type);
589  if ($val < 0)
590  throw SOAP_DESERIALIZATION_ERROR, sprintf("type %n does not accept negative values (value supplied: %d)", $.type, $val);
591  return $val;
592 
593  case "unsignedShort":
594  $val = int($val);
595  if (($val & 0xffff) != $val)
596  throw SOAP_DESERIALIZATION_ERROR, sprintf("value %d is out of range for type %n", $val, $.type);
597  if ($val < 0)
598  throw SOAP_DESERIALIZATION_ERROR, sprintf("type %n does not accept negative values (value supplied: %d)", $.type, $val);
599  return $val;
600 
601  case "unsignedInt":
602  $val = int($val);
603  if (($val & 0xffffffff) != $val)
604  throw SOAP_DESERIALIZATION_ERROR, sprintf("value %d is out of range for type %n", $val, $.type);
605  if ($val < 0)
606  throw SOAP_DESERIALIZATION_ERROR, sprintf("type %n does not accept negative values (value supplied: %d)", $.type, $val);
607  return $val;
608 
609  case "unsignedLong":
610  if ($val < 0)
611  throw SOAP_DESERIALIZATION_ERROR, sprintf("type %n does not accept negative values (value supplied: %d)", $.type, $val);
612  return int($val);
613 
614  case "positiveInteger":
615  if ($val <= 0)
616  throw SOAP_DESERIALIZATION_ERROR, sprintf("type %n only accepts positive values (value supplied: %d)", $.type, $val);
617  return int($val);
618 
619  case "date":
620  # remove dashes from date
621  $val =~ s/-//g;
622  return date($val);
623 
624  case "dateTime":
625  return date(substr($val, 0, 4) + substr($val, 5, 2) + substr($val, 8, 2) +
626  substr($val, 11, 2) + substr($val, 14, 2) + substr($val, 17, 2));
627 
628  case "time":
629  return date("19700101" + substr($val, 0, 2) + substr($val, 3, 2) + substr($val, 6, 2)) +
630  milliseconds(substr($val, 9, 3));
631 
632  case "boolean":
633  if ($val =~ /true/i)
634  return True;
635  if ($val =~ /false/i)
636  return False;
637  return boolean($val);
638 
639  case "decimal":
640  return float($val);
641 
642  case "base64Binary":
643  return parseBase64String($val);
644 
645  case "hexBinary":
646  return parseHexString($val);
647 
648  default: {
649  if ($.type == "anyType") {
650  if (exists $types.$type)
651  return $types.$type.deserialize($types, $mrh, $val);
652  }
653  throw SOAP_DESERIALIZATION_ERROR, sprintf("don't know how to handle type %n", $.type);
654  }
655  }
656  }
657 
658  string getName() {
659  return $.type;
660  }
661 
662  string getNameWithNS() {
663  return $.nstype;
664  }
665 }
666 
667 # class for XSD array types; currently only supports "binary"; used, for example with HTTP MultiPart messages
668 public class WSDL::XSDArrayType inherits XSDData {
669  public {
670  string $.type;
671  }
672  constructor(string $t) {
673  $.type = $t;
674 
675  if ($t != "binary")
676  throw "XSD-ARRAYTYPE-ERROR", sprintf("don't know how to handle arrays of type %n", $t);
677  }
678  any serialize(any $val, any $omit_type) {
679  switch ($.type) {
680  case "binary": {
681  my int $t = $val.typeCode();
682  if ($t === NT_STRING)
683  $val = binary($val);
684  else if ($t !== NT_BINARY)
685  throw SOAP_SERIALIZATION_ERROR, sprintf("cannot serialize type %n from type %n; requires string or binary", $.type, $t);
686  return $val;
687  }
688 
689  default: {
690  throw SOAP_SERIALIZATION_ERROR, sprintf("don't know how to handle type %n", $.type);
691  }
692  }
693  }
694  any deserialize(any $types, any $mrh, any $val) {
695  switch ($.type) {
696  case "binary": {
697  if ($val.typeCode() != NT_BINARY)
698  throw SOAP_DESERIALIZATION_ERROR, sprintf("cannot deserialize type %n from type %n; requires binary", $.type, $val.typeName());
699  return $val;
700  }
701 
702  default: {
703  throw SOAP_DESERIALIZATION_ERROR, sprintf("don't know how to handle type %n", $.type);
704  }
705  }
706  }
707 }
708 
709 # XSD element class
710 public class WSDL::XSDElement inherits XSDNamedData {
711  public {
712  any $.type;
713  int $.minOccurs = 1;
714  int $.maxOccurs = 1;
715  bool $.nillable = False;
716  }
717  constructor(hash $e, any $nsinfo, XSDLateResolverHelper $unresolved) : XSDNamedData(\$e) {
718  if ($nsinfo instanceof XSDData) {
719  $.type = $nsinfo;
720  return;
721  }
722 
723  my any $a = $e."^attributes^";
724 
725  if (exists $a.minOccurs)
726  $.minOccurs = int($a.minOccurs);
727 
728  if (exists $a.maxOccurs)
729  if ($a.maxOccurs == "unbounded")
730  $.maxOccurs = -1;
731  else
732  $.maxOccurs = int($a.maxOccurs);
733 
734  if ($.maxOccurs != -1 && $.minOccurs > $.maxOccurs)
735  throw "XSD-ELEMENT-ERROR", sprintf("minOccurs (%d) > maxOccurs (%d) for element %s", $.minOccurs, $.maxOccurs, $.name);
736 
737  if ($a.nillable == "true")
738  $.nillable = True;
739 
740  if (exists $a.type) {
741  $.type = WSDL::XSDBase::doType($a.type, $nsinfo);
742 
743  # add self to unresolved list if element type cannot be resolved
744  if (!($.type instanceof XSDData)) {
745  #printf("DEBUG: self=%n\n", $self);
746  $unresolved.add($self);
747  }
748  }
749  else if (exists $e.simpleType)
750  $.type = new XSDSimpleType($e.simpleType, $nsinfo, $unresolved);
751  else if (exists $e.complexType)
752  $.type = new XSDComplexType($e.complexType, $nsinfo, $unresolved);
753 
754  #printf("DEBUG: XSDElement self=%N\n", $self);
755  }
756 
757  any serialize(any $h, *softbool $omit_type, *softbool $omit_ns, any $key, any $typename) {
758  #printf("DEBUG: XSDElement::serialize() name=%y h=%y key=%y typename=%y\n", $.name, $h, $key, $typename);
759 
760  if (!exists $h) {
761  if ($.minOccurs) {
762  if ($.nillable) {
763  my hash $rh = ("xsi:nil" : "true");
764  if (!$omit_type)
765  $rh += ("xsi:type" : $.type.getNameWithNS());
766  return ("^attributes^" : $rh);
767  }
768  else {
769  if (exists $key && exists $typename)
770  throw SOAP_SERIALIZATION_ERROR, sprintf("missing value for %s.%s (minOccurs=%d, type %n)", $typename, $key, $.minOccurs, $.type.getName());
771  else
772  throw SOAP_SERIALIZATION_ERROR, sprintf("missing element value (minOccurs=%d, type %n)", $.minOccurs, $.type.getName());
773  }
774  }
775  else
776  return;
777  }
778  if ($h.typeCode() == NT_LIST) {
779  if (elements $h == 1)
780  $h = $h[0];
781  else {
782  if ($.maxOccurs == 1)
783  throw SOAP_SERIALIZATION_ERROR, sprintf("cannot serialize element %n of type %n from a list because maxOccurs = 1", $.name, $.type.getName());
784  if (elements $h > $.maxOccurs && $.maxOccurs > 0)
785  throw SOAP_SERIALIZATION_ERROR, sprintf("list for element %n of type %n has %d element%s, but maxOccurs = %d", $.name, $.type.getName(), elements $h, elements $h == 1 ? "" : "s", $.maxOccurs);
786  if (elements $h < $.minOccurs)
787  throw SOAP_SERIALIZATION_ERROR, sprintf("list for element %n of type %n has %d element%s, but minOccurs = %d", $.name, $.type.getName(), elements $h, elements $h == 1 ? "" : "s", $.minOccurs);
788 
789  my list $l = ();
790  foreach my any $e in ($h) {
791  $l += $.type.serialize($e, $omit_type, $omit_ns);
792  }
793  return $l;
794  }
795  }
796  if ($.minOccurs > 1)
797  throw SOAP_SERIALIZATION_ERROR, sprintf("only one element passed to element %n of type $n, but minOccurs = %d", $.name, $.type.getName(), $.minOccurs);
798  #printf("DEBUG: element %n omit_type=%n omit_ns=%n\n", $.name, $omit_type, $omit_ns);
799  #printf("DEBUG: type=%N\n", $.type);
800  return $.type.serialize($h, $omit_type, $omit_ns);
801  }
802 
803  any deserialize(any $types, any $mrh, any $val) {
804  my any $a = $val."^attributes^";
805  WSDL::XSDBase::removeNS(\$a);
806 
807  if (!exists $val || $a.nil == "true") {
808  if ($.nillable || !$.minOccurs)
809  return;
810  throw SOAP_DESERIALIZATION_ERROR, sprintf("NOTHING passed for element %n, but nillable=False and minOccurs=%d", $.name, $.minOccurs);
811  }
812 
813  if ($val.typeCode() == NT_LIST) {
814  my int $el = elements $val;
815  if ($.maxOccurs != -1 && $el > $.maxOccurs)
816  throw SOAP_DESERIALIZATION_ERROR, sprintf("error deserializing element %n, maxOccurs=%d but list is %d elements long", $.name, $.maxOccurs, $el);
817  if ($el < $.minOccurs)
818  throw SOAP_DESERIALIZATION_ERROR, sprintf("error deserializing element %n, minOccurs=%d but list is %d elements long", $.name, $.minOccurs, $el);
819 
820  my list $l;
821  foreach my any $e in ($val)
822  $l[elements $l] = $.type.deserialize($types, $mrh, $.getValue($mrh, $e));
823  return $l;
824  }
825 
826  if ($.minOccurs > 1)
827  throw SOAP_DESERIALIZATION_ERROR, sprintf("single value passed for element %n, but minOccurs=%d", $.name, $.minOccurs);
828 
829  return $.type.deserialize($types, $mrh, $.getValue($mrh, $val));
830  }
831 }
832 
833 # XSD simple type class
834 public class WSDL::XSDSimpleType inherits XSDNamedData {
835  public {
836  any $.nsinfo;
837  list $.enum = ();
838  any $.type;
839  }
840 
841  constructor(hash $st, any $nsinfo, XSDLateResolverHelper $unresolved) : XSDNamedData(\$st) {
842  $.nsinfo = $nsinfo;
843  #my any $a = $st."^attributes^";
844  delete $st."^attributes^";
845 
846  WSDL::XSDBase::removeNS(\$st);
847 
848  if (exists $st.restriction) {
849  my any $r = $st.restriction;
850 
851  my any $base = $r."^attributes^".base;
852  if (!exists $base)
853  throw "XSD-SIMPLETYPE-ERROR", sprintf("missing 'base' attribute in simpleType %n restriction", $.name);
854 
855  $.type = WSDL::XSDBase::doType($base, $nsinfo);
856 
857  # add base type to unresolved list if type cannot be resolved
858  if (!($.type instanceof XSDData))
859  $unresolved.add($self);
860 
861  WSDL::XSDBase::removeNS(\$r);
862 
863  if (exists $r.enumeration)
864  $.enum = map $1."^attributes^".value, $r.enumeration;
865  else
866  throw "XSD-SIMPLETYPE-ERROR", sprintf("missing enumeration element in simpleType %n restriction", $.name);
867  }
868  else
869  throw "XSD-SIMPLETYPE-ERROR", sprintf("missing restriction element in simpleType %n", $.name);
870 
871  #printf("DEBUG: st=%N\n", $self); exit();
872  }
873 
874  any serialize(any $val, *softbool $omit_type, *softbool $omit_ns) {
875  if (!inlist($val, $.enum))
876  throw "SOAP-SERIALIZATION-ERROR", sprintf("value %n passed to simpleType %n is not in the enumeration list (%n)", $val, $.name, $.enum);
877 
878  return $.type.serialize($val, $omit_type, $omit_ns);
879  }
880 
881  any deserialize(any $types, any $mrh, any $val) {
882  my any $v = $.type.deserialize($types, $mrh, $val);
883 
884  if (!inlist($v, $.enum))
885  throw "SOAP-DESERIALIZATION-ERROR", sprintf("value %n passed to simpleType %n is not in the enumeration list (%n)", $v, $.name, $.enum);
886 
887  return $v;
888  }
889 
890  string getNameWithNS() {
891  return "ns1:" + $.name;
892  }
893 }
894 
895 # XSD complex type class
896 public class WSDL::XSDComplexType inherits XSDNamedData {
897  public {
898  any $.nsinfo;
899  any $.array;
900  any $.restriction;
901  any $.extension;
902  any $.hash_type;
903  any $.elements;
904 
905  bool $.anyAttribute = False;
906  }
907  constructor(any $ct, any $nsinfo, XSDLateResolverHelper $unresolved) : XSDNamedData(\$ct) {
908  $.nsinfo = $nsinfo;
909  #my any $a = $ct."^attributes^";
910  delete $ct."^attributes^";
911 
912  my any $d = $ct.complexContent;
913  if (exists $d) {
914  WSDL::XSDBase::removeNS(\$d);
915  if (exists $d.restriction) {
916  WSDL::XSDBase::removeNS(\$d.restriction);
917 
918  my any $base = $d.restriction."^attributes^".base;
919 
920  # FIXME: handle namespace
921  my (any $ns, any $tn) = $base =~ x/(\w+):(\w+)/;
922  if (exists $tn) {
923  if ($tn == "Array") {
924  # FIXME check that namespace is SOAP encoding
925  my any $aa = $d.restriction.attribute."^attributes^";
926  WSDL::XSDBase::removeNS(\$aa);
927  if (!exists $aa.arrayType)
928  throw WSDL_ERROR, sprintf("cannot parse complexType restriction: %n", $d.restriction);
929 
930  # FIXME: handle multiple dimensions?
931  my (any $ans, any $atn) = $aa.arrayType =~ x/(\w+):(\w+)\[\]$/;
932  if (exists $atn) {
933  $.array.val = $atn;
934  $.array.ns = $ans;
935  }
936  else
937  $.array.val = $aa.arrayType;
938 
939  delete $d.restriction.attribute;
940  #printf("DEBUG: ans=%n atn=%n aa=%N\n", $ans, $atn, $aa);
941  return;
942  }
943  else {
944  $.restriction = $tn;
945  }
946  }
947 
948  delete $d.restriction."^attributes^";
949 
950  $.parseData($d.restriction, $unresolved);
951  }
952  else if (exists $d.extension) {
953  $.extension = $d.extension."^attributes^".base;
954 
955  # FIXME: check for soap encoding namespace
956  $.extension =~ s/(.*:)(.*)/$2/;
957  delete $d.extension."^attributes^";
958  WSDL::XSDBase::removeNS(\$d.extension);
959 
960  $.parseData($d.extension, $unresolved);
961  }
962  else
963  throw "XSD-COMPLEXCONTENT-ERROR", sprintf("can't parse complexContent %n information", $d.firstKey());
964  }
965  else
966  $.parseData($ct, $unresolved);
967  }
968 
969  private parseData(any $d, XSDLateResolverHelper $unresolved) {
970  delete $d.ns;
971  my list $el = keys $d;
972  if (inlist("anyAttribute", $el)) {
973  $.anyAttribute = True;
974  delete $d.anyAttribute;
975  $el = keys $d;
976  }
977 
978  if (elements $d > 1)
979  throw WSDL_ERROR, sprintf("%s: expecting a single element in the complexType hash, got: %n", $.name, $el);
980 
981  my string $k = $el[0];
982  if ($k == "all") {
983  $.hash_type = XET_ALL;
984  WSDL::XSDBase::removeNS(\$d.all);
985  $.elements = $.parseElements($d.all.element, $unresolved);
986  }
987  else if ($k == "choice") {
988  $.hash_type = XET_CHOICE;
989  WSDL::XSDBase::removeNS(\$d.choice);
990  $.elements = $.parseElements($d.choice.element, $unresolved);
991  }
992  else if ($k == "sequence") {
993  $.hash_type = XET_SEQUENCE;
994  WSDL::XSDBase::removeNS(\$d.sequence);
995  if (exists $d.sequence.element)
996  $.elements = $.parseElements($d.sequence.element, $unresolved);
997  else
998  $.elements = hash();
999  }
1000  else
1001  throw "XSD-COMPLEXTYPE-ERROR", sprintf("unknown keys in %n", $d);
1002  }
1003 
1004  private hash parseElements(any $el, XSDLateResolverHelper $unresolved) {
1005  #printf("DEBUG: XSDComplexType::parseElements(%n)\n", $el);
1006  my hash $h;
1007  foreach my any $e in ($el) {
1008  my XSDElement $elem($e, $.nsinfo, $unresolved);
1009  $h.($elem.name) = $elem;
1010  }
1011  return $h;
1012  }
1013 
1014  any serialize(any $h, *softbool $omit_type, *softbool $omit_ns) {
1015  if (exists $.array)
1016  return $.array.serialize($h, $omit_type, $omit_ns);
1017 
1018  if ($h.typeCode() != NT_HASH)
1019  throw SOAP_SERIALIZATION_ERROR, sprintf("expecting hash argument to serialize from complexType %n (got %n, type %n)", $.getName(), $h, type($h));
1020 
1021  my hash $rh;
1022 
1023  if ($.hash_type == XET_SEQUENCE || $.hash_type == XET_ALL) {
1024  foreach my string $p in (keys $.elements) {
1025  #printf("DEBUG element=%s=%y\nvalue=%y\n", $p, $.elements.$p, $h.$p);
1026  my any $e = $.elements.$p.serialize($h.$p, $omit_type, $omit_ns, $p, $.name);
1027  if (exists $e) {
1028  my any $key = $omit_ns ? $p : ("ns1:" + $p);
1029  $rh.$key = $e;
1030  }
1031  delete $h.$p;
1032  }
1033  if (elements $h)
1034  throw SOAP_SERIALIZATION_ERROR, sprintf("%n %s of type %n (valid elements: %n)", (my string $kl = keys $h), elements $kl == 1 ? "is an invalid member" : "are invalid members", $.getName(), keys $.elements);
1035  }
1036  else { # "choice" - union
1037  if (elements $h > 1)
1038  throw SOAP_SERIALIZATION_ERROR, sprintf("cannot serialize type %s with more than 1 member (%n)", $.getName(), keys $h);
1039  my *string $key = keys $h.firstKey();
1040  if (!exists $.elements.$key)
1041  throw SOAP_SERIALIZATION_ERROR, sprintf("%n is an invalid member of type %n", $key, $.getName());
1042 
1043  # add namespace if necessary
1044  my string $nskey = $omit_ns ? $key : ("ns1:" + $key);
1045  $rh.$nskey = $.elements.$key.serialize($h.$key, $omit_type, $omit_ns, $key, $.name);
1046  }
1047 
1048  if (exists $.name && !$omit_type)
1049  $rh."^attributes^" = ( "xsi:type" : "ns1:" + $.name );
1050  #printf("complex type %s returning %n from %n\n", $.name, $rh, $h);
1051  return $rh;
1052  }
1053 
1054  hash deserialize(any $types, any $mrh, any $val) {
1055  if (exists $.array)
1056  return $.array.deserialize($types, $mrh, $val);
1057 
1058  if ($val.typeCode() != NT_HASH)
1059  throw SOAP_DESERIALIZATION_ERROR, sprintf("cannot deserialize type %n from qore type %n (expecting hash)", $.getName(), type($val));
1060 
1061  my hash $rh;
1062 
1063  my any $attr = $val."^attributes^";
1064  delete $val."^attributes^";
1065 
1066  # ensure types match
1067  my any $tn = $attr."xsi:type";
1068  if (exists $tn) {
1069  my (any $ns, any $name) = $tn =~ x/(.*):(.*)/;
1070  if (exists $name)
1071  $tn = $name;
1072  if ($tn != $.name)
1073  throw SOAP_DESERIALIZATION_ERROR, sprintf("expecting ComplexType type %n, got %n", $.getName(), $tn);
1074  }
1075 
1076  WSDL::XSDBase::removeNS2(\$val);
1077 
1078  #my any $ns = $val.".ns";
1079  $val -= ".ns";
1080 
1081  if ($.hash_type == XET_SEQUENCE || $.hash_type == XET_ALL) {
1082  foreach my string $p in (keys $.elements) {
1083  #printf("element %n\n", $p);
1084  $rh.$p = $.elements.$p.deserialize($types, $mrh, $.getValue($mrh, $val.$p));
1085  delete $val.$p;
1086  }
1087  delete $val."^attributes^";
1088  if (elements $val)
1089  throw SOAP_DESERIALIZATION_ERROR, sprintf("invalid element %n passed in type %n (expecting %n)", (keys $val)[0], $.getName(), keys $.elements);
1090  }
1091  else { # "choice" - union
1092  my any $kl = keys $val;
1093  if (elements $kl > 1)
1094  throw SOAP_DESERIALIZATION_ERROR, sprintf("too many elements supplied for union type %n (%n)", $.getName(), $kl);
1095  $kl = $kl[0];
1096  if (!exists $.elements.$kl)
1097  throw SOAP_DESERIALIZATION_ERROR, sprintf("element %n is not a valid element for union type %n", $kl, $.getName());
1098 
1099  $rh.$kl = $.elements.$kl.deserialize($types, $mrh, $.getValue($mrh, $val.$kl));
1100  }
1101  return $rh;
1102  }
1103 
1104  string getNameWithNS() {
1105  return "ns1:" + $.name;
1106  }
1107 }
1108 
1109 #! web service operation class
1110 public class WSDL::WSOperation inherits XSDNamedData {
1111  public {
1112  WSMessage $.input;
1113  WSMessage $.output;
1114  any $.types;
1115  string $.targetns;
1116  bool $.soap12 = False;
1117  bool $.usedocns = False;
1118  *string $.soapAction;
1119  *string $.request_name;
1120  any $.in;
1121  any $.out;
1122  bool $.docstyle = False;
1123 
1124  # info about soap header requirements
1125  hash $.iheader;
1126  hash $.oheader;
1127  }
1128 
1129  constructor(any $p, any $types, string $targetns, any $messages, bool $soap12 = False, bool $usedocns = False) : XSDNamedData(\$p) {
1130  $.types = $types;
1131  $.targetns = $targetns;
1132  $.soap12 = $soap12;
1133  $.usedocns = $usedocns;
1134 
1135  my any $msghash = $.processNSValue($p.input."^attributes^");
1136 
1137  my *WSMessage $msg = $messages.($msghash.message.val);
1138  if (!exists $msg)
1139  throw WSDL_ERROR, sprintf("missing definition for input message %n required by operation %n", $msghash.name.val, $.name);
1140  $.input = $msg;
1141 
1142  if (exists $p.output) {
1143  $msghash = $.processNSValue($p.output."^attributes^");
1144 
1145  $msg = $messages.($msghash.message.val);
1146  if (!exists $msg)
1147  throw WSDL_ERROR, sprintf("missing definition for output message %n required by operation %n", $msghash.name.val, $.name);
1148 
1149  $.output = $msg;
1150  }
1151 
1152  my *string $op_ns = $.targetns;
1153  if (exists $op_ns && $op_ns !~ /\/$/)
1154  $op_ns += "/";
1155  $.soapAction = exists $op_ns ? $op_ns + $.name : $.name;
1156  }
1157 
1158  setDocStyle(reference $idocmap) {
1159  $.docstyle = True;
1160 
1161  if (elements $.input.args > 1)
1162  throw WSDL_ERROR, sprintf("don't know how to handle document-style messages for operation %n that has more than one top-level part (%n)",
1163  $.name, keys $.input.args);
1164 
1165  my any $arg = ($.input.args).firstKey();
1166  my any $element = $.input.args.$arg.element.name;
1167  $.request_name = $element;
1168  $idocmap.$element = $.input.args.$arg.element;
1169  }
1170 
1171  setTopLevelRequestElement(string $name) {
1172  $.request_name = $name;
1173  }
1174 
1175  string getTopLevelRequestName() {
1176  return exists $.request_name ? $.request_name : $.name;
1177  }
1178 
1179  #! serializes a request to an XML string for the operation
1180 
1187  hash serializeRequest(any h, any header, *string enc);
1188 
1189 
1191 
1197  hash serializeResponse(any h, *string enc);
1198 
1199 
1200 
1201 private:
1202  list processMultiRef(hash body);
1203 public:
1204 
1205 
1207 
1210  any deserializeRequest(hash o);
1211 
1212 
1214 
1217  any deserializeResponse(hash o);
1218 
1219 
1220 
1221 private:
1222  hash processNSValue(hash h);
1223 public:
1224 
1225 
1227 
1229  bool isSoap12();
1230 
1231 
1233 
1235  string getTargetNS();
1236 
1237 
1238  setOutputMultipart(any v);
1239 
1240 
1241 
1242 private:
1243  parsePart(reference msg, any part);
1244 public:
1245 
1246 
1247  addOutputPart(any part);
1248 
1249 
1250  setInputMultipart(any v);
1251 
1252 
1253  addInputPart(any part);
1254 
1255 
1256  setInputHeader(string part, WSMessage msg, bool encoded);
1257 
1258 };
1259 
1260 // web service message class
1261 class WSDL::WSMessage : public XSDNamedData {
1262 
1263 public:
1264  public :
1265  hash args;
1266  bool encoded = False;
1267 
1268 public:
1269  constructor(any m, any element_map);
1270 
1271 
1272  hash serialize(any msginfo, any mpm, any name, any h);
1273 
1274 
1275  hash serializeDocument(any msginfo, any mpm, any h, bool force_ns);
1276 
1277 
1278  any deserialize(any types, any mrh, any val);
1279 
1280 
1281  any deserializeDocument(any types, any mrh, any val);
1282 
1283 };
1284 
1285 // private helper class for lazy name resolution
1286 class WSDL::XSDLateResolverHelper {
1287 
1288 public:
1289 private:
1290  list l = ();
1291 public:
1292 
1293  constructor();
1294 
1295 
1296  add(any v);
1297 
1298 
1299  list getList();
1300 
1301 };
1302 
1303 // private helper class to save namespaces in the WebService class, parses the imported definitions, and restores the namespace info on exit
1304 class WSDL::XSDImportHelper {
1305 
1306 public:
1307  public :
1308  any ws;
1309  hash sp;
1310 
1311 public:
1312 
1313  constructor(WebService ws, any xsd);
1314 
1315  destructor();
1316 
1317 };
1318 
1320 class WSDL::Binding : public XSDNamedData {
1321 
1322 public:
1323  public :
1324  bool docStyle = False;
1325 
1326 public:
1327 
1328  constructor(hash data, hash opmap, reference idocmap, *hash messages);
1329 
1330 };
1331 
1333 
1335 class WSDL::WebService : public XSDBase {
1336 
1337 public:
1338  public :
1339  string wsdl;
1340  hash ns;
1341  bool soap12 = False;
1342  hash base_type;
1343  hash services;
1344  list wsdl_services = ();
1345  hash idocmap;
1346  hash opmap;
1347  hash binding;
1348  hash element_map;
1349  hash messages;
1350  hash types;
1351  bool usedocns = False;
1352  hash portType;
1353 
1354 public:
1355 
1357 
1362  constructor(string str, *hash opts);
1363 
1364 
1366 
1368  *hash getOperationMap(any name);
1369 
1370 
1371 
1372 private:
1373  getNSPrefixes(any a);
1374 public:
1375 
1376 
1377 
1378 private:
1379  XSDBaseType getBaseType(any t);
1380 public:
1381 
1382 
1383 
1384 private:
1385  any resolveType(hash v);
1386 public:
1387 
1388 
1389  // parse XSD schema types
1390 
1391 private:
1392  parseTypes(any data, any http_client, any http_headers);
1393 public:
1394 
1395 
1396 
1397 private:
1398  parseMessage(any message);
1399 public:
1400 
1401 
1402 
1403 private:
1404  parseService(any svc);
1405 public:
1406 
1407 
1408 
1409 private:
1410  parsePortType(any data);
1411 public:
1412 
1413 
1414 
1415 private:
1416  parseBinding(any bindings);
1417 public:
1418 
1419 
1421 
1423  bool isSoap12();
1424 
1425 
1427 
1429  string getWSDL();
1430 
1431 };