00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "xml.h"
00036 #include "str.h"
00037 #include "type.h"
00038 #include <alloc.h>
00039 #include <stack.h>
00040
00041 #include <apr_base64.h>
00042 #include <apr_strings.h>
00043 #include <apr_xml.h>
00044 #include <apr_uuid.h>
00045 #include <assert.h>
00046 #include <string.h>
00047 #include <stdio.h>
00048
00049
00050
00051
00052
00053
00054
00055
00056 static bs_status add_datatypes_to_xml(char **buf, const bs_definition *def,
00057 apr_pool_t *mp)
00058 {
00059 bs_uint16 i;
00060 char *collect = "";
00061
00062 for (i = 0; i < def->num_data_types; i++) {
00063 char *tmp;
00064 bs_data_type *type = def->data_types[i];
00065 tmp = apr_psprintf(mp, "<type name=\"%s\" />", type->name);
00066 collect = apr_pstrcat(mp, collect, tmp, NULL);
00067 }
00068
00069 *buf = apr_pstrcat(mp, *buf, collect, NULL);
00070 return BS_OK;
00071 }
00072
00073
00074 static bs_status add_message_part_to_xml(char **buf,
00075 const bs_message_part *part, apr_pool_t *mp)
00076 {
00077 char *collect = apr_psprintf(mp, "<part name=\"%s\" type=\"%s\"/>",
00078 part->name, part->type->name);
00079 *buf = apr_pstrcat(mp, *buf, collect, NULL);
00080 return BS_OK;
00081 }
00082
00083
00084 static bs_status add_message_to_xml(char **buf, const bs_message *msg,
00085 apr_pool_t *mp)
00086 {
00087 bs_status rv;
00088 int i;
00089 char *collect = apr_psprintf(mp, "<message name=\"%s\">", msg->name);
00090
00091 for (i = 0; i < msg->num_parts; i++) {
00092 rv = add_message_part_to_xml(&collect, msg->parts[i], mp);
00093 if (rv != BS_OK) return rv;
00094 }
00095
00096 *buf = apr_pstrcat(mp, *buf, collect, "</message>", NULL);
00097 return BS_OK;
00098 }
00099
00100
00101 static bs_status add_messages_to_xml(char **buf, const bs_definition *def,
00102 apr_pool_t *mp)
00103 {
00104 int i;
00105 bs_status rv;
00106
00107 for (i = 0; i < def->num_messages; i++) {
00108 rv = add_message_to_xml(buf, def->messages[i], mp);
00109 if (rv != BS_OK) return rv;
00110 }
00111
00112 return BS_OK;
00113 }
00114
00115
00116 static bs_status add_operation_to_xml(char **buf, const bs_operation *op,
00117 apr_pool_t *mp)
00118 {
00119 char *i = "", *o = "", *f = "";
00120 char *collect = apr_psprintf(mp, "<operation name=\"%s\">", op->name);
00121
00122 if (op->input)
00123 i = apr_psprintf(mp, "<input message=\"%s\"/>", op->input->name);
00124 if (op->output)
00125 o = apr_psprintf(mp, "<output message=\"%s\"/>", op->output->name);
00126 if (op->fault)
00127 f = apr_psprintf(mp, "<fault message=\"%s\"/>", op->fault->name);
00128
00129 *buf = apr_pstrcat(mp, *buf, collect, i, o, f, "</operation>", NULL);
00130 return BS_OK;
00131 }
00132
00133
00134 static bs_status add_port_type_to_xml(char **buf, const bs_port_type *pt,
00135 apr_pool_t *mp)
00136 {
00137 bs_status rv;
00138 unsigned i;
00139 char *collect = "";
00140
00141 collect = apr_psprintf(mp, "<portType name=\"%s\">", pt->name);
00142
00143 for (i = 0; i < pt->num_operations; i++) {
00144 rv = add_operation_to_xml(&collect, pt->operations[i], mp);
00145 if (rv != BS_OK) return rv;
00146 }
00147
00148 *buf = apr_pstrcat(mp, *buf, collect, "</portType>", NULL);
00149 return BS_OK;
00150 }
00151
00152
00153 static bs_status add_porttypes_to_xml(char **buf, const bs_definition *def,
00154 apr_pool_t *mp)
00155 {
00156 int i;
00157 bs_status rv;
00158
00159 for (i = 0; i < def->num_port_types; i++) {
00160 rv = add_port_type_to_xml(buf, def->port_types[i], mp);
00161 if (rv != BS_OK) return rv;
00162 }
00163
00164 return BS_OK;
00165 }
00166
00167
00168 static bs_status add_port_to_xml(char **buf, const bs_port *port,
00169 apr_pool_t *mp)
00170 {
00171 char *collect = apr_psprintf(mp, "<port name=\"%s\" type=\"%s\" />",
00172 port->name, port->port_type->name);
00173 *buf = apr_pstrcat(mp, *buf, collect, NULL);
00174 return BS_OK;
00175 }
00176
00177
00178 static bs_status add_service_to_xml(char **buf, const bs_service *sv,
00179 apr_pool_t *mp)
00180 {
00181 bs_status rv;
00182 unsigned i;
00183 char *collect = apr_psprintf(mp, "<service name=\"%s\">", sv->name);
00184
00185
00186 for (i = 0; i < sv->num_ports; i++) {
00187 rv = add_port_to_xml(&collect, sv->ports[i], mp);
00188 if (rv != BS_OK) return rv;
00189 }
00190
00191 *buf = apr_pstrcat(mp, *buf, collect, "</service>", NULL);
00192 return BS_OK;
00193 }
00194
00195
00196 static bs_status add_services_to_xml(char **buf, const bs_definition *def,
00197 apr_pool_t *mp)
00198 {
00199 unsigned i;
00200 bs_status rv;
00201
00202 for (i = 0; i < def->num_services; i++) {
00203 rv = add_service_to_xml(buf, def->services[i], mp);
00204 if (rv != BS_OK) return rv;
00205 }
00206
00207 return BS_OK;
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217 static bs_status add_use_service_to_xml(char **buf, const bs_service_request *def,
00218 apr_pool_t *mp)
00219 {
00220 char *collect = apr_psprintf(mp,
00221 "<use service=\"%s\" port=\"%s\" operation=\"%s\" />",
00222 def->service, def->port, def->operation);
00223 *buf = apr_pstrcat(mp, *buf, collect, NULL);
00224 return BS_OK;
00225 }
00226
00227
00228 static bs_status add_part_instance_to_xml(char **buf, const bs_part_instance *def,
00229 apr_pool_t *mp)
00230 {
00231 char *tmp, *data64;
00232 tmp = apr_psprintf(mp, "<part name=\"%s\" type=\"%s\" size=\"%" BS_UINT64_FMT "\">", def->name,
00233 def->type->name, def->size);
00234
00235
00236 if (def->type->builtin) data64 = def->data;
00237 else {
00238 data64 = apr_pcalloc(mp, apr_base64_encode_len(def->size) + 1);
00239 apr_base64_encode(data64, def->data, def->size);
00240 }
00241
00242 *buf = apr_pstrcat(mp, *buf, tmp, data64, "</part>", NULL);
00243 return BS_OK;
00244 }
00245
00246
00247 static bs_status add_message_instance_to_xml(char **buf, const bs_message_instance *def,
00248 char *type, apr_pool_t *mp)
00249 {
00250 bs_status rv;
00251 unsigned i;
00252 char *tmp, *tmp2, *collect = "";
00253 tmp = apr_psprintf(mp, "<%s message=\"%s\">", type, def->name);
00254
00255
00256 for (i = 0; i < def->num_parts; i++) {
00257 rv = add_part_instance_to_xml(&collect, def->parts[i], mp);
00258 if (rv != BS_OK) return rv;
00259 }
00260
00261 tmp2 = apr_psprintf(mp, "</%s>", type);
00262 *buf = apr_pstrcat(mp, *buf, tmp, collect, tmp2, NULL);
00263 return BS_OK;
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273 static bs_status add_used_service_to_xml(char **buf, const bs_service_response *def,
00274 apr_pool_t *mp)
00275 {
00276 char *collect = apr_psprintf(mp,
00277 "<used service=\"%s\" port=\"%s\" operation=\"%s\" />",
00278 def->service, def->port, def->operation);
00279 *buf = apr_pstrcat(mp, *buf, collect, NULL);
00280 return BS_OK;
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290 bs_status xlate_definition_to_xml(char **buf, bs_uint64 *size,
00291 const bs_definition *def, apr_pool_t *mp)
00292 {
00293 char *collect = apr_psprintf(mp, "<definitions name=\"%s\">", def->name);
00294 add_datatypes_to_xml(&collect, def, mp);
00295 add_messages_to_xml(&collect, def, mp);
00296 add_porttypes_to_xml(&collect, def, mp);
00297 add_services_to_xml(&collect, def, mp);
00298 *buf = apr_pstrcat(mp, collect, "</definitions>", NULL);
00299 *size = strlen(*buf);
00300 return BS_OK;
00301 }
00302
00303
00304 bs_status xlate_request_to_xml(char **buf, bs_uint64 *size,
00305 const bs_service_request *def, apr_pool_t *mp)
00306 {
00307 char *collect, uuid_format[APR_UUID_FORMATTED_LENGTH + 1];
00308
00309
00310 uuid_format[APR_UUID_FORMATTED_LENGTH] = '\0';
00311 apr_uuid_format(uuid_format, (apr_uuid_t *) &def->uuid);
00312 collect = apr_psprintf(mp, "<request uuid=\"%s\">", uuid_format);
00313
00314 add_use_service_to_xml(&collect, def, mp);
00315 add_message_instance_to_xml(&collect, def->input, "input", mp);
00316
00317 *buf = apr_pstrcat(mp, collect, "</request>", NULL);
00318 *size = strlen(*buf);
00319 return BS_OK;
00320 }
00321
00322
00323 bs_status xlate_response_to_xml(char **buf, bs_uint64 *size,
00324 const bs_service_response *def, apr_pool_t *mp)
00325 {
00326 char *collect, uuid_format[APR_UUID_FORMATTED_LENGTH + 1];
00327
00328
00329 uuid_format[APR_UUID_FORMATTED_LENGTH] = '\0';
00330 apr_uuid_format(uuid_format, (apr_uuid_t *) &def->uuid);
00331 collect = apr_psprintf(mp, "<response uuid=\"%s\">", uuid_format);
00332
00333 add_used_service_to_xml(&collect, def, mp);
00334 if (def->output)
00335 add_message_instance_to_xml(&collect, def->output, "output", mp);
00336 if (def->fault)
00337 add_message_instance_to_xml(&collect, def->fault, "fault", mp);
00338
00339 *buf = apr_pstrcat(mp, collect, "</response>", NULL);
00340 *size = strlen(*buf);
00341 return BS_OK;
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00354 static bs_data_type *process_data_type(const apr_xml_elem *type, apr_pool_t *mp)
00355 {
00356 const apr_xml_attr *attr;
00357 bs_data_type *ret = NULL;
00358
00359
00360 for (attr = type->attr; attr; attr = attr->next) {
00361 if (streq(attr->name, "name")) {
00362 ret = new_bs_data_type(mp, attr->value);
00363 break;
00364 }
00365 }
00366
00367 return ret;
00368 }
00369
00370
00375 static bs_data_type *lookup_data_type_by_name(const bs_definition *def, const char *name)
00376 {
00377
00378 bs_uint16 i;
00379 for (i = 0; i < def->num_data_types; i++) {
00380 bs_data_type *type = def->data_types[i];
00381 if (streq(type->name, name)) return type;
00382 }
00383 return NULL;
00384 }
00385
00386
00395 static bs_message *process_message(const apr_xml_elem *msg, bs_definition *def,
00396 apr_pool_t *mp)
00397 {
00398 const apr_xml_elem *part;
00399 const apr_xml_attr *attr;
00400 bs_message *m = NULL;
00401
00402
00403 for (attr = msg->attr; attr; attr = attr->next)
00404 if (streq(attr->name, "name"))
00405 m = new_bs_message(mp, attr->value, 0);
00406 if (!m) return NULL;
00407
00408
00409 for (part = msg->first_child; part; part = part->next) {
00410
00411 char *part_name = NULL;
00412 bs_data_type *part_type = NULL;
00413 bs_message_part *msg_part = NULL;
00414 for (attr = part->attr; attr; attr = attr->next) {
00415 if (streq(attr->name, "name"))
00416 part_name = apr_pstrdup(mp, attr->value);
00417 if (streq(attr->name, "type")) {
00418 part_type = lookup_data_type_by_name(def, attr->value);
00419 if (!part_type) return NULL;
00420 }
00421 }
00422 msg_part = new_bs_message_part(mp, part_name, part_type);
00423 add_part_to_message(m, msg_part, mp);
00424 }
00425 return m;
00426 }
00427
00428
00437 static bs_message *lookup_message_by_element(const apr_xml_elem *elem,
00438 const bs_definition *def, apr_pool_t *mp)
00439 {
00440 const apr_xml_attr *attr;
00441 char *message_name = NULL;
00442 bs_uint32 i;
00443
00444
00445 for (attr = elem->attr; attr; attr = attr->next)
00446 if (streq(attr->name, "message"))
00447 message_name = apr_pstrdup(mp, attr->value);
00448 if (!message_name) return NULL;
00449
00450
00451 for (i = 0; i < def->num_messages; i++) {
00452 bs_message *msg = def->messages[i];
00453 if (streq(msg->name, message_name)) return msg;
00454 }
00455 return NULL;
00456 }
00457
00458
00469 static bs_operation *process_operation(const apr_xml_elem *op, bs_definition *def,
00470 apr_pool_t *mp)
00471 {
00472 const apr_xml_elem *elem;
00473 const apr_xml_attr *attr;
00474 char *op_name = NULL;
00475 bs_message *input = NULL, *output = NULL, *fault = NULL;
00476
00477
00478 for (attr = op->attr; attr; attr = attr->next)
00479 if (streq(attr->name, "name"))
00480 op_name = apr_pstrdup(mp, attr->value);
00481 if (!op_name) return NULL;
00482
00483
00484 for (elem = op->first_child; elem; elem = elem->next) {
00485 if (streq(elem->name, "input")) {
00486 input = lookup_message_by_element(elem, def, mp);
00487 if (!input) return NULL;
00488 }
00489 else if (streq(elem->name, "output")) {
00490 output = lookup_message_by_element(elem, def, mp);
00491 if (!output) return NULL;
00492 }
00493 else if (streq(elem->name, "fault")) {
00494 fault = lookup_message_by_element(elem, def, mp);
00495 if (!fault) return NULL;
00496 }
00497 }
00498
00499 return new_bs_operation(mp, op_name, input, output, fault);
00500 }
00501
00502
00512 static bs_port_type *process_porttype(const apr_xml_elem *pt, bs_definition *def,
00513 apr_pool_t *mp)
00514 {
00515 const apr_xml_elem *operation;
00516 const apr_xml_attr *attr;
00517 bs_port_type *p = NULL;
00518
00519
00520 for (attr = pt->attr; attr; attr = attr->next)
00521 if (streq(attr->name, "name"))
00522 p = new_bs_port_type(mp, attr->value, 0);
00523 if (!p) return NULL;
00524
00525
00526 for (operation = pt->first_child; operation; operation = operation->next) {
00527 bs_operation *op = process_operation(operation, def, mp);
00528 if (!op) return NULL;
00529 add_operation_to_port_type(p, op, mp);
00530 }
00531
00532 return p;
00533 }
00534
00535
00542 static bs_port_type *lookup_porttype_by_name(const char *name, bs_definition *def)
00543 {
00544
00545 bs_uint16 i;
00546 for (i = 0; i < def->num_port_types; i++) {
00547 bs_port_type *pt = def->port_types[i];
00548 if (streq(pt->name, name)) return pt;
00549 }
00550 return NULL;
00551 }
00552
00553
00562 static bs_port *process_port(const apr_xml_elem *port, bs_definition *def,
00563 apr_pool_t *mp)
00564 {
00565 const apr_xml_attr *attr;
00566 char *port_name = NULL;
00567 bs_port_type *port_type = NULL;
00568
00569
00570 for (attr = port->attr; attr; attr = attr->next) {
00571 if (streq(attr->name, "name"))
00572 port_name = apr_pstrdup(mp, attr->value);
00573 else if (streq(attr->name, "type")) {
00574 port_type = lookup_porttype_by_name(attr->value, def);
00575 if (!port_type) return NULL;
00576 }
00577 }
00578 return new_bs_port(mp, port_name, port_type);
00579 }
00580
00581
00591 static bs_service *process_service(const apr_xml_elem *svc, bs_definition *def,
00592 apr_pool_t *mp)
00593 {
00594 const apr_xml_elem *port;
00595 const apr_xml_attr *attr;
00596 bs_service *s = NULL;
00597
00598
00599 for (attr = svc->attr; attr; attr = attr->next)
00600 if (streq(attr->name, "name"))
00601 s = new_bs_service(mp, attr->value, 0);
00602 if (!s) return NULL;
00603
00604
00605 for (port = svc->first_child; port; port = port->next) {
00606 bs_port *pt = process_port(port, def, mp);
00607 if (!pt) return NULL;
00608 add_port_to_service(s, pt, mp);
00609 }
00610
00611 return s;
00612 }
00613
00614
00622 static bs_status process_definition(const apr_xml_elem *root, bs_definition **def,
00623 apr_pool_t *mp)
00624 {
00625 const apr_xml_elem *elem;
00626 const apr_xml_attr *attr;
00627 bs_definition *d = NULL;
00628
00629
00630 for (attr = root->attr; attr; attr = attr->next)
00631 if (streq(attr->name, "name"))
00632 d = new_bs_definition(mp, attr->value, 0, 0, 0, 0);
00633 if (!d) return BS_XML_PARSE_ERROR;
00634
00635
00636 for (elem = root->first_child; elem; elem = elem->next) {
00637 if (streq(elem->name, "type")) {
00638 bs_data_type *type = process_data_type(elem, mp);
00639 if (!type) return BS_ERROR;
00640 add_data_type_to_definition(d, type, mp);
00641 }
00642 else if (streq(elem->name, "message")) {
00643 bs_message *msg = process_message(elem, d, mp);
00644 if (!msg) return BS_ERROR;
00645 add_message_to_definition(d, msg, mp);
00646 }
00647 else if (streq(elem->name, "portType")) {
00648 bs_port_type *type = process_porttype(elem, d, mp);
00649 if (!type) return BS_ERROR;
00650 add_port_type_to_definition(d, type, mp);
00651 }
00652 else if (streq(elem->name, "service")) {
00653 bs_service *svc = process_service(elem, d, mp);
00654 if (!svc) return BS_ERROR;
00655 add_service_to_definition(d, svc, mp);
00656 }
00657 }
00658
00659 *def = d;
00660 return BS_OK;
00661 }
00662
00663
00664
00665
00666
00667
00668
00669
00674 static bs_status process_request_input_part(bs_part_instance **part,
00675 const apr_xml_elem *elem, apr_pool_t *mp)
00676 {
00677 const apr_xml_attr *attr;
00678 bs_part_instance *ret = NULL;
00679 char *name = NULL, *data = NULL;
00680 bs_data_type *type = NULL;
00681
00682
00683 for (attr = elem->attr; attr; attr = attr->next) {
00684 if (streq(attr->name, "name"))
00685 name = apr_pstrdup(mp, attr->value);
00686 else if (streq(attr->name, "type"))
00687 type = new_bs_data_type(mp, attr->value);
00688 }
00689 if (!name || !type) return BS_XML_PARSE_ERROR;
00690
00691
00692 if (type->builtin) {
00693 if (elem->first_cdata.first == NULL)
00694 data = apr_pstrdup(mp, "");
00695 else
00696 data = apr_pstrdup(mp, elem->first_cdata.first->text);
00697 }
00698 else {
00699 if (elem->first_cdata.first == NULL)
00700 data = apr_pstrdup(mp, "");
00701 else {
00702 const char *encbuf = elem->first_cdata.first->text;
00703 data = apr_pcalloc(mp, apr_base64_decode_len(encbuf));
00704 apr_base64_decode(data, encbuf);
00705 }
00706 }
00707 ret = new_bs_part_instance(mp, name, type, data, strlen(data));
00708 if (!ret) return BS_ERROR;
00709
00710 *part = ret;
00711 return BS_OK;
00712 }
00713
00714
00719 static bs_status process_request_input(const apr_xml_elem *msg,
00720 bs_service_request *request, apr_pool_t *mp)
00721 {
00722 const apr_xml_attr *attr;
00723 const apr_xml_elem *part;
00724 bs_message_instance *inst = NULL;
00725
00726
00727 for (attr = msg->attr; attr; attr = attr->next)
00728 if (streq(attr->name, "message"))
00729 inst = new_bs_message_instance(mp, attr->value, 0);
00730 if (!inst) return BS_XML_PARSE_ERROR;
00731
00732
00733 for (part = msg->first_child; part; part = part->next) {
00734 bs_part_instance *pinst;
00735 bs_status rv;
00736
00737
00738 if (!streq(part->name, "part"))
00739 return BS_XML_PARSE_ERROR;
00740 rv = process_request_input_part(&pinst, part, mp);
00741 if (rv != BS_OK) return BS_XML_PARSE_ERROR;
00742 add_part_to_request_instance(pinst, inst, mp);
00743 }
00744
00745 request->input = inst;
00746 return BS_OK;
00747 }
00748
00749
00753 static bs_status process_request_use(const apr_xml_elem *elem,
00754 bs_service_request *request, apr_pool_t *mp)
00755 {
00756 const apr_xml_attr *attr;
00757
00758 for (attr = elem->attr; attr; attr = attr->next) {
00759 if (streq(attr->name, "service"))
00760 request->service = apr_pstrdup(mp, attr->value);
00761 else if (streq(attr->name, "port"))
00762 request->port = apr_pstrdup(mp, attr->value);
00763 else if (streq(attr->name, "operation"))
00764 request->operation = apr_pstrdup(mp, attr->value);
00765 }
00766 return BS_OK;
00767 }
00768
00769
00770 static bs_status process_request(const apr_xml_elem *root,
00771 bs_service_request **request,
00772 apr_pool_t *mp)
00773 {
00774 const apr_xml_elem *elem;
00775 const apr_xml_attr *attr;
00776 bs_service_request *r = NULL;
00777
00778
00779 for (attr = root->attr; attr; attr = attr->next)
00780 if (streq(attr->name, "uuid")) {
00781 bs_byte uuid[16];
00782 apr_uuid_parse((apr_uuid_t *) &uuid, attr->value);
00783 r = new_bs_service_request(mp, uuid, NULL, NULL, NULL, NULL);
00784 }
00785 if (!r) return BS_XML_PARSE_ERROR;
00786
00787
00788 for (elem = root->first_child; elem; elem = elem->next) {
00789 if (streq(elem->name, "use")) {
00790 bs_status rv = process_request_use(elem, r, mp);
00791 if (rv != BS_OK) return BS_XML_PARSE_ERROR;
00792 }
00793 else if (streq(elem->name, "input")) {
00794 bs_status rv = process_request_input(elem, r, mp);
00795 if (rv != BS_OK) return BS_XML_PARSE_ERROR;
00796 }
00797 }
00798
00799 *request = r;
00800 return BS_OK;
00801 }
00802
00803
00804
00805
00806
00807
00808
00809 static bs_status process_response_output(const apr_xml_elem *msg,
00810 bs_service_response *response, apr_pool_t *mp)
00811 {
00812 const apr_xml_attr *attr;
00813 const apr_xml_elem *part;
00814 bs_message_instance *inst = NULL;
00815
00816
00817 for (attr = msg->attr; attr; attr = attr->next)
00818 if (streq(attr->name, "message"))
00819 inst = new_bs_message_instance(mp, attr->value, 0);
00820 if (!inst) return BS_XML_PARSE_ERROR;
00821
00822
00823 for (part = msg->first_child; part; part = part->next) {
00824 bs_part_instance *pinst;
00825 bs_status rv;
00826
00827
00828 if (!streq(part->name, "part"))
00829 return BS_XML_PARSE_ERROR;
00830 rv = process_request_input_part(&pinst, part, mp);
00831 if (rv != BS_OK) return BS_XML_PARSE_ERROR;
00832 add_part_to_request_instance(pinst, inst, mp);
00833 }
00834
00835 response->output = inst;
00836 return BS_OK;
00837 }
00838
00839
00840 static bs_status process_response_fault(const apr_xml_elem *msg,
00841 bs_service_response *response, apr_pool_t *mp)
00842 {
00843 const apr_xml_attr *attr;
00844 const apr_xml_elem *part;
00845 bs_message_instance *inst = NULL;
00846
00847
00848 for (attr = msg->attr; attr; attr = attr->next)
00849 if (streq(attr->name, "message"))
00850 inst = new_bs_message_instance(mp, attr->value, 0);
00851 if (!inst) return BS_XML_PARSE_ERROR;
00852
00853
00854 for (part = msg->first_child; part; part = part->next) {
00855 bs_part_instance *pinst;
00856 bs_status rv;
00857
00858
00859 if (!streq(part->name, "part"))
00860 return BS_XML_PARSE_ERROR;
00861 rv = process_request_input_part(&pinst, part, mp);
00862 if (rv != BS_OK) return BS_XML_PARSE_ERROR;
00863 add_part_to_request_instance(pinst, inst, mp);
00864 }
00865
00866 response->output = inst;
00867 return BS_OK;
00868 }
00869
00870
00871 static bs_status process_response_used(const apr_xml_elem *elem,
00872 bs_service_response *response, apr_pool_t *mp)
00873 {
00874 const apr_xml_attr *attr;
00875
00876 for (attr = elem->attr; attr; attr = attr->next) {
00877 if (streq(attr->name, "service"))
00878 response->service = apr_pstrdup(mp, attr->value);
00879 else if (streq(attr->name, "port"))
00880 response->port = apr_pstrdup(mp, attr->value);
00881 else if (streq(attr->name, "operation"))
00882 response->operation = apr_pstrdup(mp, attr->value);
00883 }
00884 return BS_OK;
00885 }
00886
00887
00888 static bs_status process_response(const apr_xml_elem *root,
00889 bs_service_response **response,
00890 apr_pool_t *mp)
00891 {
00892 const apr_xml_elem *elem;
00893 const apr_xml_attr *attr;
00894 bs_service_response *r = NULL;
00895
00896
00897 for (attr = root->attr; attr; attr = attr->next)
00898 if (streq(attr->name, "uuid")) {
00899 bs_byte uuid[16];
00900 apr_uuid_parse((apr_uuid_t *) &uuid, attr->value);
00901 r = new_bs_service_response(mp, uuid, NULL, NULL, NULL, NULL, NULL);
00902 }
00903 if (!r) return BS_XML_PARSE_ERROR;
00904
00905
00906 for (elem = root->first_child; elem; elem = elem->next) {
00907 if (streq(elem->name, "used")) {
00908 bs_status rv = process_response_used(elem, r, mp);
00909 if (rv != BS_OK) return BS_XML_PARSE_ERROR;
00910 }
00911 else if (streq(elem->name, "output")) {
00912 bs_status rv = process_response_output(elem, r, mp);
00913 if (rv != BS_OK) return BS_XML_PARSE_ERROR;
00914 }
00915 else if (streq(elem->name, "fault")) {
00916 bs_status rv = process_response_fault(elem, r, mp);
00917 if (rv != BS_OK) return BS_XML_PARSE_ERROR;
00918 }
00919 }
00920
00921 *response = r;
00922 return BS_OK;
00923 }
00924
00925
00933 static bs_status process_tree(const apr_xml_elem *root, void **object, unsigned *type, apr_pool_t *mp)
00934 {
00935
00936 if (!root) return BS_XML_PARSE_ERROR;
00937
00938 if (streq(root->name, "definitions")) {
00939 *type = SERVICE_DEF_FROM_XML;
00940 return process_definition(root, (bs_definition **) object, mp);
00941 }
00942 else if (streq(root->name, "request")) {
00943 *type = SERVICE_REQUEST_FROM_XML;
00944 return process_request(root, (bs_service_request **) object, mp);
00945 }
00946 else if (streq(root->name, "response")) {
00947 *type = SERVICE_RESPONSE_FROM_XML;
00948 return process_response(root, (bs_service_response **) object, mp);
00949 }
00950 else return BS_XML_UNKNOWN_ROOT;
00951 }
00952
00953
00954 bs_status xlate_from_xml(const char *buf, bs_uint64 limit, void **object,
00955 unsigned *type, apr_pool_t *mp)
00956 {
00957 apr_xml_parser *parser = apr_xml_parser_create(mp);
00958 apr_xml_doc *doc;
00959 apr_status_t rv;
00960
00961
00962 while (buf[0] != '<' && buf[0] != '\0' && limit > 0) {
00963 buf++;
00964 limit--;
00965 }
00966
00967
00968 rv = apr_xml_parser_feed(parser, buf, limit);
00969 if (rv != APR_SUCCESS) {
00970 char err[256];
00971 apr_xml_parser_geterror(parser, err, sizeof(err));
00972 fprintf(stderr, "XML parse error: %s\n", err);
00973 return BS_XML_NWF;
00974 }
00975 else apr_xml_parser_done(parser, &doc);
00976
00977
00978 return process_tree(doc->root, object, type, mp);
00979 }