comparison GEMBASSY-1.0.3/gsoap/wsdl/service.cpp @ 0:8300eb051bea draft

Initial upload
author ktnyt
date Fri, 26 Jun 2015 05:19:29 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:8300eb051bea
1 /*
2 service.cpp
3
4 Generate gSOAP service structures from WSDL.
5
6 --------------------------------------------------------------------------------
7 gSOAP XML Web services tools
8 Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc. All Rights Reserved.
9 This part of the software is released under one of the following licenses:
10 GPL or Genivia's license for commercial use.
11 --------------------------------------------------------------------------------
12 GPL license.
13
14 This program is free software; you can redistribute it and/or modify it under
15 the terms of the GNU General Public License as published by the Free Software
16 Foundation; either version 2 of the License, or (at your option) any later
17 version.
18
19 This program is distributed in the hope that it will be useful, but WITHOUT ANY
20 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 PARTICULAR PURPOSE. See the GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License along with
24 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
25 Place, Suite 330, Boston, MA 02111-1307 USA
26
27 Author contact information:
28 engelen@genivia.com / engelen@acm.org
29 --------------------------------------------------------------------------------
30 A commercial use license is available from Genivia, Inc., contact@genivia.com
31 --------------------------------------------------------------------------------
32
33 TODO: consider adding support for non-SOAP HTTP operations
34 add headerfault output definitions
35
36 */
37
38 #include "types.h"
39 #include "service.h"
40
41 #include <algorithm>
42
43 #define URI_CHAR(c) (((c) > 32 && (c) != '"' && (c) != '<' && (c) != '>' && (c) != '\\' && (c) != '^' && (c) != '`' && (c) <= 'z') || (c) == '~')
44
45 static const char *urienc(struct soap*, const char*);
46 static bool imported(const char *tag);
47 static void comment(const char *start, const char *middle, const char *end, const char *text);
48 static void page(const char *page, const char *title, const char *text);
49 static void section(const char *section, const char *title, const char *text);
50 static void banner(const char*);
51 static void banner(const char*, const char*);
52 static void ident();
53 static void gen_policy(Service&, const vector<const wsp__Policy*>&, const char*, Types&);
54 static void gen_policy_enablers(const Service&);
55
56 ////////////////////////////////////////////////////////////////////////////////
57 //
58 // Definitions methods
59 //
60 ////////////////////////////////////////////////////////////////////////////////
61
62 Definitions::Definitions()
63 { }
64
65 void Definitions::collect(const wsdl__definitions &definitions)
66 { // Collect information: analyze WSDL definitions and imported definitions
67 analyze(definitions);
68 for (vector<wsdl__import>::const_iterator import = definitions.import.begin(); import != definitions.import.end(); ++import)
69 if ((*import).definitionsPtr())
70 analyze(*(*import).definitionsPtr());
71 }
72
73 void Definitions::analyze(const wsdl__definitions &definitions)
74 { // Analyze WSDL and build Service information
75 int binding_count = 0;
76 // Determine number of relevant SOAP service bindings (service prefix option only)
77 for (vector<wsdl__binding>::const_iterator i = definitions.binding.begin(); i != definitions.binding.end(); ++i)
78 { for (vector<wsdl__ext_operation>::const_iterator j = (*i).operation.begin(); j != (*i).operation.end(); ++j)
79 { if ((*j).operationPtr())
80 { binding_count++;
81 break;
82 }
83 }
84 }
85 if (binding_count == 0 && definitions.name && (!definitions.portType.empty() || !definitions.interface_.empty()))
86 fprintf(stderr, "\nWarning: WSDL \"%s\" has no bindings to implement operations\n", definitions.name);
87 else if (binding_count > 1 && !service_prefix)
88 { // This puts all operations under a single binding
89 fprintf(stderr, "\nWarning: %d service bindings found, but collected as one service (use option -Nname to produce a separate service for each binding)\n", binding_count);
90 }
91 // Analyze and collect service data
92 for (vector<wsdl__binding>::const_iterator binding = definitions.binding.begin(); binding != definitions.binding.end(); ++binding)
93 { // /definitions/binding/documentation
94 const char *binding_documentation = (*binding).documentation;
95 // /definitions/binding/soap:binding
96 soap__binding *soap__binding_ = (*binding).soap__binding_;
97 // /definitions/binding/soap:binding/@transport
98 const char *soap__binding_transport = NULL;
99 int version = 0;
100 if (soap__binding_)
101 soap__binding_transport = soap__binding_->transport;
102 else if ((*binding).wsoap__version && strlen((*binding).wsoap__version) > 2)
103 version = (*binding).wsoap__version[2]-'0'; // WSDL 2.0
104 else if (!(*binding).http__binding_)
105 version = 2; // assume WSDL 2.0
106 if (version == 2)
107 soap12 = true;
108 // /definitions/binding/@soap:protocol
109 if ((*binding).wsoap__protocol)
110 soap__binding_transport = (*binding).wsoap__protocol;
111 // /definitions/binding/@name
112 const char *binding_name = "";
113 if ((*binding).name)
114 binding_name = (*binding).name;
115 else if ((*binding).portTypePtr() && (*binding).portTypePtr()->name)
116 { char *s = (char*)soap_malloc(definitions.soap, strlen((*binding).portTypePtr()->name) + 8);
117 strcpy(s, (*binding).portTypePtr()->name);
118 strcat(s, "Binding");
119 binding_name = s;
120 }
121 // /definitions/binding/@type
122 const char *binding_type = NULL;
123 if ((*binding).type_)
124 binding_type = (*binding).type_;
125 // TODO: need to find the Policy of portType, though never used...
126 // const wsp__Policy *portType_policy = NULL;
127 // /definitions/binding/wsp:Policy and wsp:PolicyReference
128 /*
129 const wsp__Policy *binding_policy = NULL;
130 if ((*binding).wsp__Policy_)
131 binding_policy = (*binding).wsp__Policy_;
132 if ((*binding).wsp__PolicyReference_)
133 binding_policy = (*binding).wsp__PolicyReference_->policyPtr();
134 */
135 // /definitions/binding/http:binding
136 http__binding *http__binding_ = (*binding).http__binding_;
137 const char *http__binding_verb = NULL;
138 if (http__binding_)
139 http__binding_verb = http__binding_->verb; // HTTP POST and GET
140 else if ((*binding).whttp__methodDefault)
141 http__binding_verb = (*binding).whttp__methodDefault; // HTTP POST and GET
142 // /definitions/binding/soap:binding/@style
143 soap__styleChoice soap__binding_style = document;
144 if (soap__binding_ && soap__binding_->style)
145 soap__binding_style = *soap__binding_->style;
146 // /definitions/binding/operation*
147 for (vector<wsdl__ext_operation>::const_iterator operation = (*binding).operation.begin(); operation != (*binding).operation.end(); ++operation)
148 { // /definitions/portType/operation/ associated with /definitions/binding/operation
149 wsdl__operation *wsdl__operation_ = (*operation).operationPtr();
150 // /definitions/binding/operation/soap:operation
151 soap__operation *soap__operation_ = (*operation).soap__operation_;
152 // /definitions/binding/operation/soap:operation/@style
153 soap__styleChoice soap__operation_style = soap__binding_style;
154 if (soap__operation_ && soap__operation_->style)
155 soap__operation_style = *soap__operation_->style;
156 // /definitions/binding/@wsoap:mepDefault
157 const char *soap__operation_mep = (*binding).wsoap__mepDefault;
158 // /definitions/binding/operation/@wsoap:mep
159 if ((*operation).wsoap__mep)
160 soap__operation_mep = (*operation).wsoap__mep;
161 // /definitions/binding/operation/@whttp:method
162 const char *http_method = http__binding_verb;
163 if ((*operation).whttp__method)
164 http_method = (*operation).whttp__method;
165 // /definitions/binding/operation/@wsoap:action
166 const char *soap__operation_action = NULL;
167 if ((*operation).wsoap__action)
168 soap__operation_action = (*operation).wsoap__action;
169 // /definitions/binding/operation/http:operation
170 http__operation *http__operation_ = (*operation).http__operation_;
171 // /definitions/binding/wsp:Policy and wsp:PolicyReference
172 const wsp__Policy *ext_operation_policy = NULL;
173 if ((*operation).wsp__Policy_)
174 ext_operation_policy = (*operation).wsp__Policy_;
175 if ((*operation).wsp__PolicyReference_)
176 ext_operation_policy = (*operation).wsp__PolicyReference_->policyPtr();
177 // /definitions/binding/operation/http:operation/@location
178 const char *http__operation_location = NULL;
179 if (http__operation_)
180 http__operation_location = http__operation_->location;
181 else if ((*operation).whttp__location)
182 http__operation_location = (*operation).whttp__location;
183 // /definitions/binding/operation/input and output
184 wsdl__ext_ioput *ext_input, *ext_output;
185 // /definitions/portType/operation
186 if (wsdl__operation_ && wsdl__operation_->name)
187 { bool reversed = false;
188 wsdl__ioput *input = NULL;
189 wsdl__ioput *output = NULL;
190 // normalize input/output order for solicit-response operations
191 if (wsdl__operation_->__union1 == SOAP_UNION_wsdl__union_ioput_input)
192 input = wsdl__operation_->__ioput1.input;
193 else if (wsdl__operation_->__union1 == SOAP_UNION_wsdl__union_ioput_output)
194 { reversed = true;
195 input = wsdl__operation_->__ioput1.output;
196 }
197 if (wsdl__operation_->__union2 == SOAP_UNION_wsdl__union_ioput_input)
198 { reversed = true;
199 output = wsdl__operation_->__ioput2.input;
200 }
201 else if (wsdl__operation_->__union2 == SOAP_UNION_wsdl__union_ioput_output)
202 output = wsdl__operation_->__ioput2.output;
203 else // one input only or one output only (or none)
204 { reversed = false;
205 input = NULL;
206 output = NULL;
207 if (wsdl__operation_->__union1 == SOAP_UNION_wsdl__union_ioput_input)
208 input = wsdl__operation_->__ioput1.input;
209 else if (wsdl__operation_->__union1 == SOAP_UNION_wsdl__union_ioput_output)
210 output = wsdl__operation_->__ioput1.output;
211 }
212 if (!reversed)
213 { ext_input = (*operation).input;
214 ext_output = (*operation).output;
215 }
216 else
217 { ext_input = (*operation).output;
218 ext_output = (*operation).input;
219 }
220 if ((http_method && !strcmp(http_method, "GET"))
221 || (wsdl__operation_->pattern && !strstr(wsdl__operation_->pattern, "in")))
222 input = NULL;
223 if (wsdl__operation_->pattern && !strstr(wsdl__operation_->pattern, "out"))
224 output = NULL;
225 if (wsdl__operation_->pattern) // WSDL 2.0
226 { soap__operation_style = document;
227 if (wsdl__operation_->style && !strcmp(wsdl__operation_->style, "http://www.w3.org/ns/wsdl/rpc"))
228 soap__operation_style = rpc;
229 else if ((*binding).portTypePtr() && (*binding).portTypePtr()->styleDefault && !strcmp( (*binding).portTypePtr()->styleDefault, "http://www.w3.org/ns/wsdl/rpc"))
230 soap__operation_style = rpc;
231 }
232 // /definitions/binding/wsp:Policy and wsp:PolicyReference
233 const wsp__Policy *operation_policy = NULL;
234 if (wsdl__operation_->wsp__Policy_)
235 operation_policy = wsdl__operation_->wsp__Policy_;
236 if (wsdl__operation_->wsp__PolicyReference_)
237 operation_policy = wsdl__operation_->wsp__PolicyReference_->policyPtr();
238 if (!Rflag && (http__operation_ || http__operation_location))
239 { // skip WSDL REST HTTP operations
240 if (!Wflag)
241 fprintf(stderr, "\nWarning: ignoring REST operation '%s' in binding '%s' (use option -R to enable REST)\n", wsdl__operation_->name, binding_name);
242 }
243 else if (input)
244 { soap__body *input_body = NULL;
245 mime__mimeXml *input_mime = NULL;
246 mime__content *input_mime_content = NULL;
247 if (!reversed && ext_input)
248 { input_body = ext_input->soap__body_;
249 input_mime = ext_input->mime__mimeXml_;
250 input_mime_content = ext_input->mime__content_;
251 if (ext_input->mime__multipartRelated_)
252 { for (vector<mime__part>::const_iterator part = ext_input->mime__multipartRelated_->part.begin(); part != ext_input->mime__multipartRelated_->part.end(); ++part)
253 if ((*part).soap__body_)
254 { input_body = (*part).soap__body_;
255 break;
256 }
257 }
258 }
259 else if (ext_output)
260 { input_body = ext_output->soap__body_;
261 input_mime = ext_output->mime__mimeXml_;
262 input_mime_content = ext_output->mime__content_;
263 if (ext_output->mime__multipartRelated_)
264 { for (vector<mime__part>::const_iterator part = ext_output->mime__multipartRelated_->part.begin(); part != ext_output->mime__multipartRelated_->part.end(); ++part)
265 if ((*part).soap__body_)
266 { input_body = (*part).soap__body_;
267 break;
268 }
269 }
270 }
271 if (wsdl__operation_->style && !strcmp(wsdl__operation_->style, "http://www.w3.org/ns/wsdl/style/iri"))
272 { input_mime_content = soap_new_mime__content(definitions.soap);
273 input_mime_content->soap_default(definitions.soap);
274 input_mime_content->type = (char*)"application/x-www-form-urlencoded";
275 }
276 // MUST have an input binding, otherwise can't generate a service operation
277 if (input_body || input_mime || input_mime_content || input->element)
278 { char *URI;
279 if (input_body && soap__operation_style == rpc)
280 URI = input_body->namespace_;
281 else if (binding_count == 1 || !service_prefix)
282 URI = definitions.targetNamespace;
283 else
284 { // multiple service bidings are used, each needs a unique new URI
285 URI = (char*)soap_malloc(definitions.soap, strlen(definitions.targetNamespace) + strlen(binding_name) + 2);
286 strcpy(URI, definitions.targetNamespace);
287 if (*URI && URI[strlen(URI)-1] != '/')
288 strcat(URI, "/");
289 strcat(URI, binding_name);
290 }
291 if (URI)
292 { const char *prefix = types.nsprefix(service_prefix, URI);
293 const char *name = types.aname(NULL, NULL, binding_name); // name of service is binding name
294 Service *service = services[prefix];
295 if (!service)
296 { service = services[prefix] = new Service();
297 service->prefix = prefix;
298 service->URI = urienc(definitions.soap, URI);
299 service->name = name;
300 service->transport = soap__binding_transport;
301 if ((*binding).portTypePtr() && (*binding).portTypePtr()->name)
302 service->type = types.aname(NULL, NULL, (*binding).portTypePtr()->name);
303 else
304 service->type = NULL;
305 // collect faults (TODO: this is not used anywhere)
306 for (vector<wsdl__ext_fault>::const_iterator fault = (*binding).fault.begin(); fault != (*binding).fault.end(); ++fault)
307 { Message *f = analyze_fault(definitions, service, *fault);
308 if (f)
309 service->fault[f->name] = f;
310 }
311 // collect policies for the bindings
312 for (vector<wsp__Policy>::const_iterator p = (*binding).wsp__Policy_.begin(); p != (*binding).wsp__Policy_.end(); ++p)
313 service->policy.push_back(&(*p));
314 for (vector<wsp__PolicyReference>::const_iterator r = (*binding).wsp__PolicyReference_.begin(); r != (*binding).wsp__PolicyReference_.end(); ++r)
315 service->policy.push_back((*r).policyPtr());
316 // collect policies for the service endpoints
317 for (vector<wsdl__service>::const_iterator s = definitions.service.begin(); s != definitions.service.end(); ++s)
318 { for (vector<wsp__Policy>::const_iterator p = (*s).wsp__Policy_.begin(); p != (*s).wsp__Policy_.end(); ++p)
319 service->policy.push_back(&(*p));
320 for (vector<wsp__PolicyReference>::const_iterator r = (*s).wsp__PolicyReference_.begin(); r != (*s).wsp__PolicyReference_.end(); ++r)
321 service->policy.push_back((*r).policyPtr());
322 }
323 }
324 for (vector<wsdl__service>::const_iterator s = definitions.service.begin(); s != definitions.service.end(); ++s)
325 { for (vector<wsdl__port>::const_iterator port = (*s).port.begin(); port != (*s).port.end(); ++port)
326 { if ((*port).bindingPtr() == &(*binding))
327 { if ((*port).soap__address_ && (*port).soap__address_->location)
328 service->location.insert(urienc(definitions.soap, (*port).soap__address_->location));
329 if ((*port).wsa__EndpointReference && (*port).wsa__EndpointReference->Address)
330 service->location.insert(urienc(definitions.soap, (*port).wsa__EndpointReference->Address));
331 if ((*port).http__address_ && (*port).http__address_->location)
332 service->location.insert(urienc(definitions.soap, (*port).http__address_->location));
333 // collect service documentation
334 if ((*s).documentation)
335 service->service_documentation[(*service).name] = (*s).documentation;
336 if ((*port).documentation && (*port).name)
337 service->port_documentation[(*port).name] = (*port).documentation;
338 if (binding_documentation)
339 service->binding_documentation[binding_name] = binding_documentation;
340 // collect policies for the service and endpoints
341 if ((*port).wsp__Policy_)
342 service->policy.push_back((*port).wsp__Policy_);
343 if ((*port).wsp__PolicyReference_ && (*port).wsp__PolicyReference_->policyPtr())
344 service->policy.push_back((*port).wsp__PolicyReference_->policyPtr());
345 }
346 }
347 for (vector<wsdl__port>::const_iterator endpoint = (*s).endpoint.begin(); endpoint != (*s).endpoint.end(); ++endpoint)
348 { if ((*endpoint).bindingPtr() == &(*binding))
349 { if ((*endpoint).address)
350 service->location.insert(urienc(definitions.soap, (*endpoint).address));
351 if ((*endpoint).wsa__EndpointReference && (*endpoint).wsa__EndpointReference->Address)
352 service->location.insert(urienc(definitions.soap, (*endpoint).wsa__EndpointReference->Address));
353 if ((*endpoint).http__address_ && (*endpoint).http__address_->location)
354 service->location.insert(urienc(definitions.soap, (*endpoint).http__address_->location));
355 // TODO: locations need auth
356 // service->auth_scheme = (*endpoint).whttp__authenticationScheme;
357 // service->auth_realm = (*endpoint).whttp__authenticationRealm;
358 // collect service documentation
359 if ((*s).documentation)
360 service->service_documentation[(*service).name] = (*s).documentation;
361 if ((*endpoint).documentation && (*endpoint).name)
362 service->port_documentation[(*endpoint).name] = (*endpoint).documentation;
363 if (binding_documentation)
364 service->binding_documentation[binding_name] = binding_documentation;
365 // collect policies for the service and endpoints
366 if ((*endpoint).wsp__Policy_)
367 service->policy.push_back((*endpoint).wsp__Policy_);
368 if ((*endpoint).wsp__PolicyReference_ && (*endpoint).wsp__PolicyReference_->policyPtr())
369 service->policy.push_back((*endpoint).wsp__PolicyReference_->policyPtr());
370 }
371 }
372 }
373 Operation *op = new Operation();
374 op->name = types.aname(NULL, NULL, wsdl__operation_->name);
375 op->prefix = prefix;
376 op->URI = urienc(definitions.soap, URI);
377 op->style = soap__operation_style;
378 op->mep = soap__operation_mep;
379 if (soap__binding_transport
380 && (!strcmp(soap__binding_transport+strlen(soap__binding_transport)-4, "http")
381 || !strcmp(soap__binding_transport+strlen(soap__binding_transport)-5, "HTTP/")))
382 { if ((op->mep && strstr(op->mep, "soap-response"))
383 || (http_method && !strcmp(http_method, "GET")))
384 op->protocol = "SOAP-GET";
385 else if (version == 1)
386 op->protocol = "SOAP1.1";
387 else if (version == 2)
388 op->protocol = "SOAP1.2";
389 else
390 op->protocol = "SOAP";
391 }
392 else
393 { if (http_method)
394 op->protocol = http_method;
395 else
396 op->protocol = "HTTP";
397 }
398 op->documentation = wsdl__operation_->documentation;
399 op->operation_documentation = (*operation).documentation;
400 op->parameterOrder = wsdl__operation_->parameterOrder;
401 if (http__operation_location)
402 op->action = http__operation_location; // TODO: for now, store HTTP location in action
403 else
404 { op->action = soap__operation_action;
405 if ((*operation).soap__operation_)
406 { if ((*operation).soap__operation_->soapActionRequired)
407 op->action = (*operation).soap__operation_->soapAction;
408 }
409 else if (version != 2)
410 op->action = "";
411 }
412 if (operation_policy)
413 op->policy.push_back(operation_policy);
414 if (ext_operation_policy)
415 op->policy.push_back(ext_operation_policy);
416 op->input = new Message();
417 op->input->name = wsdl__operation_->name;
418 if (input_body && soap__operation_style == rpc && !input_body->namespace_)
419 { op->input->URI = "";
420 fprintf(stderr, "\nError: no soap:body namespace attribute\n");
421 }
422 else if (input_body)
423 op->input->URI = urienc(definitions.soap, input_body->namespace_);
424 else
425 op->input->URI = service->URI;
426 op->input->style = soap__operation_style;
427 if (input_body)
428 { op->input->use = input_body->use;
429 op->input->encodingStyle = input_body->encodingStyle;
430 }
431 if (input->wsa__Action)
432 op->input->action = input->wsa__Action;
433 else if (input->wsam__Action)
434 op->input->action = input->wsam__Action;
435 else if (op->action)
436 op->input->action = op->action;
437 else if (definitions.targetNamespace && (*binding).portTypePtr() && (*binding).portTypePtr()->name)
438 { const char *name = input->name ? input->name : op->name;
439 char *tmp = (char*)soap_malloc(definitions.soap, strlen(definitions.targetNamespace) + strlen((*binding).portTypePtr()->name) + strlen(name) + 3);
440 sprintf(tmp, "%s/%s/%s", definitions.targetNamespace, (*binding).portTypePtr()->name, name);
441 op->input->action = tmp;
442 }
443 op->input->message = input->messagePtr();
444 op->input->element = input->elementPtr();
445 op->input->part = NULL;
446 op->input->mustUnderstand = false;
447 op->input->multipartRelated = NULL;
448 op->input->content = input_mime_content;
449 op->input->body_parts = NULL;
450 op->input->layout = NULL;
451 op->input->ext_documentation = NULL;
452 if (ext_input)
453 { op->input->multipartRelated = ext_input->mime__multipartRelated_;
454 if (ext_input->mime__multipartRelated_ && !ext_input->mime__multipartRelated_->part.empty())
455 op->input->header = ext_input->mime__multipartRelated_->part.front().soap__header_;
456 else if (!ext_input->soap__header_.empty())
457 op->input->header = ext_input->soap__header_;
458 else if (!ext_input->wsoap__header_.empty())
459 op->input->wheader = ext_input->wsoap__header_;
460 if (ext_input->mime__multipartRelated_ && !ext_input->mime__multipartRelated_->part.empty() && ext_input->mime__multipartRelated_->part.front().soap__body_)
461 op->input->body_parts = ext_input->mime__multipartRelated_->part.front().soap__body_->parts;
462 else if (input_body)
463 op->input->body_parts = input_body->parts;
464 if (ext_input->dime__message_)
465 op->input->layout = ext_input->dime__message_->layout;
466 else
467 op->input->layout = NULL;
468 op->input->ext_documentation = ext_input->documentation;
469 }
470 op->input->documentation = input->documentation;
471 // collect input message policies
472 if (op->input->message)
473 { for (vector<wsp__Policy>::const_iterator p = op->input->message->wsp__Policy_.begin(); p != op->input->message->wsp__Policy_.end(); ++p)
474 op->input->policy.push_back(&(*p));
475 for (vector<wsp__PolicyReference>::const_iterator r = op->input->message->wsp__PolicyReference_.begin(); r != op->input->message->wsp__PolicyReference_.end(); ++r)
476 op->input->policy.push_back((*r).policyPtr());
477 }
478 if (input->wsp__Policy_)
479 op->input->policy.push_back(input->wsp__Policy_);
480 if (input->wsp__PolicyReference_ && input->wsp__PolicyReference_->policyPtr())
481 op->input->policy.push_back(input->wsp__PolicyReference_->policyPtr());
482 if (ext_input)
483 { if (ext_input->wsp__Policy_)
484 op->input->policy.push_back(ext_input->wsp__Policy_);
485 if (ext_input->wsp__PolicyReference_ && ext_input->wsp__PolicyReference_->policyPtr())
486 op->input->policy.push_back(ext_input->wsp__PolicyReference_->policyPtr());
487 }
488 if (soap__operation_style == document)
489 op->input_name = types.oname("__", op->URI, op->input->name);
490 else
491 op->input_name = types.oname(NULL, op->input->URI, op->input->name);
492 if (output)
493 { soap__body *output_body = NULL;
494 mime__mimeXml *output_mime = NULL;
495 mime__content *output_mime_content = NULL;
496 if (ext_output)
497 { output_body = ext_output->soap__body_;
498 output_mime = ext_output->mime__mimeXml_;
499 output_mime_content = ext_output->mime__content_;
500 if (ext_output->mime__multipartRelated_)
501 { for (vector<mime__part>::const_iterator part = ext_output->mime__multipartRelated_->part.begin(); part != ext_output->mime__multipartRelated_->part.end(); ++part)
502 if ((*part).soap__body_)
503 { output_body = (*part).soap__body_;
504 break;
505 }
506 }
507 }
508 if (ext_output && ext_output->mime__content_)
509 { op->output = new Message();
510 op->output->name = NULL;
511 op->output->URI = NULL;
512 op->output->style = soap__operation_style;
513 op->output->use = literal;
514 op->output->encodingStyle = NULL;
515 op->output->action = NULL;
516 op->output->body_parts = NULL;
517 op->output->part = NULL;
518 op->output->mustUnderstand = false;
519 op->output->multipartRelated = NULL;
520 op->output->content = output_mime_content;
521 op->output->message = output->messagePtr();
522 op->output->element = output->elementPtr();
523 op->output->layout = NULL;
524 }
525 else if (output_body || output_mime || output_mime_content || output->element)
526 { op->output = new Message();
527 op->output->name = wsdl__operation_->name; // RPC uses operation/@name with suffix 'Response' as set below
528 op->output->style = soap__operation_style;
529 if (output_body)
530 { op->output->use = output_body->use;
531 // the code below is a hack around the RPC encoded response message element tag mismatch with Axis:
532 if (!output_body->namespace_ || output_body->use == encoded)
533 op->output->URI = op->input->URI; // encoded seems (?) to require the request's namespace
534 else
535 op->output->URI = urienc(definitions.soap, output_body->namespace_);
536 op->output->encodingStyle = output_body->encodingStyle;
537 }
538 else
539 op->output->URI = service->URI;
540 if (output->wsa__Action)
541 op->output->action = output->wsa__Action;
542 else if (output->wsam__Action)
543 op->output->action = output->wsam__Action;
544 else if (http__operation_location)
545 op->output->action = NULL;
546 else if (op->action)
547 { const char *name = op->action;
548 char *tmp = (char*)soap_malloc(definitions.soap, strlen(name) + 9);
549 strcpy(tmp, name);
550 strcat(tmp, "Response");
551 op->output->action = tmp;
552 }
553 else if (definitions.targetNamespace && (*binding).portTypePtr() && (*binding).portTypePtr()->name)
554 { const char *name = output->name ? output->name : op->name;
555 char *tmp = (char*)soap_malloc(definitions.soap, strlen(definitions.targetNamespace) + strlen((*binding).portTypePtr()->name) + strlen(name) + 11);
556 sprintf(tmp, "%s/%s/%s%s", definitions.targetNamespace, (*binding).portTypePtr()->name, name, output->name ? "" : "Response");
557 op->output->action = tmp;
558 }
559 op->output->message = output->messagePtr();
560 op->output->element = output->elementPtr();
561 op->output->part = NULL;
562 op->output->content = output_mime_content;
563 op->output->body_parts = NULL;
564 op->output->layout = NULL;
565 op->output->ext_documentation = NULL;
566 op->output->mustUnderstand = false;
567 }
568 if (ext_output)
569 { op->output->multipartRelated = ext_output->mime__multipartRelated_;
570 if (ext_output->mime__multipartRelated_ && !ext_output->mime__multipartRelated_->part.empty())
571 op->output->header = ext_output->mime__multipartRelated_->part.front().soap__header_;
572 else if (!ext_output->soap__header_.empty())
573 op->output->header = ext_output->soap__header_;
574 else if (!ext_output->wsoap__header_.empty())
575 op->output->wheader = ext_output->wsoap__header_;
576 if (ext_output->mime__multipartRelated_ && !ext_output->mime__multipartRelated_->part.empty() && ext_output->mime__multipartRelated_->part.front().soap__body_)
577 op->output->body_parts = ext_output->mime__multipartRelated_->part.front().soap__body_->parts;
578 else if (output_body)
579 op->output->body_parts = output_body->parts;
580 if (ext_output->dime__message_)
581 op->output->layout = ext_output->dime__message_->layout;
582 else
583 op->output->layout = NULL;
584 op->output->ext_documentation = ext_output->documentation;
585 }
586 if (op->output->name)
587 { char *s = (char*)soap_malloc(definitions.soap, strlen(op->output->name) + 9);
588 strcpy(s, op->output->name);
589 strcat(s, "Response");
590 if (soap__operation_style == document)
591 op->output_name = types.oname("__", op->URI, s);
592 else
593 op->output_name = types.oname(NULL, op->output->URI, s);
594 }
595 op->output->documentation = output->documentation;
596 // collect output message policies
597 if (op->output->message)
598 { for (vector<wsp__Policy>::const_iterator p = op->output->message->wsp__Policy_.begin(); p != op->output->message->wsp__Policy_.end(); ++p)
599 op->output->policy.push_back(&(*p));
600 for (vector<wsp__PolicyReference>::const_iterator r = op->output->message->wsp__PolicyReference_.begin(); r != op->output->message->wsp__PolicyReference_.end(); ++r)
601 op->output->policy.push_back((*r).policyPtr());
602 }
603 if (output->wsp__Policy_)
604 op->output->policy.push_back(output->wsp__Policy_);
605 if (output->wsp__PolicyReference_ && output->wsp__PolicyReference_->policyPtr())
606 op->output->policy.push_back(output->wsp__PolicyReference_->policyPtr());
607 if (ext_output)
608 { if (ext_output->wsp__Policy_)
609 op->output->policy.push_back(ext_output->wsp__Policy_);
610 if (ext_output->wsp__PolicyReference_ && ext_output->wsp__PolicyReference_->policyPtr())
611 op->output->policy.push_back(ext_output->wsp__PolicyReference_->policyPtr());
612 }
613 }
614 else
615 { op->output_name = NULL;
616 op->output = NULL;
617 }
618 analyze_headers(definitions, service, ext_input, ext_output);
619 analyze_faults(definitions, service, op, operation);
620 service->operation.push_back(op);
621 }
622 else
623 { if (!Wflag)
624 fprintf(stderr, "\nWarning: no SOAP RPC operation namespace, operations will be ignored\n");
625 }
626 }
627 else
628 fprintf(stderr, "\nError: no wsdl:definitions/binding/operation/input\n");
629 }
630 else if (output)
631 { // This part is similar to the previous clause, limited to one-way output operations
632 soap__body *output_body = NULL;
633 mime__mimeXml *output_mime = NULL;
634 mime__content *output_mime_content = NULL;
635 if (!reversed && ext_output)
636 { output_body = ext_output->soap__body_;
637 output_mime = ext_output->mime__mimeXml_;
638 output_mime_content = ext_output->mime__content_;
639 if (ext_output->mime__multipartRelated_)
640 { for (vector<mime__part>::const_iterator part = ext_output->mime__multipartRelated_->part.begin(); part != ext_output->mime__multipartRelated_->part.end(); ++part)
641 if ((*part).soap__body_)
642 { output_body = (*part).soap__body_;
643 break;
644 }
645 }
646 }
647 else if (ext_input)
648 { output_body = ext_input->soap__body_;
649 output_mime = ext_input->mime__mimeXml_;
650 output_mime_content = ext_input->mime__content_;
651 if (ext_input->mime__multipartRelated_)
652 { for (vector<mime__part>::const_iterator part = ext_input->mime__multipartRelated_->part.begin(); part != ext_input->mime__multipartRelated_->part.end(); ++part)
653 if ((*part).soap__body_)
654 { output_body = (*part).soap__body_;
655 break;
656 }
657 }
658 }
659 if (wsdl__operation_->style && !strcmp(wsdl__operation_->style, "http://www.w3.org/ns/wsdl/style/iri"))
660 { output_mime_content = soap_new_mime__content(definitions.soap);
661 output_mime_content->soap_default(definitions.soap);
662 output_mime_content->type = (char*)"application/x-www-form-urlencoded";
663 }
664 if (output_body || output_mime || output_mime_content || output->element)
665 { char *URI;
666 if (output_body && soap__operation_style == rpc)
667 URI = output_body->namespace_;
668 else if (binding_count == 1 || !service_prefix)
669 URI = definitions.targetNamespace;
670 else
671 { // multiple service bidings are used, each needs a unique new URI
672 URI = (char*)soap_malloc(definitions.soap, strlen(definitions.targetNamespace) + strlen(binding_name) + 2);
673 strcpy(URI, definitions.targetNamespace);
674 if (*URI && URI[strlen(URI)-1] != '/')
675 strcat(URI, "/");
676 strcat(URI, binding_name);
677 }
678 if (URI)
679 { const char *prefix = types.nsprefix(service_prefix, URI);
680 const char *name = types.aname(NULL, NULL, binding_name); // name of service is binding name
681 Service *service = services[prefix];
682 if (!service)
683 { service = services[prefix] = new Service();
684 service->prefix = prefix;
685 service->URI = urienc(definitions.soap, URI);
686 service->name = name;
687 service->transport = soap__binding_transport;
688 if ((*binding).portTypePtr() && (*binding).portTypePtr()->name)
689 service->type = types.aname(NULL, NULL, (*binding).portTypePtr()->name);
690 else
691 service->type = NULL;
692 // collect faults (TODO: this is not used anywhere)
693 for (vector<wsdl__ext_fault>::const_iterator fault = (*binding).fault.begin(); fault != (*binding).fault.end(); ++fault)
694 { Message *f = analyze_fault(definitions, service, *fault);
695 if (f)
696 service->fault[f->name] = f;
697 }
698 // collect policies for the bindings
699 for (vector<wsp__Policy>::const_iterator p = (*binding).wsp__Policy_.begin(); p != (*binding).wsp__Policy_.end(); ++p)
700 service->policy.push_back(&(*p));
701 for (vector<wsp__PolicyReference>::const_iterator r = (*binding).wsp__PolicyReference_.begin(); r != (*binding).wsp__PolicyReference_.end(); ++r)
702 service->policy.push_back((*r).policyPtr());
703 // collect policies for the service endpoints
704 for (vector<wsdl__service>::const_iterator s = definitions.service.begin(); s != definitions.service.end(); ++s)
705 { for (vector<wsp__Policy>::const_iterator p = (*s).wsp__Policy_.begin(); p != (*s).wsp__Policy_.end(); ++p)
706 service->policy.push_back(&(*p));
707 for (vector<wsp__PolicyReference>::const_iterator r = (*s).wsp__PolicyReference_.begin(); r != (*s).wsp__PolicyReference_.end(); ++r)
708 service->policy.push_back((*r).policyPtr());
709 }
710 }
711 for (vector<wsdl__service>::const_iterator s = definitions.service.begin(); s != definitions.service.end(); ++s)
712 { for (vector<wsdl__port>::const_iterator port = (*s).port.begin(); port != (*s).port.end(); ++port)
713 { if ((*port).bindingPtr() == &(*binding))
714 { if ((*port).soap__address_ && (*port).soap__address_->location)
715 service->location.insert(urienc(definitions.soap, (*port).soap__address_->location));
716 else if ((*port).wsa__EndpointReference && (*port).wsa__EndpointReference->Address)
717 service->location.insert(urienc(definitions.soap, (*port).wsa__EndpointReference->Address));
718 // TODO: HTTP address for HTTP operations
719 // if ((*port).http__address_)
720 // http__address_location = http__address_->location;
721 // collect service documentation
722 if ((*s).documentation)
723 service->service_documentation[(*service).name] = (*s).documentation;
724 if ((*port).documentation && (*port).name)
725 service->port_documentation[(*port).name] = (*port).documentation;
726 if (binding_documentation)
727 service->binding_documentation[binding_name] = binding_documentation;
728 // collect policies for the service and endpoints
729 if ((*port).wsp__Policy_)
730 service->policy.push_back((*port).wsp__Policy_);
731 if ((*port).wsp__PolicyReference_ && (*port).wsp__PolicyReference_->policyPtr())
732 service->policy.push_back((*port).wsp__PolicyReference_->policyPtr());
733 }
734 }
735 }
736 Operation *op = new Operation();
737 op->input_name = NULL;
738 op->input = NULL;
739 op->name = types.aname(NULL, NULL, wsdl__operation_->name);
740 op->prefix = prefix;
741 op->URI = urienc(definitions.soap, URI);
742 op->style = soap__operation_style;
743 op->mep = soap__operation_mep;
744 if (soap__binding_transport
745 && (!strcmp(soap__binding_transport+strlen(soap__binding_transport)-4, "http")
746 || !strcmp(soap__binding_transport+strlen(soap__binding_transport)-5, "HTTP/")))
747 { if (op->mep && strstr(op->mep, "soap-response")
748 || (http_method && !strcmp(http_method, "GET")))
749 op->protocol = "SOAP-GET";
750 else if (version == 1)
751 op->protocol = "SOAP1.1";
752 else if (version == 2)
753 op->protocol = "SOAP1.2";
754 else
755 op->protocol = "SOAP";
756 }
757 else
758 { if (http_method)
759 op->protocol = http_method;
760 else
761 op->protocol = "HTTP";
762 }
763 op->documentation = wsdl__operation_->documentation;
764 op->operation_documentation = (*operation).documentation;
765 op->parameterOrder = wsdl__operation_->parameterOrder;
766 if (http__operation_location)
767 op->action = http__operation_location; // TODO: for now, store HTTP location in action
768 else
769 { op->action = soap__operation_action;
770 if ((*operation).soap__operation_)
771 { if ((*operation).soap__operation_->soapActionRequired)
772 op->action = (*operation).soap__operation_->soapAction;
773 }
774 else if (version != 2)
775 op->action = "";
776 }
777 if (operation_policy)
778 op->policy.push_back(operation_policy);
779 if (ext_operation_policy)
780 op->policy.push_back(ext_operation_policy);
781 op->output = new Message(); // one-way output operation
782 op->output->name = wsdl__operation_->name; // RPC uses operation/@name
783 if (output_body && soap__operation_style == rpc && !output_body->namespace_)
784 { op->output->URI = "";
785 fprintf(stderr, "\nError: no soap:body namespace attribute\n");
786 }
787 else if (output_body)
788 op->output->URI = urienc(definitions.soap, output_body->namespace_);
789 else
790 op->output->URI = service->URI;
791 op->output->style = soap__operation_style;
792 if (output_body)
793 { op->output->use = output_body->use;
794 op->output->encodingStyle = output_body->encodingStyle;
795 }
796 if (output->wsa__Action)
797 op->output->action = output->wsa__Action;
798 else if (output->wsam__Action)
799 op->output->action = output->wsam__Action;
800 else if (op->action)
801 op->output->action = op->action;
802 else if (definitions.targetNamespace && (*binding).portTypePtr() && (*binding).portTypePtr()->name)
803 { const char *name = output->name ? output->name : op->name;
804 char *tmp = (char*)soap_malloc(definitions.soap, strlen(definitions.targetNamespace) + strlen((*binding).portTypePtr()->name) + strlen(name) + 3);
805 sprintf(tmp, "%s/%s/%s", definitions.targetNamespace, (*binding).portTypePtr()->name, name);
806 op->output->action = tmp;
807 }
808 op->output->message = output->messagePtr();
809 op->output->element = output->elementPtr();
810 op->output->part = NULL;
811 op->output->mustUnderstand = false;
812 op->output->multipartRelated = NULL;
813 op->output->content = output_mime_content;
814 op->output->body_parts = NULL;
815 op->output->layout = NULL;
816 op->output->ext_documentation = NULL;
817 if (ext_output)
818 { op->output->multipartRelated = ext_output->mime__multipartRelated_;
819 if (ext_output->mime__multipartRelated_ && !ext_output->mime__multipartRelated_->part.empty())
820 op->output->header = ext_output->mime__multipartRelated_->part.front().soap__header_;
821 else if (!ext_output->soap__header_.empty())
822 op->output->header = ext_output->soap__header_;
823 else if (!ext_output->wsoap__header_.empty())
824 op->output->wheader = ext_output->wsoap__header_;
825 if (ext_output->mime__multipartRelated_ && !ext_output->mime__multipartRelated_->part.empty() && ext_output->mime__multipartRelated_->part.front().soap__body_)
826 op->output->body_parts = ext_output->mime__multipartRelated_->part.front().soap__body_->parts;
827 else if (output_body)
828 op->output->body_parts = output_body->parts;
829 if (ext_output->dime__message_)
830 op->output->layout = ext_output->dime__message_->layout;
831 else
832 op->output->layout = NULL;
833 op->output->ext_documentation = ext_output->documentation;
834 }
835 op->output->documentation = output->documentation;
836 // collect output message policies
837 if (op->output->message)
838 { for (vector<wsp__Policy>::const_iterator p = op->output->message->wsp__Policy_.begin(); p != op->output->message->wsp__Policy_.end(); ++p)
839 op->output->policy.push_back(&(*p));
840 for (vector<wsp__PolicyReference>::const_iterator r = op->output->message->wsp__PolicyReference_.begin(); r != op->output->message->wsp__PolicyReference_.end(); ++r)
841 op->output->policy.push_back((*r).policyPtr());
842 }
843 if (output->wsp__Policy_)
844 op->output->policy.push_back(output->wsp__Policy_);
845 if (output->wsp__PolicyReference_ && output->wsp__PolicyReference_->policyPtr())
846 op->output->policy.push_back(output->wsp__PolicyReference_->policyPtr());
847 if (ext_output)
848 { if (ext_output->wsp__Policy_)
849 op->output->policy.push_back(ext_output->wsp__Policy_);
850 if (ext_output->wsp__PolicyReference_ && ext_output->wsp__PolicyReference_->policyPtr())
851 op->output->policy.push_back(ext_output->wsp__PolicyReference_->policyPtr());
852 }
853 if (soap__operation_style == document)
854 op->input_name = types.oname("__", op->URI, op->output->name);
855 else
856 op->input_name = types.oname(NULL, op->output->URI, op->output->name);
857 char *s = (char*)soap_malloc(definitions.soap, strlen(op->output->name) + 9);
858 strcpy(s, op->output->name);
859 strcat(s, "Response");
860 if (soap__operation_style == document)
861 op->output_name = types.oname("__", op->URI, s);
862 else
863 op->output_name = types.oname(NULL, op->output->URI, s);
864 analyze_headers(definitions, service, ext_input, ext_output);
865 analyze_faults(definitions, service, op, operation);
866 service->operation.push_back(op);
867 }
868 else
869 { if (!Wflag)
870 fprintf(stderr, "\nWarning: no SOAP RPC operation namespace, operations will be ignored\n");
871 }
872 }
873 else
874 fprintf(stderr, "\nError: no wsdl:definitions/binding/operation/output\n");
875 }
876 else
877 fprintf(stderr, "\nError: no wsdl:definitions/portType/operation/input and output\n");
878 }
879 else
880 fprintf(stderr, "\nError: no wsdl:definitions/portType/operation\n");
881 }
882 }
883 }
884
885 void Definitions::analyze_headers(const wsdl__definitions &definitions, Service *service, wsdl__ext_ioput *ext_input, wsdl__ext_ioput *ext_output)
886 { // collect input headers and headerfaults
887 if (ext_input)
888 { const vector<soap__header> *soap__header_ = NULL;
889 // check if soap header is in mime:multipartRelated
890 if (ext_input->mime__multipartRelated_)
891 { for (vector<mime__part>::const_iterator part = ext_input->mime__multipartRelated_->part.begin(); part != ext_input->mime__multipartRelated_->part.end(); ++part)
892 if (!(*part).soap__header_.empty())
893 { soap__header_ = &(*part).soap__header_;
894 break;
895 }
896 }
897 if (!soap__header_)
898 soap__header_ = &ext_input->soap__header_;
899 for (vector<soap__header>::const_iterator header = soap__header_->begin(); header != soap__header_->end(); ++header)
900 { Message *h = new Message();
901 h->message = (*header).messagePtr();
902 h->element = NULL;
903 h->body_parts = NULL;
904 h->part = (*header).partPtr();
905 h->URI = urienc(definitions.soap, (*header).namespace_);
906 if (h->part && h->part->element)
907 h->name = types.aname(NULL, NULL, h->part->element);
908 else if (h->URI && h->part && h->part->name && h->part->type)
909 h->name = types.aname(NULL, h->URI, h->part->name);
910 else
911 { fprintf(stderr, "\nError in SOAP Header part definition: input part '%s' missing?\n", h->part && h->part->name ? h->part->name : "?");
912 h->name = "";
913 }
914 h->encodingStyle = (*header).encodingStyle;
915 h->style = document; // irrelevant
916 h->use = (*header).use;
917 h->mustUnderstand = true;
918 h->multipartRelated = NULL;
919 h->content = NULL;
920 h->layout = NULL;
921 h->ext_documentation = NULL; // TODO: add document content
922 h->documentation = NULL; // TODO: add document content
923 service->header[h->name] = h;
924 for (vector<soap__headerfault>::const_iterator headerfault = (*header).headerfault.begin(); headerfault != (*header).headerfault.end(); ++headerfault)
925 { // TODO: headerfault processing. This is practically never used...
926 }
927 }
928 for (vector<wsoap__header>::const_iterator wheader = ext_input->wsoap__header_.begin(); wheader != ext_input->wsoap__header_.end(); ++wheader)
929 { Message *h = new Message();
930 h->message = NULL;
931 h->element = (*wheader).elementPtr();
932 h->body_parts = NULL;
933 h->part = NULL;
934 h->URI = NULL;
935 h->mustUnderstand = (*wheader).mustUnderstand_;
936 h->name = types.aname(NULL, NULL, (*wheader).element);
937 h->encodingStyle = NULL;
938 h->style = document; // irrelevant
939 h->use = literal;
940 h->multipartRelated = NULL;
941 h->content = NULL;
942 h->layout = NULL;
943 h->ext_documentation = NULL; // TODO: add document content
944 h->documentation = NULL; // TODO: add document content
945 service->header[h->name] = h;
946 }
947 }
948 // collect output headers and headerfaults
949 if (ext_output)
950 { const vector<soap__header> *soap__header_ = NULL;
951 // check if soap header is in mime:multipartRelated
952 if (ext_output->mime__multipartRelated_)
953 { for (vector<mime__part>::const_iterator part = ext_output->mime__multipartRelated_->part.begin(); part != ext_output->mime__multipartRelated_->part.end(); ++part)
954 if (!(*part).soap__header_.empty())
955 { soap__header_ = &(*part).soap__header_;
956 break;
957 }
958 }
959 if (!soap__header_)
960 soap__header_ = &ext_output->soap__header_;
961 for (vector<soap__header>::const_iterator header = soap__header_->begin(); header != soap__header_->end(); ++header)
962 { Message *h = new Message();
963 h->message = (*header).messagePtr();
964 h->element = NULL;
965 h->body_parts = NULL;
966 h->part = (*header).partPtr();
967 h->URI = urienc(definitions.soap, (*header).namespace_);
968 if (h->part && h->part->element)
969 h->name = types.aname(NULL, NULL, h->part->element);
970 else if (h->URI && h->part && h->part->name && h->part->type)
971 h->name = types.aname(NULL, h->URI, h->part->name);
972 else
973 { fprintf(stderr, "\nError in SOAP Header part definition: output part '%s' missing?\n", h->part && h->part->name ? h->part->name : "?");
974 h->name = "";
975 }
976 h->encodingStyle = (*header).encodingStyle;
977 h->style = document; // irrelevant
978 h->use = (*header).use;
979 h->mustUnderstand = false;
980 h->multipartRelated = NULL;
981 h->content = NULL;
982 h->layout = NULL;
983 h->ext_documentation = NULL; // TODO: add document content?
984 h->documentation = NULL; // TODO: add document content?
985 service->header[h->name] = h;
986 for (vector<soap__headerfault>::const_iterator headerfault = (*header).headerfault.begin(); headerfault != (*header).headerfault.end(); ++headerfault)
987 { // TODO: headerfault processing. This is practically never used...
988 }
989 }
990 for (vector<wsoap__header>::const_iterator wheader = ext_output->wsoap__header_.begin(); wheader != ext_output->wsoap__header_.end(); ++wheader)
991 { Message *h = new Message();
992 h->message = NULL;
993 h->element = (*wheader).elementPtr();
994 h->body_parts = NULL;
995 h->part = NULL;
996 h->URI = NULL;
997 h->mustUnderstand = (*wheader).mustUnderstand_;
998 h->name = types.aname(NULL, NULL, (*wheader).element);
999 h->encodingStyle = NULL;
1000 h->style = document; // irrelevant
1001 h->use = literal;
1002 h->multipartRelated = NULL;
1003 h->content = NULL;
1004 h->layout = NULL;
1005 h->ext_documentation = NULL; // TODO: add document content
1006 h->documentation = NULL; // TODO: add document content
1007 service->header[h->name] = h;
1008 }
1009 }
1010 }
1011
1012 void Definitions::analyze_faults(const wsdl__definitions &definitions, Service *service, Operation *op, vector<wsdl__ext_operation>::const_iterator& operation)
1013 { for (vector<wsdl__ext_fault>::const_iterator fault = (*operation).fault.begin(); fault != (*operation).fault.end(); ++fault)
1014 { Message *f = analyze_fault(definitions, service, *fault);
1015 if (f)
1016 { op->outfault.push_back(f);
1017 service->fault[f->name] = f;
1018 }
1019 }
1020 for (vector<wsdl__ext_fault>::const_iterator infault = (*operation).infault.begin(); infault != (*operation).infault.end(); ++infault)
1021 { Message *f = analyze_fault(definitions, service, *infault);
1022 if (f)
1023 { op->infault.push_back(f);
1024 service->fault[f->name] = f;
1025 }
1026 }
1027 for (vector<wsdl__ext_fault>::const_iterator outfault = (*operation).outfault.begin(); outfault != (*operation).outfault.end(); ++outfault)
1028 { Message *f = analyze_fault(definitions, service, *outfault);
1029 if (f)
1030 { op->outfault.push_back(f);
1031 service->fault[f->name] = f;
1032 }
1033 }
1034 }
1035
1036 Message *Definitions::analyze_fault(const wsdl__definitions &definitions, Service *service, const wsdl__ext_fault &ext_fault)
1037 { Message *f = NULL;
1038 const wsdl__fault *fault = ext_fault.faultPtr();
1039 if (fault && (fault->messagePtr() || fault->elementPtr()))
1040 { f = new Message();
1041 f->message = fault->messagePtr();
1042 f->element = fault->elementPtr();
1043 f->body_parts = NULL;
1044 f->part = NULL;
1045 f->encodingStyle = NULL;
1046 if (ext_fault.soap__fault_)
1047 f->encodingStyle = ext_fault.soap__fault_->encodingStyle;
1048 f->action = NULL;
1049 if (fault->wsa__Action)
1050 f->action = fault->wsa__Action;
1051 else
1052 f->action = fault->wsam__Action;
1053 if (ext_fault.soap__fault_)
1054 f->URI = ext_fault.soap__fault_->namespace_;
1055 else if (f->element && f->element->schemaPtr())
1056 f->URI = f->element->schemaPtr()->targetNamespace;
1057 else
1058 f->URI = service->URI; // must have a unique URI
1059 f->style = document; // irrelevant
1060 f->use = literal;
1061 if (ext_fault.soap__fault_)
1062 f->use = ext_fault.soap__fault_->use;
1063 if (ext_fault.wsoap__code)
1064 { char *s = (char*)soap_malloc(definitions.soap, 80 + strlen(ext_fault.wsoap__code) + (ext_fault.wsoap__subcodes ? strlen(ext_fault.wsoap__subcodes) : 0));
1065 sprintf(s, "\"%s\" with subcodes \"%s\"", ext_fault.wsoap__code, ext_fault.wsoap__subcodes ? ext_fault.wsoap__subcodes : "");
1066 f->body_parts = s;
1067 }
1068 else
1069 f->ext_documentation = ext_fault.documentation;
1070 f->mustUnderstand = false;
1071 f->multipartRelated = NULL;
1072 f->content = NULL;
1073 f->layout = NULL;
1074 if (f->message)
1075 { f->name = types.aname("_", f->URI, f->message->name);
1076 f->documentation = f->message->documentation;
1077 }
1078 else
1079 { f->name = types.aname(NULL, f->URI, fault->element);
1080 f->documentation = fault->documentation;
1081 }
1082 // collect fault message policies
1083 if (fault->wsp__Policy_)
1084 f->policy.push_back(fault->wsp__Policy_);
1085 if (fault->wsp__PolicyReference_ && fault->wsp__PolicyReference_->policyPtr())
1086 f->policy.push_back(fault->wsp__PolicyReference_->policyPtr());
1087 if (ext_fault.wsp__Policy_)
1088 f->policy.push_back(ext_fault.wsp__Policy_);
1089 if (ext_fault.wsp__PolicyReference_ && ext_fault.wsp__PolicyReference_->policyPtr())
1090 f->policy.push_back(ext_fault.wsp__PolicyReference_->policyPtr());
1091 }
1092 else if (ext_fault.soap__fault_ && ext_fault.soap__fault_->name)
1093 fprintf(stderr, "\nError: no wsdl:definitions/binding/operation/fault/soap:fault '%s'\n", ext_fault.soap__fault_->name);
1094 else
1095 fprintf(stderr, "\nError: no wsdl:definitions/binding/operation/fault/soap:fault\n");
1096 return f;
1097 }
1098
1099 void Definitions::compile(const wsdl__definitions& definitions)
1100 { // compile the definitions and generate gSOAP header file
1101 const char *defs;
1102 if (definitions.name)
1103 defs = types.aname(NULL, NULL, definitions.name);
1104 else
1105 defs = "Service";
1106 ident();
1107 fprintf(stream, "/** @page page_notes Usage Notes\n\nNOTE:\n\n - Run soapcpp2 on %s to generate the SOAP/XML processing logic.\n Use soapcpp2 -I to specify paths for #import\n To build with STL, 'stlvector.h' is imported from 'import' dir in package.\n Use soapcpp2 -j to generate improved proxy and server classes.\n - Use wsdl2h -c and -s to generate pure C code or C++ code without STL.\n - Use 'typemap.dat' to control namespace bindings and type mappings.\n It is strongly recommended to customize the names of the namespace prefixes\n generated by wsdl2h. To do so, modify the prefix bindings in the Namespaces\n section below and add the modified lines to 'typemap.dat' to rerun wsdl2h.\n - Use Doxygen (www.doxygen.org) on this file to generate documentation.\n - Use wsdl2h -R to generate REST operations.\n - Use wsdl2h -nname to use name as the base namespace prefix instead of 'ns'.\n - Use wsdl2h -Nname for service prefix and produce multiple service bindings\n - Use wsdl2h -d to enable DOM support for xsd:anyType.\n - Use wsdl2h -g to auto-generate readers and writers for root elements.\n - Use wsdl2h -b to auto-generate bi-directional operations (duplex ops).\n - Struct/class members serialized as XML attributes are annotated with a '@'.\n - Struct/class members that have a special role are annotated with a '$'.\n\nWARNING:\n\n DO NOT INCLUDE THIS ANNOTATED FILE DIRECTLY IN YOUR PROJECT SOURCE CODE.\n USE THE FILES GENERATED BY soapcpp2 FOR YOUR PROJECT'S SOURCE CODE:\n THE soapStub.h FILE CONTAINS THIS CONTENT WITHOUT ANNOTATIONS.\n\n", outfile?outfile:"this file");
1108 fprintf(stream, "LICENSE:\n\n@verbatim\n%s@endverbatim\n\n*/\n\n", licensenotice);
1109 // gsoap compiler options: 'w' disables WSDL/schema output to avoid file collisions
1110 if (cflag)
1111 fprintf(stream, "\n//gsoapopt cw\n");
1112 else
1113 fprintf(stream, "\n//gsoapopt w\n");
1114 banner("Definitions", definitions.targetNamespace?definitions.targetNamespace:"targetNamespace");
1115 // copy documentation from WSDL definitions
1116 if (definitions.documentation)
1117 { fprintf(stream, "/* WSDL Documentation:\n\n");
1118 text(definitions.documentation);
1119 fprintf(stream, "*/\n\n");
1120 }
1121 if (definitions.version)
1122 { banner("Version", definitions.version);
1123 fprintf(stream, "#define SOAP_WSDL_VERSION \"%s\"\n", definitions.version);
1124 }
1125 banner("Import");
1126 if (dflag)
1127 { fprintf(stream, "\n// dom.h declares the DOM xsd__anyType object (compiler and link with dom.cpp)\n");
1128 fprintf(stream, "#import \"dom.h\"\n");
1129 }
1130 if (!cflag && !sflag)
1131 { fprintf(stream, "\n// STL vector containers (use option -s to remove STL dependency)\n");
1132 fprintf(stream, "#import \"stlvector.h\"\n");
1133 }
1134 if (mflag)
1135 { fprintf(stream, "#import \"");
1136 fprintf(stream, "xsd.h\"\t// import primitive XSD types.\n");
1137 }
1138 for (SetOfString::const_iterator u = exturis.begin(); u != exturis.end(); ++u)
1139 { bool found = false;
1140 size_t n = strlen(*u);
1141 for (SetOfString::const_iterator i = definitions.builtinTypes().begin(); i != definitions.builtinTypes().end(); ++i)
1142 { if (**i == '"' && !strncmp(*u, *i + 1, n) && (*i)[n+1] == '"')
1143 { found = true;
1144 break;
1145 }
1146 }
1147 if (!found)
1148 { for (SetOfString::const_iterator j = definitions.builtinElements().begin(); j != definitions.builtinElements().end(); ++j)
1149 { if (**j == '"' && !strncmp(*u, *j + 1, n) && (*j)[n+1] == '"')
1150 { found = true;
1151 break;
1152 }
1153 }
1154 }
1155 if (!found)
1156 { for (SetOfString::const_iterator k = definitions.builtinAttributes().begin(); k != definitions.builtinAttributes().end(); ++k)
1157 { if (**k == '"' && !strncmp(*u, *k + 1, n) && (*k)[n+1] == '"')
1158 { found = true;
1159 break;
1160 }
1161 }
1162 }
1163 if (found)
1164 { if (vflag)
1165 fprintf(stderr, "import %s\n", *u);
1166 fprintf(stream, "#import \"%s.h\"\t// %s = <%s>\n", types.nsprefix(NULL, *u), types.nsprefix(NULL, *u), *u);
1167 }
1168 }
1169 banner("Schema Namespaces");
1170 // Determine if bindings use SOAP 1.2
1171 soap12 = false;
1172 for (Namespace *p = definitions.soap->local_namespaces; p && p->id; p++)
1173 { if (p->out && !strcmp(p->id, "soap") && !strcmp(p->out, "http://schemas.xmlsoap.org/wsdl/soap12/"))
1174 { soap12 = true;
1175 break;
1176 }
1177 }
1178 if (definitions.types)
1179 { fprintf(stream, "\n/* NOTE:\n\nIt is strongly recommended to customize the names of the namespace prefixes\ngenerated by wsdl2h. To do so, modify the prefix bindings below and add the\nmodified lines to typemap.dat to rerun wsdl2h:\n\n");
1180 if (definitions.targetNamespace && *definitions.targetNamespace)
1181 fprintf(stream, "%s = \"%s\"\n", types.nsprefix(service_prefix, definitions.targetNamespace), definitions.targetNamespace);
1182 for (vector<xs__schema*>::const_iterator schema1 = definitions.types->xs__schema_.begin(); schema1 != definitions.types->xs__schema_.end(); ++schema1)
1183 if (!definitions.targetNamespace || strcmp((*schema1)->targetNamespace, definitions.targetNamespace))
1184 fprintf(stream, "%s = \"%s\"\n", types.nsprefix(NULL, (*schema1)->targetNamespace), (*schema1)->targetNamespace);
1185 fprintf(stream, "\n*/\n");
1186 for (vector<xs__schema*>::const_iterator schema2 = definitions.types->xs__schema_.begin(); schema2 != definitions.types->xs__schema_.end(); ++schema2)
1187 { const char *t = types.nsprefix(NULL, (*schema2)->targetNamespace);
1188 fprintf(stream, "\n");
1189 types.document((*schema2)->annotation);
1190 fprintf(stream, "#define SOAP_NAMESPACE_OF_%s\t\"%s\"\n", types.aname(NULL, NULL, t), urienc(definitions.soap, (*schema2)->targetNamespace));
1191 fprintf(stream, schemaformat, t, "namespace", urienc(definitions.soap, (*schema2)->targetNamespace));
1192 if ((*schema2)->elementFormDefault == (*schema2)->attributeFormDefault)
1193 fprintf(stream, schemaformat, types.nsprefix(NULL, (*schema2)->targetNamespace), "form", (*schema2)->elementFormDefault == qualified ? "qualified" : "unqualified");
1194 else
1195 { fprintf(stream, schemaformat, types.nsprefix(NULL, (*schema2)->targetNamespace), "elementForm", (*schema2)->elementFormDefault == qualified ? "qualified" : "unqualified");
1196 fprintf(stream, schemaformat, types.nsprefix(NULL, (*schema2)->targetNamespace), "attributeForm", (*schema2)->attributeFormDefault == qualified ? "qualified" : "unqualified");
1197 }
1198 }
1199 }
1200 // generate the prototypes first: these should allow use before def, e.g. class names then generate the defs
1201 // check if xsd:anyType is used
1202 if (!cflag && !pflag)
1203 { for (SetOfString::const_iterator i = definitions.builtinTypes().begin(); i != definitions.builtinTypes().end(); ++i)
1204 { if (!cflag && !strcmp(*i, "xs:anyType"))
1205 { pflag = 1;
1206 break;
1207 }
1208 }
1209 }
1210 if (dflag && pflag && !Pflag)
1211 { if (!Wflag)
1212 fprintf(stderr, "\nWarning -d option: -p option disabled and xsd__anyType base class removed.\nUse run-time SOAP_DOM_NODE flag to deserialize class instances into DOM nodes.\n");
1213 fprintf(stream, "\n/*\nWarning -d option used: -p option disabled and xsd:anyType base class removed.\nUse run-time SOAP_DOM_NODE flag to deserialize class instances into DOM nodes.\nA DOM node is represented by the xsd__anyType object implemented in dom.cpp.\n*/\n\n");
1214 pflag = 0;
1215 }
1216 // define xsd:anyType first, if used
1217 if (!cflag && pflag)
1218 { const char *s, *t;
1219 t = types.cname(NULL, NULL, "xs:anyType");
1220 s = types.deftypemap[t];
1221 if (s)
1222 { if (*s)
1223 { if (!mflag)
1224 fprintf(stream, "%s\n", s);
1225 }
1226 s = types.usetypemap[t];
1227 if (s)
1228 { if (mflag)
1229 fprintf(stream, "// xsd.h: should define type %s\n", s);
1230 types.knames.insert(s);
1231 }
1232 }
1233 else
1234 { fprintf(stderr, "\nError: no xsd__anyType defined in type map\n");
1235 pflag = 0;
1236 }
1237 }
1238 if (Pflag)
1239 pflag = 0;
1240 // produce built-in primitive types, limited to the ones that are used only
1241 banner("Built-in Schema Types and Top-Level Elements and Attributes");
1242 if (vflag)
1243 fprintf(stderr, "\nGenerating built-in types\n");
1244 for (SetOfString::const_iterator i = definitions.builtinTypes().begin(); i != definitions.builtinTypes().end(); ++i)
1245 { const char *s, *t;
1246 if (!cflag && !strcmp(*i, "xs:anyType"))
1247 continue;
1248 t = types.cname(NULL, NULL, *i);
1249 s = types.deftypemap[t];
1250 if (s)
1251 { if (*s)
1252 { if (**i == '"')
1253 fprintf(stream, "\n/// Imported type %s from typemap %s.\n", *i, mapfile?mapfile:"");
1254 else
1255 fprintf(stream, "\n/// Built-in type \"%s\".\n", *i);
1256 if (mflag)
1257 fprintf(stream, "// (declaration of %s removed by option -m)\n", t);
1258 else if (!iflag && !imported(*i))
1259 types.format(s);
1260 }
1261 s = types.usetypemap[t];
1262 if (s && *s)
1263 { if (mflag && **i != '"')
1264 fprintf(stream, "\n// xsd.h: typemap override of type %s with %s\n", t, s);
1265 if (types.knames.find(s) == types.knames.end())
1266 types.knames.insert(s);
1267 }
1268 }
1269 }
1270 for (SetOfString::const_iterator i = definitions.builtinTypes().begin(); i != definitions.builtinTypes().end(); ++i)
1271 { const char *s, *t;
1272 if (!cflag && !strcmp(*i, "xs:anyType"))
1273 continue;
1274 t = types.cname(NULL, NULL, *i);
1275 s = types.deftypemap[t];
1276 if (!s)
1277 { if (!mflag)
1278 { if (**i == '"')
1279 fprintf(stream, "\n// Imported type %s defined by %s\n", *i, t);
1280 else if (!iflag)
1281 { s = types.tname(NULL, NULL, "xsd:string");
1282 fprintf(stream, "\n/// Primitive built-in type \"%s\"\n", *i);
1283 fprintf(stream, "typedef %s %s;\n", s, t);
1284 types.deftname(TYPEDEF, NULL, strchr(s, '*') != NULL, NULL, NULL, *i);
1285 const char *u = types.uri(*i);
1286 if (u && !types.uris[u])
1287 fprintf(stream, schemaformat, types.nsprefix(types.prefix(*i), u), "namespace", u);
1288 }
1289 }
1290 else if (**i == '"')
1291 fprintf(stream, "\n// Imported type %s defined by %s\n", *i, t);
1292 else
1293 fprintf(stream, "\n// xsd.h: should define type %s\n", t);
1294 types.deftname(TYPEDEF, NULL, false, NULL, NULL, *i);
1295 }
1296 if (pflag && !strncmp(*i, "xs:", 3)) // only xsi types are polymorph
1297 { s = types.aname(NULL, NULL, *i);
1298 if (!mflag)
1299 { fprintf(stream, "\n/// Class wrapper for built-in type \"%s\" derived from xsd__anyType\n/// Use virtual method soap_type() == SOAP_TYPE_%s to check runtime type (see soapStub.h)\n", *i, s);
1300 fprintf(stream, "class %s : public xsd__anyType\n{ public:\n", s);
1301 fprintf(stream, elementformat, types.tname(NULL, NULL, *i), "__item;");
1302 fprintf(stream, "\n};\n");
1303 }
1304 types.knames.insert(s);
1305 }
1306 }
1307 // produce built-in primitive elements, limited to the ones that are used only
1308 if (vflag)
1309 fprintf(stderr, "\nGenerating built-in elements\n");
1310 for (SetOfString::const_iterator j = definitions.builtinElements().begin(); j != definitions.builtinElements().end(); ++j)
1311 { const char *s, *t;
1312 t = types.cname("_", NULL, *j);
1313 s = types.deftypemap[t];
1314 if (s)
1315 { if (*s)
1316 { if (**j == '"')
1317 fprintf(stream, "\n/// Imported element %s from typemap %s.\n", *j, mapfile?mapfile:"");
1318 else
1319 fprintf(stream, "\n/// Built-in element \"%s\".\n", *j);
1320 if (mflag)
1321 fprintf(stream, "// (declaration of %s removed by option -m)\n", t);
1322 else if (!iflag && !imported(*j))
1323 types.format(s);
1324 }
1325 s = types.usetypemap[t];
1326 if (s && *s)
1327 { if (mflag && **j != '"')
1328 fprintf(stream, "\n// xsd.h: typemap override of element %s with %s\n", t, s);
1329 if (types.knames.find(s) == types.knames.end())
1330 types.knames.insert(s);
1331 }
1332 }
1333 else
1334 { if (!mflag)
1335 { if (**j == '"')
1336 fprintf(stream, "\n// Imported element %s declared as %s\n", *j, t);
1337 else if (!iflag && !imported(*j))
1338 { s = types.tname(NULL, NULL, "xsd:any");
1339 fprintf(stream, "\n/// Built-in element \"%s\".\n", *j);
1340 fprintf(stream, "typedef %s %s;\n", s, t);
1341 types.deftname(TYPEDEF, NULL, true, "_", NULL, *j); // already pointer
1342 const char *u = types.uri(*j);
1343 if (u && !types.uris[u])
1344 fprintf(stream, schemaformat, types.nsprefix(types.prefix(*j), u), "namespace", u);
1345 }
1346 }
1347 else if (**j == '"')
1348 fprintf(stream, "\n// Imported element %s declared as %s\n", *j, t);
1349 else
1350 fprintf(stream, "\n// xsd.h: should define element %s\n", t);
1351 types.deftname(TYPEDEF, NULL, false, "_", NULL, *j);
1352 }
1353 }
1354 // produce built-in primitive attributes, limited to the ones that are used only
1355 if (vflag)
1356 fprintf(stderr, "\nGenerating built-in attributes\n");
1357 for (SetOfString::const_iterator k = definitions.builtinAttributes().begin(); k != definitions.builtinAttributes().end(); ++k)
1358 { const char *s, *t;
1359 t = types.cname("_", NULL, *k);
1360 s = types.deftypemap[t];
1361 if (s)
1362 { if (*s)
1363 { if (**k == '"')
1364 fprintf(stream, "\n/// Imported attribute %s from typemap %s.\n", *k, mapfile?mapfile:"");
1365 else
1366 fprintf(stream, "\n/// Built-in attribute \"%s\".\n", *k);
1367 if (mflag)
1368 fprintf(stream, "// (declaration of %s removed by option -m)\n", t);
1369 else if (!iflag && !imported(*k))
1370 types.format(s);
1371 }
1372 s = types.usetypemap[t];
1373 if (s && *s)
1374 { if (mflag && **k != '"')
1375 fprintf(stream, "\n// xsd.h: typemap override of attribute %s with %s\n", t, s);
1376 if (types.knames.find(s) == types.knames.end())
1377 types.knames.insert(s);
1378 }
1379 }
1380 else
1381 { s = types.tname(NULL, NULL, "xsd:string");
1382 if (!mflag)
1383 { if (**k == '"')
1384 fprintf(stream, "\n// Imported attribute %s declared as %s\n", *k, t);
1385 else if (!iflag && !imported(*k))
1386 { fprintf(stream, "\n/// Built-in attribute \"%s\".\n", *k);
1387 fprintf(stream, "typedef %s %s;\n", s, t);
1388 const char *u = types.uri(*k);
1389 if (u && !types.uris[u])
1390 fprintf(stream, schemaformat, types.nsprefix(types.prefix(*k), u), "namespace", u);
1391 }
1392 }
1393 else if (**k == '"')
1394 fprintf(stream, "// Imported attribute %s declared as %s\n", *k, t);
1395 else
1396 fprintf(stream, "// xsd.h: should define attribute %s\n", t);
1397 types.deftname(TYPEDEF, NULL, strchr(s, '*') != NULL, "_", NULL, *k);
1398 }
1399 }
1400 // produce types
1401 // define class/struct types first
1402 if (!cflag)
1403 banner("Forward Declarations");
1404 if (definitions.types)
1405 { comment("Definitions", defs, "types", definitions.types->documentation);
1406 fprintf(stream, "\n");
1407 for (vector<xs__schema*>::const_iterator schema4 = definitions.types->xs__schema_.begin(); schema4 != definitions.types->xs__schema_.end(); ++schema4)
1408 { if (vflag)
1409 fprintf(stderr, "\nDefining types in %s\n", (*schema4)->targetNamespace);
1410 for (vector<xs__complexType>::const_iterator complexType = (*schema4)->complexType.begin(); complexType != (*schema4)->complexType.end(); ++complexType)
1411 types.define((*schema4)->targetNamespace, NULL, *complexType);
1412 if (vflag)
1413 fprintf(stderr, "\nDefining elements in %s\n", (*schema4)->targetNamespace);
1414 for (vector<xs__element>::const_iterator element = (*schema4)->element.begin(); element != (*schema4)->element.end(); ++element)
1415 { if (!(*element).type && !(*element).abstract)
1416 { if ((*element).complexTypePtr())
1417 types.define((*schema4)->targetNamespace, (*element).name, *(*element).complexTypePtr());
1418 else if (!(*element).simpleTypePtr())
1419 { fprintf(stream, "\n/// Top-level root element \"%s\":%s.\n", (*schema4)->targetNamespace, (*element).name);
1420 if (gflag)
1421 { const char *t = types.deftname(TYPEDEF, NULL, false, "_", (*schema4)->targetNamespace, (*element).name);
1422 if (t)
1423 fprintf(stream, "typedef _XML %s;\n", t);
1424 else
1425 fprintf(stream, "// Element definition intentionally left blank.\n");
1426 }
1427 else
1428 { const char *s = types.cname("_", (*schema4)->targetNamespace, (*element).name);
1429 types.ptrtypemap[s] = types.usetypemap[s] = "_XML";
1430 fprintf(stream, "/// Note: use wsdl2h option -g to auto-generate a top-level root element declaration and processing code.\n");
1431 }
1432 }
1433 }
1434 }
1435 }
1436 // visit types with lowest base level first
1437 int baseLevel = 1;
1438 bool found;
1439 do
1440 { found = (baseLevel == 1);
1441 for (vector<xs__schema*>::iterator schema = definitions.types->xs__schema_.begin(); schema != definitions.types->xs__schema_.end(); ++schema)
1442 { if (found)
1443 banner("Schema Types and Top-Level Elements and Attributes", (*schema)->targetNamespace);
1444 for (vector<xs__simpleType>::iterator simpleType = (*schema)->simpleType.begin(); simpleType != (*schema)->simpleType.end(); ++simpleType)
1445 { if ((*simpleType).baseLevel() == baseLevel)
1446 { found = true;
1447 types.gen((*schema)->targetNamespace, NULL, *simpleType, false);
1448 }
1449 }
1450 for (vector<xs__element>::iterator element = (*schema)->element.begin(); element != (*schema)->element.end(); ++element)
1451 { if (!(*element).type && (*element).simpleTypePtr() && (*element).simpleTypePtr()->baseLevel() == baseLevel)
1452 { found = true;
1453 if ((*element).type)
1454 fprintf(stream, "/// Top-level root element \"%s\":%s of simpleType %s.\n", (*schema)->targetNamespace, (*element).name, (*element).type);
1455 types.document((*element).annotation);
1456 types.gen((*schema)->targetNamespace, (*element).name, *(*element).simpleTypePtr(), false);
1457 }
1458 if (!(*element).type && (*element).complexTypePtr() && (*element).complexTypePtr()->baseLevel() == baseLevel)
1459 found = true;
1460 }
1461 for (vector<xs__attribute>::const_iterator attribute = (*schema)->attribute.begin(); attribute != (*schema)->attribute.end(); ++attribute)
1462 { if (!(*attribute).type && (*attribute).simpleTypePtr() && (*attribute).simpleTypePtr()->baseLevel() == baseLevel)
1463 { found = true;
1464 if ((*attribute).type)
1465 fprintf(stream, "/// Top-level attribute \"%s\":%s of simpleType %s.\n", (*schema)->targetNamespace, (*attribute).name, (*attribute).type);
1466 types.document((*attribute).annotation);
1467 types.gen((*schema)->targetNamespace, (*attribute).name, *(*attribute).simpleTypePtr(), false); // URI = NULL won't generate type in schema (type without namespace qualifier)
1468 }
1469 }
1470 for (vector<xs__complexType>::iterator complexType = (*schema)->complexType.begin(); complexType != (*schema)->complexType.end(); ++complexType)
1471 { if ((*complexType).baseLevel() == baseLevel)
1472 found = true;
1473 }
1474 }
1475 ++baseLevel;
1476 } while (found);
1477 // generate complex type defs. Problem: what if a simpleType restriction/extension depends on a complexType simpleContent restriction/extension?
1478 int maxLevel = baseLevel;
1479 for (baseLevel = 1; baseLevel < maxLevel; ++baseLevel)
1480 { for (vector<xs__schema*>::iterator schema = definitions.types->xs__schema_.begin(); schema != definitions.types->xs__schema_.end(); ++schema)
1481 { if (baseLevel == 1)
1482 banner("Schema Complex Types and Top-Level Elements", (*schema)->targetNamespace);
1483 for (vector<xs__complexType>::iterator complexType = (*schema)->complexType.begin(); complexType != (*schema)->complexType.end(); ++complexType)
1484 { if ((*complexType).baseLevel() == baseLevel)
1485 types.gen((*schema)->targetNamespace, NULL, *complexType, false);
1486 }
1487 for (vector<xs__element>::iterator element = (*schema)->element.begin(); element != (*schema)->element.end(); ++element)
1488 { if (!(*element).type && (*element).complexTypePtr() && (*element).complexTypePtr()->baseLevel() == baseLevel)
1489 { fprintf(stream, "\n\n/// Top-level root element \"%s\":%s\n", (*schema)->targetNamespace, (*element).name);
1490 types.document((*element).annotation);
1491 types.gen((*schema)->targetNamespace, (*element).name, *(*element).complexTypePtr(), false);
1492 }
1493 }
1494 }
1495 }
1496 for (vector<xs__schema*>::iterator schema = definitions.types->xs__schema_.begin(); schema != definitions.types->xs__schema_.end(); ++schema)
1497 { for (vector<xs__simpleType>::iterator simpleType = (*schema)->simpleType.begin(); simpleType != (*schema)->simpleType.end(); ++simpleType)
1498 { if ((*simpleType).baseLevel() <= 0)
1499 { fprintf(stream, "\n\n/// Warning: '%s' is a simpleType with cyclic restriction/extension inheritance\n", (*simpleType).name?(*simpleType).name:"");
1500 fprintf(stream, "typedef _XML %s;\n", types.deftname(TYPEDEF, NULL, false, NULL, (*schema)->targetNamespace, (*simpleType).name));
1501 }
1502 }
1503 for (vector<xs__complexType>::iterator complexType = (*schema)->complexType.begin(); complexType != (*schema)->complexType.end(); ++complexType)
1504 { if ((*complexType).baseLevel() <= 0)
1505 { fprintf(stream, "\n\n/// Warning: '%s' is a complexType with cyclic restriction/extension inheritance\n", (*complexType).name?(*complexType).name:"");
1506 if (cflag)
1507 fprintf(stream, "typedef _XML %s;\n", types.cname(NULL, (*schema)->targetNamespace, (*complexType).name));
1508 else
1509 fprintf(stream, "class %s { };\n", types.cname(NULL, (*schema)->targetNamespace, (*complexType).name));
1510 }
1511 }
1512 }
1513 // option to consider: generate local complexTypes iteratively
1514 /*
1515 for (MapOfStringToType::const_iterator local = types.locals.begin(); local != types.locals.end(); ++local)
1516 { types.gen(NULL, (*local).first, *(*local).second);
1517 }
1518 */
1519 for (vector<xs__schema*>::iterator schema = definitions.types->xs__schema_.begin(); schema != definitions.types->xs__schema_.end(); ++schema)
1520 { if (vflag)
1521 fprintf(stderr, "\nGenerating elements in %s\n", (*schema)->targetNamespace);
1522 banner("Additional Top-Level Elements", (*schema)->targetNamespace);
1523 for (vector<xs__element>::iterator element = (*schema)->element.begin(); element != (*schema)->element.end(); ++element)
1524 { if ((*element).name && (*element).type && !(*element).abstract)
1525 { fprintf(stream, "\n/// Top-level root element \"%s\":%s of type %s.\n", (*schema)->targetNamespace, (*element).name, (*element).type);
1526 types.document((*element).annotation);
1527 if (!types.is_defined("_", (*schema)->targetNamespace, (*element).name))
1528 { if (gflag)
1529 { const char *s = types.tname(NULL, (*schema)->targetNamespace, (*element).type);
1530 const char *t = types.deftname(TYPEDEF, NULL, false, "_", (*schema)->targetNamespace, (*element).name);
1531 if (strncmp(s, "char", 4) && strchr(s, '*')) // don't want pointer typedef, unless char*
1532 { size_t n = strlen(s);
1533 char *r = (char*)malloc(n);
1534 strncpy(r, s, n - 1);
1535 r[n - 1] = '\0';
1536 fprintf(stream, "typedef %s %s;\n", r, t);
1537 free(r);
1538 }
1539 else
1540 fprintf(stream, "typedef %s %s;\n", s, t);
1541 }
1542 else
1543 fprintf(stream, "/// Note: use wsdl2h option -g to auto-generate a top-level root element declaration and processing code.\n");
1544 }
1545 else
1546 { const char *s = types.cname("_", (*schema)->targetNamespace, (*element).name);
1547 const char *t = types.deftypemap[s];
1548 if (t && *t)
1549 { fprintf(stream, "/// Imported element %s from typemap %s.\n", s, mapfile?mapfile:"");
1550 types.format(t);
1551 }
1552 else
1553 fprintf(stream, "// '%s' element definition intentionally left blank.\n", types.cname("_", (*schema)->targetNamespace, (*element).name));
1554 }
1555 }
1556 }
1557 if (vflag)
1558 fprintf(stderr, "\nGenerating attributes in %s\n", (*schema)->targetNamespace);
1559 banner("Additional Top-Level Attributes", (*schema)->targetNamespace);
1560 for (vector<xs__attribute>::iterator attribute = (*schema)->attribute.begin(); attribute != (*schema)->attribute.end(); ++attribute)
1561 { if ((*attribute).name && (*attribute).type)
1562 { fprintf(stream, "\n/// Top-level attribute \"%s\":%s of simpleType %s.\n", (*schema)->targetNamespace, (*attribute).name, (*attribute).type);
1563 types.document((*attribute).annotation);
1564 if (!types.is_defined("_", (*schema)->targetNamespace, (*attribute).name))
1565 { if (gflag)
1566 { const char *s = types.tname(NULL, (*schema)->targetNamespace, (*attribute).type);
1567 const char *t = types.deftname(TYPEDEF, NULL, false, "_", (*schema)->targetNamespace, (*attribute).name);
1568 if (strncmp(s, "char", 4) && strchr(s, '*')) // don't want pointer typedef, unless char*
1569 { size_t n = strlen(s);
1570 char *r = (char*)malloc(n);
1571 strncpy(r, s, n - 1);
1572 r[n - 1] = '\0';
1573 fprintf(stream, "typedef %s %s;\n", r, t);
1574 free(r);
1575 }
1576 else
1577 fprintf(stream, "typedef %s %s;\n", s, t);
1578 }
1579 else
1580 fprintf(stream, "/// Note: use wsdl2h option -g to auto-generate a top-level attribute declaration and processing code.\n");
1581 }
1582 else
1583 { const char *s = types.cname("_", (*schema)->targetNamespace, (*attribute).name);
1584 const char *t = types.deftypemap[s];
1585 if (t && *t)
1586 { fprintf(stream, "/// Imported attribute %s from typemap %s.\n", s, mapfile?mapfile:"");
1587 types.format(t);
1588 }
1589 else
1590 fprintf(stream, "// '%s' attribute definition intentionally left blank.\n", types.cname("_", (*schema)->targetNamespace, (*attribute).name));
1591 }
1592 }
1593 }
1594 }
1595 }
1596 if (vflag)
1597 fprintf(stderr, "\nCollecting service bindings\n");
1598 collect(definitions);
1599 if (!services.empty())
1600 { banner("Services");
1601 if (soap12)
1602 fprintf(stream, "// This service supports SOAP 1.2 namespaces:\n#import \"soap12.h\"\n");
1603 for (MapOfStringToService::const_iterator service1 = services.begin(); service1 != services.end(); ++service1)
1604 { Service *sv = (*service1).second;
1605 if (sv && sv->prefix)
1606 { fprintf(stream, "\n");
1607 if (sv->name)
1608 fprintf(stream, serviceformat, sv->prefix, "name", sv->name, "");
1609 if (sv->type)
1610 fprintf(stream, serviceformat, sv->prefix, "type", sv->type, "");
1611 for (SetOfString::const_iterator port = sv->location.begin(); port != sv->location.end(); ++port)
1612 fprintf(stream, serviceformat, sv->prefix, "port", (*port), "");
1613 if (sv->URI)
1614 fprintf(stream, serviceformat, sv->prefix, "namespace", sv->URI, "");
1615 if (sv->transport)
1616 fprintf(stream, serviceformat, sv->prefix, "transport", sv->transport, "");
1617 }
1618 }
1619 fprintf(stream, "\n/** @mainpage %s Definitions\n", definitions.name?definitions.name:"Service");
1620 if (definitions.version)
1621 { section(defs, "_version Definitions Version", NULL);
1622 text(definitions.version);
1623 }
1624 if (definitions.documentation)
1625 { section(defs, "_documentation Documentation", NULL);
1626 text(definitions.documentation);
1627 }
1628 if (definitions.types && definitions.types->documentation)
1629 { section(defs, "_types Schema Type Information", NULL);
1630 text(definitions.types->documentation);
1631 }
1632 section(defs, "_bindings Service Bindings", NULL);
1633 for (MapOfStringToService::const_iterator service2 = services.begin(); service2 != services.end(); ++service2)
1634 { Service *sv = (*service2).second;
1635 if (sv && sv->name)
1636 fprintf(stream, "\n - @ref %s\n", sv->name);
1637 }
1638 section(defs, "_more More Information", NULL);
1639 fprintf(stream, "\n - @ref page_notes \"Usage Notes\"\n");
1640 fprintf(stream, "\n - @ref page_XMLDataBinding \"XML Data Binding\"\n");
1641 if (!jflag)
1642 fprintf(stream, "\n - @ref SOAP_ENV__Header \"SOAP Header Content\" (when applicable)\n");
1643 if (!jflag)
1644 fprintf(stream, "\n - @ref SOAP_ENV__Detail \"SOAP Fault Detail Content\" (when applicable)\n");
1645 fprintf(stream, "\n\n*/\n");
1646 for (MapOfStringToService::const_iterator service3 = services.begin(); service3 != services.end(); ++service3)
1647 { Service *sv = (*service3).second;
1648 if (sv && sv->name)
1649 { fprintf(stream, "\n/**\n");
1650 page(sv->name, " Binding", sv->name);
1651 for (MapOfStringToString::const_iterator service_doc = sv->service_documentation.begin(); service_doc != sv->service_documentation.end(); ++service_doc)
1652 { const char *name = types.aname(NULL, NULL, (*service_doc).first);
1653 section(name, "_service Service Documentation", (*service_doc).first);
1654 text((*service_doc).second);
1655 }
1656 for (MapOfStringToString::const_iterator port_doc = sv->port_documentation.begin(); port_doc != sv->port_documentation.end(); ++port_doc)
1657 { const char *name = types.aname(NULL, NULL, (*port_doc).first);
1658 section(name, "_port Port Documentation", (*port_doc).first);
1659 text((*port_doc).second);
1660 }
1661 for (MapOfStringToString::const_iterator binding_doc = sv->binding_documentation.begin(); binding_doc != sv->binding_documentation.end(); ++binding_doc)
1662 { const char *name = types.aname(NULL, NULL, (*binding_doc).first);
1663 section(name, "_binding Binding Documentation", (*binding_doc).first);
1664 text((*binding_doc).second);
1665 }
1666 section(sv->name, "_operations Operations of Binding ", sv->name);
1667 for (vector<Operation*>::const_iterator op = sv->operation.begin(); op != sv->operation.end(); ++op)
1668 { if (*op && (*op)->input && (*op)->input_name)
1669 fprintf(stream, "\n - @ref %s\n", (*op)->input_name);
1670 else if (*op && (*op)->output_name)
1671 fprintf(stream, "\n - @ref %s\n", (*op)->output_name);
1672 }
1673 section(sv->name, "_ports Endpoints of Binding ", sv->name);
1674 for (SetOfString::const_iterator port = sv->location.begin(); port != sv->location.end(); ++port)
1675 fprintf(stream, "\n - %s\n", *port);
1676 if (!sv->policy.empty())
1677 { section(sv->name, "_policy Policy of Binding ", sv->name);
1678 fprintf(stream, "\nSee Section @ref %s_policy_enablers\n", sv->name);
1679 gen_policy(*sv, sv->policy, "service endpoint ports", types);
1680 }
1681 if (!service_prefix)
1682 fprintf(stream, "\nNote: use wsdl2h option -Nname to change the service binding prefix name\n");
1683 fprintf(stream, "\n\n*/\n");
1684 }
1685 }
1686 }
1687 generate();
1688 if (definitions.types)
1689 { banner("XML Data Binding");
1690 fprintf(stream, "\n/**\n");
1691 page("page_XMLDataBinding", " XML Data Binding", NULL);
1692 fprintf(stream, "\nSOAP/XML services use data bindings contractually bound by WSDL and auto-\ngenerated by wsdl2h and soapcpp2 (see Service Bindings). Plain data bindings\nare adopted from XML schemas as part of the WSDL types section or when running\nwsdl2h on a set of schemas to produce non-SOAP-based XML data bindings.\n\nThe following readers and writers are C/C++ data type (de)serializers auto-\ngenerated by wsdl2h and soapcpp2. Run soapcpp2 on this file to generate the\n(de)serialization code, which is stored in soapC.c[pp]. Include \"soapH.h\" in\nyour code to import these data type and function declarations. Only use the\nsoapcpp2-generated files in your project build. Do not include the wsdl2h-\ngenerated .h file in your code.\n\nData can be read in XML and deserialized from:\n - a file descriptor, using soap->recvfd = fd\n - a socket, using soap->socket = ...\n - a C++ stream, using soap->is = ...\n - a buffer, using the soap->frecv() callback\n\nData can be serialized in XML and written to:\n - a file descriptor, using soap->sendfd = fd\n - a socket, using soap->socket = ...\n - a C++ stream, using soap->os = ...\n - a buffer, using the soap->fsend() callback\n\nThe following options are available for (de)serialization control:\n - soap->encodingStyle = NULL; to remove SOAP 1.1/1.2 encodingStyle\n - soap_mode(soap, SOAP_XML_TREE); XML without id-ref (no cycles!)\n - soap_mode(soap, SOAP_XML_GRAPH); XML with id-ref (including cycles)\n - soap_set_namespaces(soap, struct Namespace *nsmap); to set xmlns bindings\n\n");
1693 for (vector<xs__schema*>::const_iterator schema5 = definitions.types->xs__schema_.begin(); schema5 != definitions.types->xs__schema_.end(); ++schema5)
1694 { const char *prefix = types.nsprefix(NULL, (*schema5)->targetNamespace);
1695 fprintf(stream, "\n@section %s Top-level root elements of schema \"%s\"\n", prefix, (*schema5)->targetNamespace);
1696 for (vector<xs__element>::const_iterator element = (*schema5)->element.begin(); element != (*schema5)->element.end(); ++element)
1697 { fprintf(stream, "\n - <%s:%s> ", prefix, (*element).name);
1698 if (types.is_defined("_", (*schema5)->targetNamespace, (*element).name))
1699 { const char *cname = types.cname("_", (*schema5)->targetNamespace, (*element).name);
1700 const char *pname = types.pname(true, "_", (*schema5)->targetNamespace, (*element).name);
1701 fprintf(stream, "@ref %s\n", cname);
1702 fprintf(stream, " @code\n // Reader (returns SOAP_OK on success):\n soap_read_%s(struct soap*, %s);\n // Writer (returns SOAP_OK on success):\n soap_write_%s(struct soap*, %s);\n @endcode\n", cname, pname, cname, pname);
1703 }
1704 else
1705 fprintf(stream, "(use wsdl2h option -g to auto-generate)\n");
1706 }
1707 }
1708 fprintf(stream, "\n*/\n");
1709 }
1710 if (cppnamespace)
1711 fprintf(stream, "\n} // namespace %s\n", cppnamespace);
1712 fprintf(stream, "\n/* End of %s */\n", outfile?outfile:"file");
1713 }
1714
1715 void Definitions::generate()
1716 { MapOfStringToMessage headers;
1717 MapOfStringToMessage faults;
1718 const char *t;
1719 for (MapOfStringToService::const_iterator service1 = services.begin(); service1 != services.end(); ++service1)
1720 { if ((*service1).second)
1721 { for (MapOfStringToMessage::const_iterator header = (*service1).second->header.begin(); header != (*service1).second->header.end(); ++header)
1722 headers[(*header).first] = (*header).second;
1723 for (MapOfStringToMessage::const_iterator fault = (*service1).second->fault.begin(); fault != (*service1).second->fault.end(); ++fault)
1724 faults[(*fault).first] = (*fault).second;
1725 }
1726 }
1727 // Generate SOAP Header definition
1728 t = types.deftypemap["SOAP_ENV__Header"];
1729 if (t && *t)
1730 { banner("Custom SOAP Header");
1731 types.format(t);
1732 }
1733 else if (!jflag && !headers.empty())
1734 { banner("SOAP Header");
1735 fprintf(stream, "/**\n\nThe SOAP Header is part of the gSOAP context and its content is accessed\nthrough the soap.header variable. You may have to set the soap.actor variable\nto serialize SOAP Headers with SOAP-ENV:actor or SOAP-ENV:role attributes.\nUse option -j to remove entire SOAP Header definition.\nUse option -k to remove the mustUnderstand qualifiers.\n\n*/\n");
1736 fprintf(stream, "struct SOAP_ENV__Header\n{\n");
1737 for (MapOfStringToMessage::const_iterator header = headers.begin(); header != headers.end(); ++header)
1738 { if ((*header).second->URI && !types.uris[(*header).second->URI])
1739 fprintf(stream, schemaformat, types.nsprefix(NULL, (*header).second->URI), "namespace", (*header).second->URI);
1740 comment("Header", (*header).first, "WSDL", (*header).second->ext_documentation);
1741 comment("Header", (*header).first, "SOAP", (*header).second->documentation);
1742 if ((*header).second->mustUnderstand && !kflag)
1743 { fprintf(stream, elementformat, "mustUnderstand", "// must be understood by receiver");
1744 fprintf(stream, "\n");
1745 }
1746 if ((*header).second->part && (*header).second->part->elementPtr())
1747 { fprintf(stream, "/// \"%s\" SOAP Header part element\n", (*header).second->part->name);
1748 if ((*header).second->part->elementPtr()->type && (*header).second->part->element)
1749 fprintf(stream, elementformat, types.pname(true, NULL, NULL, (*header).second->part->elementPtr()->type), types.aname(NULL, NULL, (*header).second->part->element));
1750 else if ((*header).second->part->element)
1751 fprintf(stream, elementformat, types.pname(true, "_", NULL, (*header).second->part->element), types.aname(NULL, NULL, (*header).second->part->element));
1752 else
1753 fprintf(stream, elementformat, types.pname(true, "_", NULL, (*header).second->part->elementPtr()->name), (*header).first);
1754 fprintf(stream, ";\n");
1755 }
1756 else if ((*header).second->part && (*header).second->part->type)
1757 { fprintf(stream, "/// \"%s\" SOAP Header part type\n", (*header).second->part->type);
1758 fprintf(stream, elementformat, types.pname(true, NULL, NULL, (*header).second->part->type), types.aname(NULL, (*header).second->URI, (*header).second->part->name));
1759 fprintf(stream, ";\n");
1760 }
1761 else if ((*header).second->element)
1762 { fprintf(stream, "/// \"%s\" SOAP Header element", (*header).second->name);
1763 (*header).second->generate(types, ";", false, true, false, true);
1764 fprintf(stream, "\n");
1765 }
1766 else
1767 { if ((*header).second->part && (*header).second->part->element)
1768 fprintf(stream, elementformat, types.pname(true, "_", NULL, (*header).second->part->element), (*header).first);
1769 else
1770 fprintf(stream, pointerformat, (*header).first, (*header).first);
1771 fprintf(stream, ";\t///< TODO: Please check element name and type (imported type)\n");
1772 }
1773 }
1774 types.modify("SOAP_ENV__Header");
1775 fprintf(stream, "\n};\n");
1776 }
1777 // Generate Fault detail element definitions
1778 for (MapOfStringToMessage::const_iterator fault = faults.begin(); fault != faults.end(); ++fault)
1779 { if ((*fault).second->use == encoded)
1780 { banner("SOAP Fault Detail Message");
1781 fprintf(stream, "/// SOAP Fault detail message \"%s:%s\"\n", (*fault).second->URI, (*fault).second->message->name);
1782 comment("Fault", (*fault).first, "WSDL", (*fault).second->ext_documentation);
1783 comment("Fault", (*fault).first, "SOAP", (*fault).second->documentation);
1784 if (cflag)
1785 fprintf(stream, "struct %s\n{", (*fault).first);
1786 else
1787 fprintf(stream, "class %s\n{ public:", (*fault).first);
1788 (*fault).second->generate(types, ";", false, true, false, true);
1789 if (!cflag)
1790 { fprintf(stream, "\n");
1791 fprintf(stream, pointerformat, "struct soap", "soap");
1792 fprintf(stream, ";");
1793 }
1794 fprintf(stream, "\n};\n");
1795 if (cflag)
1796 fprintf(stream, "typedef struct %s %s;\n", (*fault).first, (*fault).first);
1797 if ((*fault).second->URI && !types.uris[(*fault).second->URI])
1798 fprintf(stream, schemaformat, types.nsprefix(NULL, (*fault).second->URI), "namespace", (*fault).second->URI);
1799 }
1800 }
1801 t = types.deftypemap["SOAP_ENV__Detail"];
1802 if (t && *t)
1803 { banner("Custom SOAP Fault Detail");
1804 types.format(t);
1805 }
1806 else if (!jflag && !faults.empty())
1807 { SetOfString fault_elements;
1808 banner("SOAP Fault Detail");
1809 fprintf(stream, "/**\n\nThe SOAP Fault is part of the gSOAP context and its content is accessed\nthrough the soap.fault->detail variable (SOAP 1.1) or the\nsoap.fault->SOAP_ENV__Detail variable (SOAP 1.2).\nUse wsdl2h option -j to omit these declarations.\n\n*/\n");
1810 fprintf(stream, "struct SOAP_ENV__Detail\n{\n");
1811 if (dflag)
1812 { const char *t = types.tname(NULL, NULL, "xsd:anyAttribute");
1813 fprintf(stream, attributeformat, t, "__anyAttribute");
1814 fprintf(stream, ";\t///< Catch any attribute content in DOM.\n");
1815 }
1816 else
1817 fprintf(stream, "// xsd:anyAttribute omitted: to parse attribute content of the Detail element into DOM anyAttribute, use wsdl2h option -d.\n");
1818 types.modify("SOAP_ENV__Detail");
1819 /* See below */
1820 fprintf(stream, elementformat, "_XML", "__any");
1821 fprintf(stream, ";\t///< Catch any element content in XML string.\n");
1822 /* The DOM representation is not desired since faultdetail is NULL.
1823 However, future options may reenable this feature (see keep code here).
1824 const char *t = types.tname(NULL, NULL, "xsd:any");
1825 fprintf(stream, elementformat, t, "__any");
1826 if (dflag)
1827 fprintf(stream, ";\t///< Catch any element content in DOM.\n");
1828 else
1829 fprintf(stream, ";\t///< Catch any element content in XML string.\n");
1830 */
1831 for (MapOfStringToMessage::const_iterator fault = faults.begin(); fault != faults.end(); ++fault)
1832 { if ((*fault).second->URI && !types.uris[(*fault).second->URI])
1833 fprintf(stream, schemaformat, types.nsprefix(NULL, (*fault).second->URI), "namespace", (*fault).second->URI);
1834 comment("Fault", (*fault).first, "WSDL", (*fault).second->ext_documentation);
1835 comment("Fault", (*fault).first, "SOAP", (*fault).second->documentation);
1836 if ((*fault).second->message)
1837 { if ((*fault).second->use == literal)
1838 { for (vector<wsdl__part>::const_iterator part = (*fault).second->message->part.begin(); part != (*fault).second->message->part.end(); ++part)
1839 { if ((*part).elementPtr())
1840 { if (fault_elements.find((*part).element) == fault_elements.end())
1841 { if ((*part).elementPtr()->type)
1842 fprintf(stream, elementformat, types.pname(true, NULL, NULL, (*part).elementPtr()->type), types.aname(NULL, (*fault).second->URI, (*part).element));
1843 else
1844 fprintf(stream, elementformat, types.pname(true, "_", NULL, (*part).element), types.aname(NULL, (*fault).second->URI, (*part).element));
1845 fprintf(stream, ";\n");
1846 fault_elements.insert((*part).element);
1847 }
1848 fprintf(stream, "///< SOAP Fault element \"%s\" part \"%s\"\n", (*part).element?(*part).element:"", (*part).name?(*part).name:"");
1849 }
1850 else if ((*part).name && (*part).type)
1851 { if (fault_elements.find((*part).name) == fault_elements.end())
1852 { fprintf(stream, elementformat, types.pname(true, NULL, NULL, (*part).type), types.aname("_", (*fault).second->URI, (*part).name));
1853 fprintf(stream, ";\n");
1854 fault_elements.insert((*part).name);
1855 }
1856 fprintf(stream, "///< SOAP Fault type \"%s\" part \"%s\"\n", (*part).type, (*part).name);
1857 }
1858 else
1859 fprintf(stream, "// Unknown SOAP Fault element \"%s\" part \"%s\"\n", (*fault).second->message->name, (*part).name?(*part).name:"");
1860 }
1861 }
1862 else
1863 { fprintf(stream, elementformat, (*fault).first, types.aname(NULL, (*fault).second->URI, (*fault).second->message->name));
1864 fprintf(stream, ";\t///< SOAP Fault detail message \"%s\":%s\n", (*fault).second->URI, (*fault).second->message->name);
1865 }
1866 }
1867 else if ((*fault).second->element)
1868 { if (fault_elements.find((*fault).second->name) == fault_elements.end())
1869 { fprintf(stream, pointerformat, types.pname(true, "_", (*fault).second->URI, (*fault).second->element->name), (*fault).second->name);
1870 fprintf(stream, ";\t///< SOAP Fault detail message \"%s\":%s\n", (*fault).second->URI, (*fault).second->element->name);
1871 fault_elements.insert((*fault).second->name);
1872 }
1873 }
1874 }
1875 fprintf(stream, elementformat, "int", "__type");
1876 fprintf(stream, ";\t///< set to SOAP_TYPE_X for a serializable type X\n");
1877 fprintf(stream, pointerformat, "void", "fault");
1878 fprintf(stream, ";\t///< points to serializable object X or NULL\n");
1879 fprintf(stream, "};\n");
1880 }
1881 /* The SOAP Fault struct below is autogenerated by soapcpp2 (kept here for future mods)
1882 if (!mflag && !faults.empty())
1883 { fprintf(stream, "struct SOAP_ENV__Code\n{\n");
1884 fprintf(stream, elementformat, "_QName", "SOAP_ENV__Value");
1885 fprintf(stream, ";\n");
1886 fprintf(stream, pointerformat, "char", "SOAP_ENV__Node");
1887 fprintf(stream, ";\n");
1888 fprintf(stream, pointerformat, "char", "SOAP_ENV__Role");
1889 fprintf(stream, ";\n};\n");
1890 fprintf(stream, "struct SOAP_ENV__Detail\n{\n");
1891 fprintf(stream, elementformat, "int", "__type");
1892 fprintf(stream, ";\n");
1893 fprintf(stream, pointerformat, "void", "fault");
1894 fprintf(stream, ";\n");
1895 fprintf(stream, elementformat, "_XML", "__any");
1896 fprintf(stream, ";\n};\n");
1897 fprintf(stream, "struct SOAP_ENV__Fault\n{\n");
1898 fprintf(stream, elementformat, "_QName", "faultcode");
1899 fprintf(stream, ";\n");
1900 fprintf(stream, pointerformat, "char", "faultstring");
1901 fprintf(stream, ";\n");
1902 fprintf(stream, pointerformat, "char", "faultactor");
1903 fprintf(stream, ";\n");
1904 fprintf(stream, pointerformat, "struct SOAP_ENV__Detail", "detail");
1905 fprintf(stream, ";\n");
1906 fprintf(stream, pointerformat, "struct SOAP_ENV__Code", "SOAP_ENV__Code");
1907 fprintf(stream, ";\n");
1908 fprintf(stream, pointerformat, "char", "SOAP_ENV__Reason");
1909 fprintf(stream, ";\n");
1910 fprintf(stream, pointerformat, "struct SOAP_ENV__Detail", "SOAP_ENV__Detail");
1911 fprintf(stream, ";\n};\n");
1912 }
1913 */
1914 for (MapOfStringToService::const_iterator service2 = services.begin(); service2 != services.end(); ++service2)
1915 if ((*service2).second)
1916 (*service2).second->generate(types);
1917 }
1918
1919 ////////////////////////////////////////////////////////////////////////////////
1920 //
1921 // Service methods
1922 //
1923 ////////////////////////////////////////////////////////////////////////////////
1924
1925 Service::Service()
1926 { prefix = NULL;
1927 URI = NULL;
1928 name = NULL;
1929 type = NULL;
1930 transport = NULL;
1931 }
1932
1933 void Service::generate(Types& types)
1934 { const char *method_name;
1935 banner("Service Binding", name);
1936 for (vector<Operation*>::const_iterator op2 = operation.begin(); op2 != operation.end(); ++op2)
1937 { if (*op2 && ((*op2)->input || bflag))
1938 { bool flag = false, anonymous = ((*op2)->style != document && (*op2)->parameterOrder != NULL);
1939 if (!(*op2)->input)
1940 method_name = (*op2)->output_name;
1941 else
1942 method_name = (*op2)->input_name;
1943 banner("Service Operation", method_name);
1944 if ((*op2)->output && (*op2)->output_name)
1945 { if ((*op2)->style == document)
1946 flag = ((*op2)->output->element || ((*op2)->output->message && (*op2)->output->message->part.size() == 1));
1947 else if (!wflag)
1948 flag = ((*op2)->output->element || ((*op2)->output->message && (*op2)->output->use == encoded && (*op2)->output->message->part.size() == 1 && !(*(*op2)->output->message->part.begin()).simpleTypePtr() && !(*(*op2)->output->message->part.begin()).complexTypePtr()));
1949 if (flag && (*op2)->input && (*op2)->output && (*op2)->input->message && (*(*op2)->output->message->part.begin()).element)
1950 for (vector<wsdl__part>::const_iterator part = (*op2)->input->message->part.begin(); part != (*op2)->input->message->part.end(); ++part)
1951 if ((*part).element && !strcmp((*part).element, (*(*op2)->output->message->part.begin()).element))
1952 flag = false;
1953 if (!flag)
1954 { if (bflag)
1955 fprintf(stream, "/* soapcpp2 generates the following struct automatically for your use:\n");
1956 fprintf(stream, "/// Operation response struct \"%s\" of operation \"%s\"\n", (*op2)->output_name, method_name);
1957 fprintf(stream, "struct %s\n{", (*op2)->output_name);
1958 (*op2)->output->generate(types, ";", anonymous, false, false, false);
1959 fprintf(stream, "\n};\n");
1960 if (bflag)
1961 fprintf(stream, "*/\n");
1962 }
1963 }
1964 fprintf(stream, "\n/// Operation \"%s\" of service binding \"%s\"\n\n/**\n\nOperation details:\n", method_name, name);
1965 if ((*op2)->documentation)
1966 text((*op2)->documentation);
1967 if ((*op2)->operation_documentation)
1968 text((*op2)->operation_documentation);
1969 if ((*op2)->input && (*op2)->input->documentation)
1970 { fprintf(stream, "Input request:\n");
1971 text((*op2)->input->documentation);
1972 }
1973 if ((*op2)->input && (*op2)->input->ext_documentation)
1974 { fprintf(stream, "Input request:\n");
1975 text((*op2)->input->ext_documentation);
1976 }
1977 if ((*op2)->output)
1978 { if ((*op2)->output->documentation)
1979 { fprintf(stream, "Output response:\n");
1980 text((*op2)->output->documentation);
1981 }
1982 if ((*op2)->output->ext_documentation)
1983 { fprintf(stream, "Output response:\n");
1984 text((*op2)->output->ext_documentation);
1985 }
1986 }
1987 gen_policy(*this, (*op2)->policy, "operation", types);
1988 if ((*op2)->input)
1989 { gen_policy(*this, (*op2)->input->policy, "request message", types);
1990 if ((*op2)->input->content)
1991 { fprintf(stream, "\n - Request message MIME content");
1992 if ((*op2)->input->content->type)
1993 { fprintf(stream, " type=\"");
1994 text((*op2)->input->content->type);
1995 fprintf(stream, "\"");
1996 }
1997 if ((*op2)->input->content->type && !strcmp((*op2)->input->content->type, "application/x-www-form-urlencoded"))
1998 fprintf(stream, "\n Use the httpform.c plugin to retrieve key-value pairs from the REST request\n message form data at the server side (client side is automated).\n");
1999 else
2000 fprintf(stream, "\n TODO: this form of MIME content is not automatically handled.\n");
2001 }
2002 }
2003 if ((*op2)->output)
2004 { gen_policy(*this, (*op2)->output->policy, "response message", types);
2005 if ((*op2)->output->content)
2006 { fprintf(stream, "\n - Response message MIME content");
2007 if ((*op2)->output->content->type)
2008 { fprintf(stream, " type=\"");
2009 text((*op2)->output->content->type);
2010 fprintf(stream, "\"");
2011 }
2012 fprintf(stream, "\n TODO: this form of MIME content response is not automatically handled.\n Use one-way request and implement code to parse response.\n");
2013 }
2014 }
2015 else
2016 fprintf(stream, "\n - One-way service request message\n");
2017 if ((*op2)->mep)
2018 fprintf(stream, "\n - SOAP MEP: \"%s\"\n", ((*op2)->mep));
2019 if ((*op2)->style == document)
2020 fprintf(stream, "\n - %s %s messaging\n", (*op2)->protocol, (*op2)->input && (*op2)->input->content && (*op2)->input->content->type ? (*op2)->input->content->type : "document/literal style");
2021 else if ((*op2)->input)
2022 { if ((*op2)->input->use == literal)
2023 fprintf(stream, "\n - %s literal messaging\n", (*op2)->protocol);
2024 else if ((*op2)->input->encodingStyle)
2025 fprintf(stream, "\n - %s RPC encodingStyle=\"%s\"\n", (*op2)->input->encodingStyle, (*op2)->protocol);
2026 else
2027 fprintf(stream, "\n - %s RPC encoded messaging\n", (*op2)->protocol);
2028 }
2029 if ((*op2)->output)
2030 { if (!(*op2)->input || (*op2)->input->use != (*op2)->output->use)
2031 { if ((*op2)->output->use == literal)
2032 fprintf(stream, "\n - %s literal response messages\n", (*op2)->protocol);
2033 else if ((*op2)->output->encodingStyle)
2034 fprintf(stream, "\n - %s RPC response encodingStyle=\"%s\"\n", (*op2)->protocol, (*op2)->output->encodingStyle);
2035 else
2036 fprintf(stream, "\n - %s RPC encoded response messages\n", (*op2)->protocol);
2037 }
2038 }
2039 if ((*op2)->action)
2040 { if (*(*op2)->action)
2041 fprintf(stream, "\n - Action: \"%s\"\n", (*op2)->action);
2042 }
2043 if ((*op2)->input)
2044 { if ((*op2)->input->action)
2045 fprintf(stream, "\n - Addressing input action: \"%s\"\n", (*op2)->input->action);
2046 }
2047 if ((*op2)->output)
2048 { if ((*op2)->output->action)
2049 fprintf(stream, "\n - Addressing output action: \"%s\"\n", (*op2)->output->action);
2050 }
2051 for (vector<Message*>::const_iterator infault = (*op2)->infault.begin(); infault != (*op2)->infault.end(); ++infault)
2052 { if ((*infault)->message)
2053 { if ((*infault)->use == literal)
2054 { for (vector<wsdl__part>::const_iterator part = (*infault)->message->part.begin(); part != (*infault)->message->part.end(); ++part)
2055 { if ((*part).element)
2056 fprintf(stream, "\n - SOAP Input Fault: %s (literal)\n", (*part).element);
2057 else if ((*part).name && (*part).type)
2058 fprintf(stream, "\n - SOAP Input Fault: %s (literal)\n", (*part).name);
2059 }
2060 }
2061 else if ((*infault)->message->name)
2062 fprintf(stream, "\n - SOAP Input Fault: %s\n", (*infault)->name);
2063 if ((*infault)->message->name && (*infault)->action)
2064 fprintf(stream, " - SOAP Input Fault addressing action: \"%s\"\n", (*infault)->action);
2065 }
2066 else if ((*infault)->name)
2067 fprintf(stream, "\n - SOAP Input Fault: %s (literal)\n", (*infault)->name);
2068 if ((*infault)->body_parts)
2069 fprintf(stream, " SOAP Input Fault code: %s\n", (*infault)->body_parts);
2070 text((*infault)->documentation);
2071 text((*infault)->ext_documentation);
2072 gen_policy(*this, (*infault)->policy, "fault message", types);
2073 }
2074 for (vector<Message*>::const_iterator outfault = (*op2)->outfault.begin(); outfault != (*op2)->outfault.end(); ++outfault)
2075 { if ((*outfault)->message)
2076 { if ((*outfault)->use == literal)
2077 { for (vector<wsdl__part>::const_iterator part = (*outfault)->message->part.begin(); part != (*outfault)->message->part.end(); ++part)
2078 { if ((*part).element)
2079 fprintf(stream, "\n - SOAP Output Fault: %s (literal)\n", (*part).element);
2080 else if ((*part).name && (*part).type)
2081 fprintf(stream, "\n - SOAP Output Fault: %s (literal)\n", (*part).name);
2082 }
2083 }
2084 else if ((*outfault)->message->name)
2085 fprintf(stream, "\n - SOAP Output Fault: %s\n", (*outfault)->name);
2086 if ((*outfault)->message->name && (*outfault)->action)
2087 fprintf(stream, " - SOAP Output Fault addressing action: \"%s\"\n", (*outfault)->action);
2088 }
2089 else if ((*outfault)->name)
2090 fprintf(stream, "\n - SOAP Output Fault: %s (literal)\n", (*outfault)->name);
2091 if ((*outfault)->body_parts)
2092 fprintf(stream, " SOAP Output Fault code: %s\n", (*outfault)->body_parts);
2093 text((*outfault)->documentation);
2094 text((*outfault)->ext_documentation);
2095 gen_policy(*this, (*outfault)->policy, "fault message", types);
2096 }
2097 if ((*op2)->input)
2098 { if (!(*op2)->input->header.empty())
2099 fprintf(stream, "\n - Request message has mandatory header part(s) (see @ref SOAP_ENV__Header):\n");
2100 for (vector<soap__header>::const_iterator inputheader = (*op2)->input->header.begin(); inputheader != (*op2)->input->header.end(); ++inputheader)
2101 { if ((*inputheader).part)
2102 { if ((*inputheader).use == encoded && (*inputheader).namespace_)
2103 fprintf(stream, " - %s\n", types.aname(NULL, (*inputheader).namespace_, (*inputheader).part));
2104 else if ((*inputheader).partPtr() && (*inputheader).partPtr()->element)
2105 fprintf(stream, " - %s\n", types.aname(NULL, NULL, (*inputheader).partPtr()->element));
2106 }
2107 }
2108 }
2109 if ((*op2)->input && (*op2)->input->multipartRelated)
2110 { int k = 2;
2111 fprintf(stream, "\n - Request message MIME multipart/related attachments:\n");
2112 for (vector<mime__part>::const_iterator part = (*op2)->input->multipartRelated->part.begin(); part != (*op2)->input->multipartRelated->part.end(); ++part)
2113 { if ((*part).soap__body_)
2114 { fprintf(stream, " -# MIME attachment with SOAP Body and mandatory header part(s):\n");
2115 for (vector<soap__header>::const_iterator header = (*part).soap__header_.begin(); header != (*part).soap__header_.end(); ++header)
2116 { if ((*header).part)
2117 { if ((*header).use == encoded && (*header).namespace_)
2118 fprintf(stream, " - %s\n", types.aname(NULL, (*header).namespace_, (*header).part));
2119 else if ((*header).partPtr() && (*header).partPtr()->element)
2120 fprintf(stream, " - %s\n", types.aname(NULL, NULL, (*header).partPtr()->element));
2121 }
2122 }
2123 }
2124 else
2125 { fprintf(stream, " -# MIME attachment %d:\n", k++);
2126 for (vector<mime__content>::const_iterator content = (*part).content.begin(); content != (*part).content.end(); ++content)
2127 { fprintf(stream, " -");
2128 if ((*content).part)
2129 { fprintf(stream, " part=\"");
2130 text((*content).part);
2131 fprintf(stream, "\"");
2132 }
2133 if ((*content).type)
2134 { fprintf(stream, " type=\"");
2135 text((*content).type);
2136 fprintf(stream, "\"");
2137 }
2138 fprintf(stream, "\n");
2139 }
2140 }
2141 }
2142 }
2143 if ((*op2)->input && (*op2)->input->layout)
2144 fprintf(stream, "\n - Request message has DIME attachments in compliance with %s\n", (*op2)->input->layout);
2145 if ((*op2)->output)
2146 { if (!(*op2)->output->header.empty())
2147 fprintf(stream, "\n - Response message has mandatory header part(s): (see @ref SOAP_ENV__Header)\n");
2148 for (vector<soap__header>::const_iterator outputheader = (*op2)->output->header.begin(); outputheader != (*op2)->output->header.end(); ++outputheader)
2149 { if ((*outputheader).part)
2150 { if ((*outputheader).use == encoded && (*outputheader).namespace_)
2151 fprintf(stream, " - %s\n", types.aname(NULL, (*outputheader).namespace_, (*outputheader).part));
2152 else if ((*outputheader).partPtr() && (*outputheader).partPtr()->element)
2153 fprintf(stream, " - %s\n", types.aname(NULL, NULL, (*outputheader).partPtr()->element));
2154 }
2155 }
2156 }
2157 if ((*op2)->output && (*op2)->output_name && (*op2)->output->multipartRelated)
2158 { int k = 2;
2159 fprintf(stream, "\n - Response message MIME multipart/related attachments\n");
2160 for (vector<mime__part>::const_iterator part = (*op2)->output->multipartRelated->part.begin(); part != (*op2)->output->multipartRelated->part.end(); ++part)
2161 { if ((*part).soap__body_)
2162 { fprintf(stream, " -# MIME attachment with SOAP Body and mandatory header part(s):\n");
2163 for (vector<soap__header>::const_iterator header = (*part).soap__header_.begin(); header != (*part).soap__header_.end(); ++header)
2164 { if ((*header).part)
2165 { if ((*header).use == encoded && (*header).namespace_)
2166 fprintf(stream, " - %s\n", types.aname(NULL, (*header).namespace_, (*header).part));
2167 else if ((*header).partPtr() && (*header).partPtr()->element)
2168 fprintf(stream, " - %s\n", types.aname(NULL, NULL, (*header).partPtr()->element));
2169 }
2170 }
2171 }
2172 else
2173 { fprintf(stream, " -# MIME attachment %d:\n", k++);
2174 for (vector<mime__content>::const_iterator content = (*part).content.begin(); content != (*part).content.end(); ++content)
2175 { fprintf(stream, " -");
2176 if ((*content).part)
2177 { fprintf(stream, " part=\"");
2178 text((*content).part);
2179 fprintf(stream, "\"");
2180 }
2181 if ((*content).type)
2182 { fprintf(stream, " type=\"");
2183 text((*content).type);
2184 fprintf(stream, "\"");
2185 }
2186 fprintf(stream, "\n");
2187 }
2188 }
2189 }
2190 }
2191 if ((*op2)->output && (*op2)->output_name && (*op2)->output->layout)
2192 fprintf(stream, "\n - Response message has DIME attachments in compliance with %s\n", (*op2)->output->layout);
2193 fprintf(stream, "\nC stub function (defined in soapClient.c[pp] generated by soapcpp2):\n@code\n int soap_%s_%s(\n struct soap *soap,\n NULL, // char *endpoint = NULL selects default endpoint for this operation\n NULL, // char *action = NULL selects default action for this operation\n // input parameters:", (*op2)->output?"call":"send", method_name);
2194 if ((*op2)->input)
2195 (*op2)->input->generate(types, ",", false, false, false, false);
2196 if ((*op2)->output && (*op2)->output_name)
2197 { fprintf(stream, "\n // output parameters:");
2198 if (flag)
2199 { if ((*op2)->style == rpc && (*op2)->output->message && (*(*op2)->output->message->part.begin()).name)
2200 { fprintf(stream, "\n");
2201 fprintf(stream, anonymous ? anonformat : paraformat, types.tname(NULL, NULL, (*(*op2)->output->message->part.begin()).type), cflag ? "*" : "&", types.aname(NULL, NULL, (*(*op2)->output->message->part.begin()).name), "");
2202 }
2203 else
2204 (*op2)->output->generate(types, "", anonymous, false, true, false);
2205 }
2206 else
2207 fprintf(stream, "\n struct %s%s", (*op2)->output_name, cflag ? "*" : "&");
2208 }
2209 fprintf(stream, "\n );\n@endcode\n\nC server function (called from the service dispatcher defined in soapServer.c[pp]):\n@code\n int %s(\n struct soap *soap,\n // input parameters:", method_name);
2210 if ((*op2)->input)
2211 (*op2)->input->generate(types, ",", false, false, false, false);
2212 fprintf(stream, "\n // output parameters:");
2213 if ((*op2)->output && (*op2)->output_name)
2214 { if (flag)
2215 { if ((*op2)->style == rpc && (*op2)->output->message && (*(*op2)->output->message->part.begin()).name)
2216 { fprintf(stream, "\n");
2217 fprintf(stream, anonymous ? anonformat : paraformat, types.tname(NULL, NULL, (*(*op2)->output->message->part.begin()).type), cflag ? "*" : "&", types.aname(NULL, NULL, (*(*op2)->output->message->part.begin()).name), "");
2218 }
2219 else
2220 (*op2)->output->generate(types, "", anonymous, false, true, false);
2221 }
2222 else
2223 fprintf(stream, "\n struct %s%s", (*op2)->output_name, cflag ? "*" : "&");
2224 }
2225 fprintf(stream, "\n );\n@endcode\n\n");
2226 if (!cflag)
2227 { fprintf(stream, "C++ proxy class (defined in soap%sProxy.h):\n", name);
2228 fprintf(stream, "@code\n class %sProxy;\n@endcode\n", name);
2229 fprintf(stream, "Important: use soapcpp2 option '-j' (or '-i') to generate greatly improved and easy-to-use proxy classes;\n\n");
2230 fprintf(stream, "C++ service class (defined in soap%sService.h):\n", name);
2231 fprintf(stream, "@code\n class %sService;\n@endcode\n", name);
2232 fprintf(stream, "Important: use soapcpp2 option '-j' (or '-i') to generate greatly improved and easy-to-use service classes;\n\n");
2233 }
2234 fprintf(stream, "*/\n\n");
2235 (*op2)->generate(types, *this);
2236 }
2237 else if (*op2 && (*op2)->output)
2238 { if (!(*op2)->input)
2239 method_name = (*op2)->output_name;
2240 else
2241 method_name = (*op2)->input_name;
2242 banner("Service Operation", method_name);
2243 fprintf(stream, "\n/// Operation \"%s\" of service binding \"%s\"\n\n/**\n\nOperation details:\n", method_name, name);
2244 if ((*op2)->documentation)
2245 text((*op2)->documentation);
2246 if ((*op2)->operation_documentation)
2247 text((*op2)->operation_documentation);
2248 if ((*op2)->output->documentation)
2249 { fprintf(stream, "Output response:\n");
2250 text((*op2)->output->documentation);
2251 }
2252 if ((*op2)->output->ext_documentation)
2253 { fprintf(stream, "Output response:\n");
2254 text((*op2)->output->ext_documentation);
2255 }
2256 gen_policy(*this, (*op2)->policy, "operation", types);
2257 gen_policy(*this, (*op2)->output->policy, "response message", types);
2258 fprintf(stream, "\n - One-way service response message\n");
2259 if ((*op2)->mep)
2260 fprintf(stream, "\n - SOAP MEP: \"%s\"\n", ((*op2)->mep));
2261 if ((*op2)->style == document)
2262 fprintf(stream, "\n - %s document/literal style messaging\n", (*op2)->protocol);
2263 else
2264 { if ((*op2)->output->use == literal)
2265 fprintf(stream, "\n - %s RPC literal messaging\n", (*op2)->protocol);
2266 else if ((*op2)->output->encodingStyle)
2267 fprintf(stream, "\n - %s RPC encodingStyle=\"%s\"\n", (*op2)->output->encodingStyle, (*op2)->protocol);
2268 else
2269 fprintf(stream, "\n - %s RPC encoded messaging\n", (*op2)->protocol);
2270 }
2271 if ((*op2)->action)
2272 { if (*(*op2)->action)
2273 fprintf(stream, "\n - Action: \"%s\"\n", (*op2)->action);
2274 }
2275 if ((*op2)->output)
2276 { if ((*op2)->output->action)
2277 fprintf(stream, "\n - Addressing output action: \"%s\"\n", (*op2)->output->action);
2278 }
2279 for (vector<Message*>::const_iterator outfault = (*op2)->outfault.begin(); outfault != (*op2)->outfault.end(); ++outfault)
2280 { if ((*outfault)->message)
2281 { if ((*outfault)->use == literal)
2282 { for (vector<wsdl__part>::const_iterator part = (*outfault)->message->part.begin(); part != (*outfault)->message->part.end(); ++part)
2283 { if ((*part).element)
2284 fprintf(stream, "\n - SOAP Output Fault: %s (literal)\n", (*part).element);
2285 else if ((*part).name && (*part).type)
2286 fprintf(stream, "\n - SOAP Output Fault: %s (literal)\n", (*part).name);
2287 }
2288 }
2289 else if ((*outfault)->message->name)
2290 fprintf(stream, "\n - SOAP Output Fault: %s\n", (*outfault)->name);
2291 if ((*outfault)->message->name && (*outfault)->action)
2292 fprintf(stream, " - SOAP Output Fault addressing action: \"%s\"\n", (*outfault)->action);
2293 }
2294 else if ((*outfault)->name)
2295 fprintf(stream, "\n - SOAP Output Fault: %s (literal)\n", (*outfault)->name);
2296 gen_policy(*this, (*outfault)->policy, "fault message", types);
2297 }
2298 if (!(*op2)->output->header.empty())
2299 fprintf(stream, "\n - Response message has mandatory header part(s) (see @ref SOAP_ENV__Header):\n");
2300 for (vector<soap__header>::const_iterator outputheader = (*op2)->output->header.begin(); outputheader != (*op2)->output->header.end(); ++outputheader)
2301 { if ((*outputheader).part)
2302 { if ((*outputheader).use == encoded && (*outputheader).namespace_)
2303 fprintf(stream, " - %s\n", types.aname(NULL, (*outputheader).namespace_, (*outputheader).part));
2304 else if ((*outputheader).partPtr() && (*outputheader).partPtr()->element)
2305 fprintf(stream, " - %s\n", types.aname(NULL, NULL, (*outputheader).partPtr()->element));
2306 }
2307 }
2308 if ((*op2)->output->multipartRelated)
2309 { int k = 2;
2310 fprintf(stream, "\n - Response message MIME multipart/related attachments:\n");
2311 for (vector<mime__part>::const_iterator part = (*op2)->output->multipartRelated->part.begin(); part != (*op2)->output->multipartRelated->part.end(); ++part)
2312 { if ((*part).soap__body_)
2313 { fprintf(stream, " -# MIME attachment with SOAP Body and mandatory header part(s):\n");
2314 for (vector<soap__header>::const_iterator header = (*part).soap__header_.begin(); header != (*part).soap__header_.end(); ++header)
2315 { if ((*header).part)
2316 { if ((*header).use == encoded && (*header).namespace_)
2317 fprintf(stream, " - %s\n", types.aname(NULL, (*header).namespace_, (*header).part));
2318 else if ((*header).partPtr() && (*header).partPtr()->element)
2319 fprintf(stream, " - %s\n", types.aname(NULL, NULL, (*header).partPtr()->element));
2320 }
2321 }
2322 }
2323 else
2324 { fprintf(stream, " -# MIME attachment %d:\n", k++);
2325 for (vector<mime__content>::const_iterator content = (*part).content.begin(); content != (*part).content.end(); ++content)
2326 { fprintf(stream, " -");
2327 if ((*content).part)
2328 { fprintf(stream, " part=\"");
2329 text((*content).part);
2330 fprintf(stream, "\"");
2331 }
2332 if ((*content).type)
2333 { fprintf(stream, " type=\"");
2334 text((*content).type);
2335 fprintf(stream, "\"");
2336 }
2337 fprintf(stream, "\n");
2338 }
2339 }
2340 }
2341 }
2342 if ((*op2)->output->layout)
2343 fprintf(stream, "\n - Response message has DIME attachments in compliance with %s\n", (*op2)->output->layout);
2344 fprintf(stream, "\nC stub function (defined in soapClient.c[pp] generated by soapcpp2):\n@code\n int soap_call_%s(\n struct soap *soap,\n NULL, // char *endpoint = NULL selects default endpoint for this operation\n NULL, // char *action = NULL selects default action for this operation\n // parameters:", method_name);
2345 (*op2)->output->generate(types, ",", false, false, false, false);
2346 fprintf(stream, "\n );\n@endcode\n\nC server function (called from the service dispatcher defined in soapServer.c[pp]):\n@code\n int %s(\n struct soap *soap,\n // parameters:", method_name);
2347 (*op2)->output->generate(types, ",", false, false, false, false);
2348 fprintf(stream, "\n );\n@endcode\n\n");
2349 if (!cflag)
2350 { fprintf(stream, "C++ proxy class (defined in soap%sProxy.h):\n", name);
2351 fprintf(stream, "@code\n class %sProxy;\n@endcode\n", name);
2352 fprintf(stream, "Important: use soapcpp2 option '-j' (or '-i') to generate greatly improved and easy-to-use proxy classes;\n\n");
2353 fprintf(stream, "C++ service class (defined in soap%sService.h):\n", name);
2354 fprintf(stream, "@code\n class %sService;\n@endcode\n", name);
2355 fprintf(stream, "Important: use soapcpp2 option '-j' (or '-i') to generate greatly improved and easy-to-use service classes;\n\n");
2356 }
2357 fprintf(stream, "*/\n\n");
2358 (*op2)->generate(types, *this);
2359 }
2360 }
2361 gen_policy_enablers(*this);
2362 }
2363
2364 void Service::add_import(const char *s)
2365 { if (find_if(imports.begin(), imports.end(), eqstr(s)) == imports.end())
2366 imports.push_back(s);
2367 }
2368
2369 void Service::del_import(const char *s)
2370 { VectorOfString::iterator i = find_if(imports.begin(), imports.end(), eqstr(s));
2371 if (i != imports.end())
2372 imports.erase(i);
2373 }
2374
2375 ////////////////////////////////////////////////////////////////////////////////
2376 //
2377 // Operation methods
2378 //
2379 ////////////////////////////////////////////////////////////////////////////////
2380
2381 void Operation::generate(Types &types, Service &service)
2382 { bool flag = false, anonymous = ((style != document) && parameterOrder != NULL);
2383 const char *method_name = NULL;
2384 if (output)
2385 { if (style == document)
2386 flag = (output->element || (output->message && output->message->part.size() == 1));
2387 else if (!wflag)
2388 flag = (output->element || (output->message && output->use == encoded && output->message->part.size() == 1 && !(*output->message->part.begin()).simpleTypePtr() && !(*output->message->part.begin()).complexTypePtr()));
2389 if (flag && input && input->message && (*output->message->part.begin()).element)
2390 for (vector<wsdl__part>::const_iterator part = input->message->part.begin(); part != input->message->part.end(); ++part)
2391 if ((*part).element && !strcmp((*part).element, (*output->message->part.begin()).element))
2392 flag = false;
2393 }
2394 if (output && output_name && bflag) // (output && (!input || bflag))
2395 { if (input)
2396 { method_name = strstr(output_name + 1, "__");
2397 if (method_name)
2398 method_name += 2;
2399 else
2400 method_name = output_name;
2401 }
2402 else
2403 { method_name = strstr(input_name + 1, "__");
2404 if (method_name)
2405 method_name += 2;
2406 else
2407 method_name = input_name;
2408 }
2409 if (protocol)
2410 fprintf(stream, serviceformat, prefix, "method-protocol", method_name, protocol);
2411 if (output->content && output->content->type)
2412 fprintf(stream, serviceformat, prefix, "method-mime-type", method_name, output->content->type);
2413 else if (style == document)
2414 fprintf(stream, serviceformat, prefix, "method-style", method_name, "document");
2415 else
2416 fprintf(stream, serviceformat, prefix, "method-style", method_name, "rpc");
2417 if (output->use == literal)
2418 fprintf(stream, serviceformat, prefix, "method-encoding", method_name, "literal");
2419 else if (output->encodingStyle)
2420 fprintf(stream, serviceformat, prefix, "method-encoding", method_name, output->encodingStyle);
2421 else
2422 fprintf(stream, serviceformat, prefix, "method-encoding", method_name, "encoded");
2423 if (output && output->action && *output->action)
2424 fprintf(stream, serviceformat, prefix, "method-action", method_name, output->action);
2425 else if (action)
2426 { if (*action)
2427 fprintf(stream, serviceformat, prefix, "method-action", method_name, action);
2428 else
2429 fprintf(stream, serviceformat, prefix, "method-action", method_name, "\"\"");
2430 }
2431 for (vector<Message*>::const_iterator message = outfault.begin(); message != outfault.end(); ++message)
2432 { if ((*message)->message)
2433 { if ((*message)->use == literal)
2434 { for (vector<wsdl__part>::const_iterator part = (*message)->message->part.begin(); part != (*message)->message->part.end(); ++part)
2435 { if ((*part).element)
2436 fprintf(stream, serviceformat, prefix, "method-fault", method_name, types.aname(NULL, NULL, (*part).element));
2437 else if ((*part).type)
2438 fprintf(stream, serviceformat, prefix, "method-fault", method_name, types.aname(NULL, (*message)->URI, (*part).name));
2439 }
2440 }
2441 else
2442 { if ((*message)->message->name)
2443 fprintf(stream, serviceformat, prefix, "method-fault", method_name, (*message)->name);
2444 }
2445 if ((*message)->action)
2446 fprintf(stream, serviceformat, prefix, "method-fault-action", method_name, (*message)->action);
2447 }
2448 else if ((*message)->name)
2449 fprintf(stream, serviceformat, prefix, "method-fault", method_name, (*message)->name);
2450 }
2451 if (output->multipartRelated)
2452 { for (vector<mime__part>::const_iterator outputmime = output->multipartRelated->part.begin(); outputmime != output->multipartRelated->part.end(); ++outputmime)
2453 { for (vector<soap__header>::const_iterator outputheader = (*outputmime).soap__header_.begin(); outputheader != (*outputmime).soap__header_.end(); ++outputheader)
2454 { if ((*outputheader).part)
2455 { if ((*outputheader).use == encoded && (*outputheader).namespace_)
2456 fprintf(stream, serviceformat, prefix, "method-header-part", method_name, types.aname(NULL, (*outputheader).namespace_, (*outputheader).part));
2457 else if ((*outputheader).partPtr() && (*outputheader).partPtr()->element)
2458 fprintf(stream, serviceformat, prefix, "method-header-part", method_name, types.aname(NULL, NULL, (*outputheader).partPtr()->element));
2459 }
2460 }
2461 for (vector<mime__content>::const_iterator content = (*outputmime).content.begin(); content != (*outputmime).content.end(); ++content)
2462 if ((*content).type)
2463 fprintf(stream, serviceformat, prefix, "method-mime-type", method_name, (*content).type);
2464 }
2465 }
2466 // TODO: add headerfault directives
2467 for (vector<soap__header>::const_iterator outputheader = output->header.begin(); outputheader != output->header.end(); ++outputheader)
2468 { if ((*outputheader).part)
2469 { if ((*outputheader).use == encoded && (*outputheader).namespace_)
2470 fprintf(stream, serviceformat, prefix, "method-header-part", method_name, types.aname(NULL, (*outputheader).namespace_, (*outputheader).part));
2471 else if ((*outputheader).partPtr() && (*outputheader).partPtr()->element)
2472 fprintf(stream, serviceformat, prefix, "method-header-part", method_name, types.aname(NULL, NULL, (*outputheader).partPtr()->element));
2473 }
2474 }
2475 for (vector<wsoap__header>::const_iterator outputwheader = output->wheader.begin(); outputwheader != output->wheader.end(); ++outputwheader)
2476 { if ((*outputwheader).element)
2477 fprintf(stream, serviceformat, prefix, "method-header-part", method_name, types.aname(NULL, NULL, (*outputwheader).element));
2478 }
2479 if (input)
2480 { fprintf(stream, "/// Operation response \"%s\" of operation \"%s\"\n", output_name, input_name);
2481 fprintf(stream, "int %s(", output_name);
2482 }
2483 else
2484 fprintf(stream, "int %s(", input_name);
2485 output->generate(types, ",", anonymous, true, false, false);
2486 fprintf(stream, "\n void\t///< One-way message: no output parameter\n);\n");
2487 }
2488 if (!input && output && output_name) // (!input && output && bflag)
2489 { method_name = strstr(output_name + 1, "__");
2490 if (method_name)
2491 method_name += 2;
2492 else
2493 method_name = output_name;
2494 if (protocol)
2495 fprintf(stream, serviceformat, prefix, "method-protocol", method_name, protocol);
2496 if (output->content && output->content->type)
2497 fprintf(stream, serviceformat, prefix, "method-mime-type", method_name, output->content->type);
2498 else if (style == document)
2499 fprintf(stream, serviceformat, prefix, "method-style", method_name, "document");
2500 else
2501 fprintf(stream, serviceformat, prefix, "method-style", method_name, "rpc");
2502 if (output->use == literal)
2503 fprintf(stream, serviceformat, prefix, "method-encoding", method_name, "literal");
2504 else if (output->encodingStyle)
2505 fprintf(stream, serviceformat, prefix, "method-encoding", method_name, output->encodingStyle);
2506 else
2507 fprintf(stream, serviceformat, prefix, "method-encoding", method_name, "encoded");
2508 if (output && output->action && *output->action)
2509 fprintf(stream, serviceformat, prefix, "method-action", method_name, output->action);
2510 else if (action)
2511 { if (*action)
2512 fprintf(stream, serviceformat, prefix, "method-action", method_name, action);
2513 else
2514 fprintf(stream, serviceformat, prefix, "method-action", method_name, "\"\"");
2515 }
2516 for (vector<Message*>::const_iterator message = outfault.begin(); message != outfault.end(); ++message)
2517 { if ((*message)->message)
2518 { if ((*message)->use == literal)
2519 { for (vector<wsdl__part>::const_iterator part = (*message)->message->part.begin(); part != (*message)->message->part.end(); ++part)
2520 { if ((*part).element)
2521 fprintf(stream, serviceformat, prefix, "method-fault", method_name, types.aname(NULL, NULL, (*part).element));
2522 else if ((*part).type)
2523 fprintf(stream, serviceformat, prefix, "method-fault", method_name, types.aname(NULL, (*message)->URI, (*part).name));
2524 }
2525 }
2526 else
2527 { if ((*message)->message->name)
2528 fprintf(stream, serviceformat, prefix, "method-fault", method_name, (*message)->name);
2529 }
2530 if ((*message)->action)
2531 fprintf(stream, serviceformat, prefix, "method-fault-action", method_name, (*message)->action);
2532 }
2533 else if ((*message)->name)
2534 fprintf(stream, serviceformat, prefix, "method-fault", method_name, (*message)->name);
2535 }
2536 if (output->multipartRelated)
2537 { for (vector<mime__part>::const_iterator outputmime = output->multipartRelated->part.begin(); outputmime != output->multipartRelated->part.end(); ++outputmime)
2538 { for (vector<soap__header>::const_iterator outputheader = (*outputmime).soap__header_.begin(); outputheader != (*outputmime).soap__header_.end(); ++outputheader)
2539 { if ((*outputheader).part)
2540 { if ((*outputheader).use == encoded && (*outputheader).namespace_)
2541 fprintf(stream, serviceformat, prefix, "method-header-part", method_name, types.aname(NULL, (*outputheader).namespace_, (*outputheader).part));
2542 else if ((*outputheader).partPtr() && (*outputheader).partPtr()->element)
2543 fprintf(stream, serviceformat, prefix, "method-header-part", method_name, types.aname(NULL, NULL, (*outputheader).partPtr()->element));
2544 }
2545 }
2546 for (vector<mime__content>::const_iterator content = (*outputmime).content.begin(); content != (*outputmime).content.end(); ++content)
2547 if ((*content).type)
2548 fprintf(stream, serviceformat, prefix, "method-mime-type", method_name, (*content).type);
2549 }
2550 }
2551 // TODO: add headerfault directives
2552 for (vector<soap__header>::const_iterator outputheader = output->header.begin(); outputheader != output->header.end(); ++outputheader)
2553 { if ((*outputheader).part)
2554 { if ((*outputheader).use == encoded && (*outputheader).namespace_)
2555 fprintf(stream, serviceformat, prefix, "method-header-part", method_name, types.aname(NULL, (*outputheader).namespace_, (*outputheader).part));
2556 else if ((*outputheader).partPtr() && (*outputheader).partPtr()->element)
2557 fprintf(stream, serviceformat, prefix, "method-header-part", method_name, types.aname(NULL, NULL, (*outputheader).partPtr()->element));
2558 }
2559 }
2560 for (vector<wsoap__header>::const_iterator outputwheader = output->wheader.begin(); outputwheader != output->wheader.end(); ++outputwheader)
2561 { if ((*outputwheader).element)
2562 fprintf(stream, serviceformat, prefix, "method-header-part", method_name, types.aname(NULL, NULL, (*outputwheader).element));
2563 }
2564 fprintf(stream, "int %s(", output_name);
2565 if (flag)
2566 { if (style == rpc && output->message && (*output->message->part.begin()).name)
2567 { fprintf(stream, "\n");
2568 fprintf(stream, anonymous ? anonformat : paraformat, types.tname(NULL, NULL, (*output->message->part.begin()).type), cflag ? "*" : "&", types.aname(NULL, NULL, (*output->message->part.begin()).name), "");
2569 fprintf(stream, "\t///< Output parameter");
2570 }
2571 else
2572 output->generate(types, "", anonymous, true, true, false);
2573 }
2574 else
2575 { fprintf(stream, "\n struct %-28s%s", output_name, cflag ? "*" : "&");
2576 fprintf(stream, "\t///< Output response struct parameter");
2577 }
2578 fprintf(stream, "\n);\n");
2579 }
2580 if (input && input_name)
2581 { method_name = strstr(input_name + 1, "__");
2582 if (method_name)
2583 method_name += 2;
2584 else
2585 method_name = input_name;
2586 if (protocol)
2587 fprintf(stream, serviceformat, prefix, "method-protocol", method_name, protocol);
2588 if (input->content && input->content->type)
2589 fprintf(stream, serviceformat, prefix, "method-mime-type", method_name, input->content->type);
2590 else if (style == document)
2591 fprintf(stream, serviceformat, prefix, "method-style", method_name, "document");
2592 else
2593 fprintf(stream, serviceformat, prefix, "method-style", method_name, "rpc");
2594 if (output && output->content && output->content->type)
2595 fprintf(stream, serviceformat, prefix, "method-output-mime-type", method_name, output->content->type);
2596 if (!input || input->use == literal)
2597 fprintf(stream, serviceformat, prefix, "method-encoding", method_name, "literal");
2598 else if (input->encodingStyle)
2599 fprintf(stream, serviceformat, prefix, "method-encoding", method_name, input->encodingStyle);
2600 else
2601 fprintf(stream, serviceformat, prefix, "method-encoding", method_name, "encoded");
2602 if (output)
2603 { if (!input || input->use != output->use)
2604 { if (output->use == literal)
2605 fprintf(stream, serviceformat, prefix, "method-response-encoding", method_name, "literal");
2606 else if (output->encodingStyle)
2607 fprintf(stream, serviceformat, prefix, "method-response-encoding", method_name, output->encodingStyle);
2608 else
2609 fprintf(stream, serviceformat, prefix, "method-response-encoding", method_name, "encoded");
2610 }
2611 if (style == rpc && (!input || (input->URI && output->URI && strcmp(input->URI, output->URI))))
2612 fprintf(stream, schemaformat, types.nsprefix(NULL, output->URI), "namespace", output->URI);
2613 }
2614 if (input && input->action && *input->action)
2615 fprintf(stream, serviceformat, prefix, "method-input-action", method_name, input->action);
2616 else if (action)
2617 { if (*action)
2618 fprintf(stream, serviceformat, prefix, "method-action", method_name, action);
2619 else
2620 fprintf(stream, serviceformat, prefix, "method-action", method_name, "\"\"");
2621 }
2622 if (output && output->action && *output->action)
2623 fprintf(stream, serviceformat, prefix, "method-output-action", method_name, output->action);
2624 for (vector<Message*>::const_iterator message = outfault.begin(); message != outfault.end(); ++message)
2625 { if ((*message)->message)
2626 { if ((*message)->use == literal)
2627 { for (vector<wsdl__part>::const_iterator part = (*message)->message->part.begin(); part != (*message)->message->part.end(); ++part)
2628 { if ((*part).element)
2629 fprintf(stream, serviceformat, prefix, "method-fault", method_name, types.aname(NULL, NULL, (*part).element));
2630 else if ((*part).type)
2631 fprintf(stream, serviceformat, prefix, "method-fault", method_name, types.aname(NULL, (*message)->URI, (*part).name));
2632 }
2633 }
2634 else
2635 { if ((*message)->message->name)
2636 fprintf(stream, serviceformat, prefix, "method-fault", method_name, (*message)->name);
2637 }
2638 if ((*message)->action)
2639 fprintf(stream, serviceformat, prefix, "method-fault-action", method_name, (*message)->action);
2640 }
2641 else if ((*message)->name)
2642 fprintf(stream, serviceformat, prefix, "method-fault", method_name, (*message)->name);
2643 }
2644 if (input)
2645 { if (input->multipartRelated)
2646 { for (vector<mime__part>::const_iterator inputmime = input->multipartRelated->part.begin(); inputmime != input->multipartRelated->part.end(); ++inputmime)
2647 { for (vector<soap__header>::const_iterator inputheader = (*inputmime).soap__header_.begin(); inputheader != (*inputmime).soap__header_.end(); ++inputheader)
2648 { if ((*inputheader).part)
2649 { if ((*inputheader).use == encoded && (*inputheader).namespace_)
2650 fprintf(stream, serviceformat, prefix, "method-input-header-part", method_name, types.aname(NULL, (*inputheader).namespace_, (*inputheader).part));
2651 else if ((*inputheader).partPtr() && (*inputheader).partPtr()->element)
2652 fprintf(stream, serviceformat, prefix, "method-input-header-part", method_name, types.aname(NULL, NULL, (*inputheader).partPtr()->element));
2653 }
2654 }
2655 for (vector<mime__content>::const_iterator content = (*inputmime).content.begin(); content != (*inputmime).content.end(); ++content)
2656 if ((*content).type)
2657 fprintf(stream, serviceformat, prefix, "method-input-mime-type", method_name, (*content).type);
2658 }
2659 }
2660 // TODO: add headerfault directives
2661 for (vector<soap__header>::const_iterator inputheader = input->header.begin(); inputheader != input->header.end(); ++inputheader)
2662 { if ((*inputheader).part)
2663 { if ((*inputheader).use == encoded && (*inputheader).namespace_)
2664 fprintf(stream, serviceformat, prefix, "method-input-header-part", method_name, types.aname(NULL, (*inputheader).namespace_, (*inputheader).part));
2665 else if ((*inputheader).partPtr() && (*inputheader).partPtr()->element)
2666 fprintf(stream, serviceformat, prefix, "method-input-header-part", method_name, types.aname(NULL, NULL, (*inputheader).partPtr()->element));
2667 }
2668 }
2669 for (vector<wsoap__header>::const_iterator inputwheader = input->wheader.begin(); inputwheader != input->wheader.end(); ++inputwheader)
2670 { if ((*inputwheader).element)
2671 fprintf(stream, serviceformat, prefix, "method-input-header-part", method_name, types.aname(NULL, NULL, (*inputwheader).element));
2672 }
2673 }
2674 if (output)
2675 { if (output->multipartRelated)
2676 { for (vector<mime__part>::const_iterator outputmime = output->multipartRelated->part.begin(); outputmime != output->multipartRelated->part.end(); ++outputmime)
2677 { for (vector<soap__header>::const_iterator outputheader = (*outputmime).soap__header_.begin(); outputheader != (*outputmime).soap__header_.end(); ++outputheader)
2678 { if ((*outputheader).part)
2679 { if ((*outputheader).use == encoded && (*outputheader).namespace_)
2680 fprintf(stream, serviceformat, prefix, "method-output-header-part", method_name, types.aname(NULL, (*outputheader).namespace_, (*outputheader).part));
2681 else if ((*outputheader).partPtr() && (*outputheader).partPtr()->element)
2682 fprintf(stream, serviceformat, prefix, "method-output-header-part", method_name, types.aname(NULL, NULL, (*outputheader).partPtr()->element));
2683 }
2684 }
2685 for (vector<mime__content>::const_iterator content = (*outputmime).content.begin(); content != (*outputmime).content.end(); ++content)
2686 if ((*content).type)
2687 fprintf(stream, serviceformat, prefix, "method-output-mime-type", method_name, (*content).type);
2688 }
2689 }
2690 for (vector<soap__header>::const_iterator outputheader = output->header.begin(); outputheader != output->header.end(); ++outputheader)
2691 { if ((*outputheader).part)
2692 { if ((*outputheader).use == encoded && (*outputheader).namespace_)
2693 fprintf(stream, serviceformat, prefix, "method-output-header-part", method_name, types.aname(NULL, (*outputheader).namespace_, (*outputheader).part));
2694 else if ((*outputheader).partPtr() && (*outputheader).partPtr()->element)
2695 fprintf(stream, serviceformat, prefix, "method-output-header-part", method_name, types.aname(NULL, NULL, (*outputheader).partPtr()->element));
2696 }
2697 }
2698 for (vector<wsoap__header>::const_iterator outputwheader = output->wheader.begin(); outputwheader != output->wheader.end(); ++outputwheader)
2699 { if ((*outputwheader).element)
2700 fprintf(stream, serviceformat, prefix, "method-output-header-part", method_name, types.aname(NULL, NULL, (*outputwheader).element));
2701 }
2702 }
2703 if (input)
2704 fprintf(stream, "int %s(", input_name);
2705 else
2706 fprintf(stream, "int %s(", output_name);
2707 if (input)
2708 input->generate(types, ",", anonymous, true, false, false);
2709 if (output)
2710 { if (flag)
2711 { if (style == rpc && output->message && (*output->message->part.begin()).name)
2712 { fprintf(stream, "\n");
2713 fprintf(stream, anonymous ? anonformat : paraformat, types.tname(NULL, NULL, (*output->message->part.begin()).type), cflag ? "*" : "&", types.aname(NULL, NULL, (*output->message->part.begin()).name), "");
2714 fprintf(stream, "\t///< Output parameter");
2715 }
2716 else
2717 output->generate(types, "", anonymous, true, true, false);
2718 }
2719 else
2720 { fprintf(stream, "\n struct %-28s%s", output_name, cflag ? "*" : "&");
2721 fprintf(stream, "\t///< Output response struct parameter");
2722 }
2723 fprintf(stream, "\n);\n");
2724 }
2725 else
2726 fprintf(stream, "\n void\t///< One-way message: no output parameter\n);\n");
2727 }
2728 }
2729
2730 ////////////////////////////////////////////////////////////////////////////////
2731 //
2732 // Message methods
2733 //
2734 ////////////////////////////////////////////////////////////////////////////////
2735
2736 void Message::generate(Types &types, const char *sep, bool anonymous, bool remark, bool response, bool optional)
2737 { if (message)
2738 { for (vector<wsdl__part>::const_iterator part = message->part.begin(); part != message->part.end(); ++part)
2739 { if (!(*part).name)
2740 fprintf(stderr, "\nError: no part name in message '%s'\n", message->name?message->name:"");
2741 else if (!body_parts || soap_tagsearch(body_parts, (*part).name))
2742 { if (remark && (*part).documentation)
2743 comment("", (*part).name, "parameter", (*part).documentation);
2744 else
2745 fprintf(stream, "\n");
2746 if ((*part).element)
2747 { if ((*part).elementPtr())
2748 { const char *name, *type, *nameURI = NULL, *typeURI = NULL, *prefix = NULL;
2749 if (style == rpc && use == encoded)
2750 name = (*part).name;
2751 else
2752 { name = (*part).elementPtr()->name;
2753 if (style == document && (*part).elementPtr()->schemaPtr())
2754 nameURI = (*part).elementPtr()->schemaPtr()->targetNamespace;
2755 }
2756 if ((*part).elementPtr()->type)
2757 type = (*part).elementPtr()->type;
2758 else
2759 { type = (*part).elementPtr()->name;
2760 prefix = "_";
2761 if ((*part).elementPtr()->schemaPtr())
2762 typeURI = (*part).elementPtr()->schemaPtr()->targetNamespace;
2763 }
2764 if ((*part).elementPtr()->xmime__expectedContentTypes)
2765 fprintf(stream, " /// MTOM attachment with content types %s\n", (*part).elementPtr()->xmime__expectedContentTypes);
2766 if (response)
2767 { const char *t = types.tname(prefix, typeURI, type);
2768 bool flag = (strchr(t, '*') && strcmp(t, "char*") && strcmp(t, "char *"));
2769 fprintf(stream, anonymous ? anonformat : paraformat, t, flag ? " " : cflag ? "*" : "&", types.aname(NULL, nameURI, name), sep);
2770 if (remark)
2771 fprintf(stream, "\t///< Output parameter");
2772 }
2773 else
2774 { fprintf(stream, anonymous ? anonformat : paraformat, types.pname(optional, prefix, typeURI, type), " ", types.aname(NULL, nameURI, name), sep);
2775 if (remark && *sep == ',')
2776 fprintf(stream, "\t///< Input parameter");
2777 }
2778 }
2779 else
2780 { fprintf(stream, anonymous ? anonformat : paraformat, types.pname(optional, NULL, NULL, (*part).element), " ", types.aname(NULL, NULL, (*part).element), sep);
2781 if (remark)
2782 fprintf(stream, "\t///< TODO: Check element type (imported type)");
2783 }
2784 }
2785 else if ((*part).type)
2786 { if (response)
2787 { const char *t = types.tname(NULL, NULL, (*part).type);
2788 bool flag = (strchr(t, '*') && strcmp(t, "char*") && strcmp(t, "char *"));
2789 fprintf(stream, anonymous ? anonformat : paraformat, t, flag ? " " : cflag ? "*" : "&", types.aname(NULL, NULL, (*part).name), sep);
2790 if (remark)
2791 fprintf(stream, "\t///< Output parameter");
2792 }
2793 else
2794 { fprintf(stream, anonymous ? anonformat : paraformat, types.pname(optional, NULL, NULL, (*part).type), " ", types.aname(NULL, NULL, (*part).name), sep);
2795 if (remark && *sep == ',')
2796 fprintf(stream, "\t///< Input parameter");
2797 }
2798 }
2799 else
2800 fprintf(stderr, "\nError: no wsdl:definitions/message/part/@type in part '%s'\n", (*part).name);
2801 }
2802 }
2803 }
2804 else if (element) // WSDL 2.0
2805 { const char *prefix = NULL;
2806 const char *URI = NULL;
2807 const char *name = element->name;
2808 const char *type = element->type;
2809 if (!type)
2810 { type = name;
2811 prefix = "_";
2812 }
2813 if (element->schemaPtr())
2814 URI = element->schemaPtr()->targetNamespace;
2815 if (response)
2816 { const char *t = types.tname(prefix, URI, type);
2817 bool flag = (strchr(t, '*') && strcmp(t, "char*") && strcmp(t, "char *"));
2818 fprintf(stream, "\n");
2819 fprintf(stream, paraformat, t, flag ? " " : cflag ? "*" : "&", anonymous ? "" : types.aname(NULL, URI, name), sep);
2820 if (remark)
2821 fprintf(stream, "\t///< Output parameter");
2822 }
2823 else if (style == document || element->simpleTypePtr())
2824 { // WSDL 2.0 document style
2825 fprintf(stream, "\n");
2826 fprintf(stream, anonymous ? anonformat : paraformat, types.pname(optional, prefix, URI, type), " ", types.aname(NULL, URI, name), sep);
2827 if (remark && *sep == ',')
2828 fprintf(stream, "\t///< Input parameter");
2829 }
2830 else if (element->complexTypePtr())
2831 { // WSDL 2.0 RPC style
2832 xs__seqchoice *seq = element->complexTypePtr()->sequence;
2833 for (vector<xs__contents>::const_iterator i = seq->__contents.begin(); i != seq->__contents.end(); ++i)
2834 { if ((*i).__union == SOAP_UNION_xs__union_content_element)
2835 { name = (*i).__content.element->name;
2836 type = (*i).__content.element->type;
2837 if (!type)
2838 type = name;
2839 fprintf(stream, "\n");
2840 fprintf(stream, anonymous ? anonformat : paraformat, types.pname(optional, prefix, URI, type), " ", types.aname(NULL, NULL, name), sep);
2841 if (remark && *sep == ',')
2842 fprintf(stream, "\t///< Input parameter");
2843 }
2844 }
2845 }
2846 }
2847 }
2848
2849 ////////////////////////////////////////////////////////////////////////////////
2850 //
2851 // Miscellaneous
2852 //
2853 ////////////////////////////////////////////////////////////////////////////////
2854
2855 static const char *urienc(struct soap *soap, const char *uri)
2856 { const char *r, *s;
2857 char *t;
2858 size_t n = 0;
2859 if (!uri)
2860 return NULL;
2861 for (s = uri; *s; s++)
2862 if (!URI_CHAR(*s))
2863 n++;
2864 if (!n)
2865 return uri;
2866 n = strlen(uri) + 2*n;
2867 r = t = (char*)soap_malloc(soap, n + 1);
2868 for (s = uri; *s; s++)
2869 { if (URI_CHAR(*s))
2870 *t++ = *s;
2871 else
2872 { sprintf(t, "%%%.2x", *s);
2873 t += 3;
2874 }
2875 }
2876 *t = '\0';
2877 return r;
2878 }
2879
2880 static bool imported(const char *tag)
2881 { if (!tag || *tag != '"')
2882 return false;
2883 for (SetOfString::const_iterator u = exturis.begin(); u != exturis.end(); ++u)
2884 { size_t n = strlen(*u);
2885 if (!strncmp(*u, tag + 1, n) && tag[n+1] == '"')
2886 return true;
2887 }
2888 return false;
2889 }
2890
2891 static void comment(const char *start, const char *middle, const char *end, const char *text)
2892 { if (text)
2893 { if (strchr(text, '\r') || strchr(text, '\n'))
2894 fprintf(stream, "\n/** %s %s %s documentation:\n%s\n*/\n\n", start, middle, end, text);
2895 else
2896 fprintf(stream, "\n/// %s %s %s: %s\n", start, middle, end, text);
2897 }
2898 }
2899
2900 static void page(const char *page, const char *title, const char *text)
2901 { if (text)
2902 fprintf(stream, "\n@page %s%s \"%s\"\n", page, title, text);
2903 else
2904 fprintf(stream, "\n@page %s%s\n", page, title);
2905 }
2906
2907 static void section(const char *section, const char *title, const char *text)
2908 { if (text)
2909 fprintf(stream, "\n@section %s%s \"%s\"\n", section, title, text);
2910 else
2911 fprintf(stream, "\n@section %s%s\n", section, title);
2912 }
2913
2914 static void banner(const char *text)
2915 { int i;
2916 if (!text)
2917 return;
2918 fprintf(stream, "\n/");
2919 for (i = 0; i < 78; i++)
2920 fputc('*', stream);
2921 fprintf(stream, "\\\n *%76s*\n * %-75s*\n *%76s*\n\\", "", text, "");
2922 for (i = 0; i < 78; i++)
2923 fputc('*', stream);
2924 fprintf(stream, "/\n\n");
2925 if (vflag)
2926 fprintf(stderr, "\n----<< %s >>----\n\n", text);
2927 }
2928
2929 static void banner(const char *text1, const char *text2)
2930 { int i;
2931 if (!text1)
2932 return;
2933 fprintf(stream, "\n/");
2934 for (i = 0; i < 78; i++)
2935 fputc('*', stream);
2936 if (text2)
2937 fprintf(stream, "\\\n *%76s*\n * %-75s*\n * %-73s*\n *%76s*\n\\", "", text1, text2, "");
2938 else
2939 fprintf(stream, "\\\n *%76s*\n * %-75s*\n *%76s*\n\\", "", text1, "");
2940 for (i = 0; i < 78; i++)
2941 fputc('*', stream);
2942 fprintf(stream, "/\n\n");
2943 if (vflag)
2944 fprintf(stderr, "\n----<< %s: %s >>----\n\n", text1, text2?text2:"");
2945 }
2946
2947 static void ident()
2948 { time_t t = time(NULL), *p = &t;
2949 char tmp[256];
2950 int i;
2951 strftime(tmp, 256, "%Y-%m-%d %H:%M:%S GMT", gmtime(p));
2952 fprintf(stream, "/* %s\n Generated by wsdl2h " WSDL2H_VERSION " from ", outfile?outfile:"");
2953 if (infiles)
2954 { for (i = 0; i < infiles; i++)
2955 fprintf(stream, "%s ", infile[i]);
2956 }
2957 else
2958 fprintf(stream, "(stdin) ");
2959 fprintf(stream, "and %s\n %s\n\n DO NOT INCLUDE THIS FILE DIRECTLY INTO YOUR PROJECT BUILDS\n USE THE soapcpp2-GENERATED SOURCE CODE FILES FOR YOUR PROJECT BUILDS\n\n gSOAP XML Web services tools.\n Copyright (C) 2000-2013 Robert van Engelen, Genivia Inc. All Rights Reserved.\n Part of this software is released under one of the following licenses:\n GPL or Genivia's license for commercial use.\n*/\n\n", mapfile, tmp);
2960 }
2961
2962 void text(const char *text)
2963 { const char *s;
2964 if (!text)
2965 return;
2966 size_t k = 0;
2967 for (s = text; *s; s++, k++)
2968 { switch (*s)
2969 { case '\n':
2970 if (k)
2971 { fputc('\n', stream);
2972 k = 0;
2973 }
2974 break;
2975 case '\t':
2976 k = 8 * ((k + 8) / 8) - 1;
2977 fputc('\t', stream);
2978 break;
2979 case '/':
2980 fputc(*s, stream);
2981 if (s[1] == '*')
2982 fputc(' ', stream);
2983 break;
2984 case '*':
2985 fputc(*s, stream);
2986 if (s[1] == '/')
2987 fputc(' ', stream);
2988 break;
2989 case ' ':
2990 if (k >= 79)
2991 { fputc('\n', stream);
2992 k = 0;
2993 }
2994 else
2995 fputc(' ', stream);
2996 break;
2997 default:
2998 if (*s >= 32)
2999 fputc(*s, stream);
3000 }
3001 }
3002 if (k)
3003 fputc('\n', stream);
3004 }
3005
3006 ////////////////////////////////////////////////////////////////////////////////
3007 //
3008 // WS-Policy
3009 //
3010 ////////////////////////////////////////////////////////////////////////////////
3011
3012 static void gen_policy(Service& service, const vector<const wsp__Policy*>& policy, const char *text, Types& types)
3013 { if (!policy.empty())
3014 { fprintf(stream, "\n - WS-Policy applicable to the %s:\n", text);
3015 for (vector<const wsp__Policy*>::const_iterator p = policy.begin(); p != policy.end(); ++p)
3016 if (*p)
3017 (*p)->generate(service, types, 0);
3018 }
3019 }
3020
3021 static void gen_policy_enablers(const Service& service)
3022 { fprintf(stream, "\n/**\n");
3023 page(service.name, " Binding", service.name);
3024 section(service.name, "_policy_enablers Policy Enablers of Binding ", service.name);
3025 fprintf(stream, "\nBased on policies, this service imports");
3026 for (VectorOfString::const_iterator i = service.imports.begin(); i != service.imports.end(); ++i)
3027 fprintf(stream, " %s", *i);
3028 fprintf(stream, "\n\n - WS-Policy reminders and enablers:\n");
3029 fprintf(stream, " - WS-Addressing 1.0 (2005/08, accepts 2004/08):\n\t@code\n\t#import \"wsa5.h\" // to be added to this header file for the soapcpp2 build step\n\t@endcode\n\t@code\n\t#include \"plugin/wsaapi.h\"\n\tsoap_register_plugin(soap, soap_wsa); // register the wsa plugin in your code\n\t// See the user guide gsoap/doc/wsa/html/index.html\n\t@endcode\n");
3030 fprintf(stream, " - WS-Addressing (2004/08):\n\t@code\n\t#import \"wsa.h\" // to be added to this header file for the soapcpp2 build step\n\t@endcode\n\t@code\n\t#include \"plugin/wsaapi.h\"\n\tsoap_register_plugin(soap, soap_wsa); // register the wsa plugin in your code\n\t// See the user guide gsoap/doc/wsa/html/index.html\n\t@endcode\n");
3031 fprintf(stream, " - WS-ReliableMessaging 1.0:\n\t@code\n\t#import \"wsrm5.h\" // to be added to this header file for the soapcpp2 build step\n\t@endcode\n\t@code\n\t#include \"plugin/wsrmapi.h\"\n\tsoap_register_plugin(soap, soap_wsa); // register the wsa plugin in your code\n\tsoap_register_plugin(soap, soap_wsrm); // register the wsrm plugin in your code\n\t// See the user guide gsoap/doc/wsrm/html/index.html\n\t@endcode\n");
3032 fprintf(stream, " - WS-ReliableMessaging 1.1:\n\t@code\n\t#import \"wsrm.h\" // to be added to this header file for the soapcpp2 build step\n\t@endcode\n\t@code\n\t#include \"plugin/wsrmapi.h\"\n\tsoap_register_plugin(soap, soap_wsa); // register the wsa plugin in your code\n\tsoap_register_plugin(soap, soap_wsrm); // register the wsrm plugin in your code\n\t// See the user guide gsoap/doc/wsrm/html/index.html\n\t@endcode\n");
3033 fprintf(stream, " - WS-Security (SOAP Message Security) 1.0 (accepts 1.1):\n\t@code\n\t#import \"wsse.h\" // to be added to this header file for the soapcpp2 build step\n\t@endcode\n\t@code\n\t#include \"plugin/wsseapi.h\"\n\tsoap_register_plugin(soap, soap_wsse); // register the wsse plugin in your code\n\t// See the user guide gsoap/doc/wsse/html/index.html\n\t@endcode\n");
3034 fprintf(stream, " - WS-Security (SOAP Message Security) 1.1 (accepts 1.0):\n\t@code\n\t#import \"wsse11.h\" // to be added to this header file for the soapcpp2 build step\n\t@endcode\n\t@code\n\t#include \"plugin/wsseapi.h\"\n\tsoap_register_plugin(soap, soap_wsse); // register the wsse plugin in your code\n\t// See the user guide gsoap/doc/wsse/html/index.html\n\t@endcode\n");
3035 fprintf(stream, " - HTTP Digest Authentication:\n\t@code\n\t#include \"plugin/httpda.h\"\n\tsoap_register_plugin(soap, soap_http_da); // register the HTTP DA plugin in your code\n\t// See the user guide gsoap/doc/httpda/html/index.html\n\t@endcode\n");
3036 fprintf(stream, "*/\n\n");
3037 for (VectorOfString::const_iterator i = service.imports.begin(); i != service.imports.end(); ++i)
3038 fprintf(stream, "#import \"%s\"\n", *i);
3039 }