]> git.evergreen-ils.org Git - Evergreen.git/blob - OpenSRF/src/libstack/osrf_message.c
added some basic exception handling and propogation
[Evergreen.git] / OpenSRF / src / libstack / osrf_message.c
1 #include "opensrf/osrf_message.h"
2
3
4
5 /*
6 int main() {
7
8         char* x = "<oils:root xmlns:oils='http://open-ils.org/xml/namespaces/oils_v1'><oils:domainObject name='oilsMessage'><oils:domainObjectAttr value='STATUS' name='type'/><oils:domainObjectAttr value='12' name='threadTrace'/><oils:domainObject name='oilsMethodException'><oils:domainObjectAttr value=' *** Call to [div] failed for session [1351200643.110915057523738], thread trace [12]:&#10;JabberDisconnected Exception &#10;This JabberClient instance is no longer connected to the server' name='status'/><oils:domainObjectAttr value='500' name='statusCode'/></oils:domainObject></oils:domainObject></oils:root>";
9         */
10
11         /*
12         char* x = "<oils:root xmlns:oils='http://open-ils.org/xml/namespaces/oils_v1'>"
13                                 "<oils:domainObject name='oilsMessage'>"
14                                 "<oils:domainObjectAttr value='STATUS' name='type'/>"
15                                 "<oils:domainObjectAttr value='1' name='threadTrace'/>"
16                                 "<oils:domainObject name='oilsConnectStatus'>"
17                                 "<oils:domainObjectAttr value='Connection Successful' name='status'/>"
18                                 "<oils:domainObjectAttr value='200' name='statusCode'/>"
19                                 "</oils:domainObject></oils:domainObject>"
20
21                                 "<oils:domainObject name='oilsMessage'>"
22                                 "<oils:domainObjectAttr value='STATUS' name='type'/>"
23                                 "<oils:domainObjectAttr value='1' name='threadTrace'/>"
24                                 "<oils:domainObject name='oilsConnectStatus'>"
25                                 "<oils:domainObjectAttr value='Request Complete' name='status'/>"
26                                 "<oils:domainObjectAttr value='205' name='statusCode'/>"
27                                 "</oils:domainObject></oils:domainObject>"
28                                 
29                                 "</oils:root>";
30                                 */
31
32 /*
33         osrf_message* arr[4];
34         memset(arr, 0, 4);
35         int ret = osrf_message_from_xml( x, arr );
36         fprintf(stderr, "RET: %d\n", ret );
37         if(ret<=0)
38                 fatal_handler( "none parsed" );
39
40         osrf_message* xml_msg = arr[0];
41         printf("Message name: %s\nstatus %s, \nstatusCode %d\n", xml_msg->status_name, xml_msg->status_text, xml_msg->status_code );
42
43 //      xml_msg = arr[1];
44 //      printf("Message 2 status %s, statusCode %d\n", xml_msg->status_text, xml_msg->status_code );
45
46
47         return 0;
48 }
49 */
50
51
52
53         /*
54         osrf_message* msg = osrf_message_init( STATUS, 1, 1 );
55 //      osrf_message* msg = osrf_message_init( CONNECT, 1, 1 );
56         //osrf_message* msg = osrf_message_init( REQUEST, 1, 1 );
57         osrf_message_set_status_info( msg, "oilsConnectStatus", "Connection Succsesful", 200 );
58
59         json* params = json_object_new_array();
60         json_object_array_add(params, json_object_new_int(1));
61         json_object_array_add(params, json_object_new_int(2));
62
63         osrf_message_set_request_info( msg, "add", params );
64         //osrf_message_set_result_content( msg, params );
65         json_object_put( params );
66
67         char* xml =  osrf_message_to_xml( msg );
68         printf( "\n\nMessage as XML\n%s", xml );
69
70         osrf_message* xml_msg = osrf_message_from_xml( xml );
71
72         printf( "Message stuff \n\ntype %d"
73                         "\nthread_trace %d \nprotocol %d "
74                         "\nstatus_name %s"
75                         "\nstatus_text %s\nstatus_code %d" 
76                         "\nresult_content %s \nparams %s"
77                         "\n", xml_msg->m_type, 
78                         xml_msg->thread_trace, xml_msg->protocol, xml_msg->status_name, 
79                         xml_msg->status_text, xml_msg->status_code, 
80                         json_object_to_json_string( xml_msg->result_content),
81                         json_object_to_json_string(xml_msg->params) 
82                         );
83
84
85         free(xml);
86         osrf_message_free( msg );
87         osrf_message_free( xml_msg );
88         return 0;
89         
90 }
91 */
92
93
94 osrf_message* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol ) {
95
96         osrf_message* msg = safe_malloc(sizeof(osrf_message));
97         msg->m_type = type;
98         msg->thread_trace = thread_trace;
99         msg->protocol = protocol;
100         msg->next = NULL;
101         msg->is_exception = 0;
102
103         return msg;
104 }
105
106
107 void osrf_message_set_request_info( osrf_message* msg, char* method_name, json* json_params ) {
108         if( msg == NULL || method_name == NULL )
109                 fatal_handler( "Bad params to osrf_message_set_request_params()" );
110
111         if( json_params != NULL )
112                 msg->params = json_tokener_parse(json_object_to_json_string(json_params));
113         else
114                 msg->params = json_tokener_parse("[]");
115
116         msg->method_name = strdup( method_name );
117 }
118
119
120
121 void osrf_message_set_status_info( 
122                 osrf_message* msg, char* status_name, char* status_text, int status_code ) {
123
124         if( msg == NULL )
125                 fatal_handler( "Bad params to osrf_message_set_status_info()" );
126
127         if( status_name != NULL ) 
128                 msg->status_name = strdup( status_name );
129
130         if( status_text != NULL )
131                 msg->status_text = strdup( status_text );
132
133         msg->status_code = status_code;
134 }
135
136
137 void osrf_message_set_result_content( osrf_message* msg, json* result_content ) {
138         if( msg == NULL )
139                 fatal_handler( "Bad params to osrf_message_set_result_content()" );
140         msg->result_content = json_tokener_parse(json_object_to_json_string(result_content));
141 }
142
143
144
145 void osrf_message_free( osrf_message* msg ) {
146         if( msg == NULL )
147                 warning_handler( "Trying to delete NULL osrf_message" );
148
149         if( msg->status_name != NULL )
150                 free(msg->status_name);
151
152         if( msg->status_text != NULL )
153                 free(msg->status_text);
154
155         if( msg->result_content != NULL )
156                 json_object_put( msg->result_content );
157
158         if( msg->method_name != NULL )
159                 free(msg->method_name);
160
161         if( msg->params != NULL )
162                 json_object_put( msg->params );
163
164         free(msg);
165 }
166
167
168                 
169 /* here's where things get interesting */
170 char* osrf_message_to_xml( osrf_message* msg ) {
171
172         if( msg == NULL )
173                 return NULL;
174
175         int                     bufsize;
176         xmlChar*                xmlbuf;
177         char*                   encoded_msg;
178
179         xmlKeepBlanksDefault(0);
180
181         xmlNodePtr      message_node;
182         xmlNodePtr      type_node;
183         xmlNodePtr      thread_trace_node;
184         xmlNodePtr      protocol_node;
185         xmlNodePtr      status_node;
186         xmlNodePtr      status_text_node;
187         xmlNodePtr      status_code_node;
188         xmlNodePtr      method_node;
189         xmlNodePtr      method_name_node;
190         xmlNodePtr      params_node;
191         xmlNodePtr      result_node;
192         xmlNodePtr      content_node;
193
194
195         xmlDocPtr       doc = xmlReadDoc( 
196                         BAD_CAST "<oils:root xmlns:oils='http://open-ils.org/xml/namespaces/oils_v1'>"
197                         "<oils:domainObject name='oilsMessage'/></oils:root>", 
198                         NULL, NULL, XML_PARSE_NSCLEAN );
199
200         message_node = xmlDocGetRootElement(doc)->children; /* since it's the only child */
201         type_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
202         thread_trace_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
203         protocol_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
204
205         char tt[64];
206         memset(tt,0,64);
207         sprintf(tt,"%d",msg->thread_trace);
208         xmlSetProp( thread_trace_node, BAD_CAST "name", BAD_CAST "threadTrace" );
209         xmlSetProp( thread_trace_node, BAD_CAST "value", BAD_CAST tt );
210
211         char prot[64];
212         memset(prot,0,64);
213         sprintf(prot,"%d",msg->protocol);
214         xmlSetProp( protocol_node, BAD_CAST "name", BAD_CAST "protocol" );
215         xmlSetProp( protocol_node, BAD_CAST "value", BAD_CAST prot );
216
217         switch(msg->m_type) {
218
219                 case CONNECT: 
220                         xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
221                         xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "CONNECT" );
222                         break;
223
224                 case DISCONNECT:
225                         xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
226                         xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "DISCONNECT" );
227                         break;
228
229                 case STATUS:
230
231                         xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
232                         xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "STATUS" );
233                         status_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
234                         xmlSetProp( status_node, BAD_CAST "name", BAD_CAST msg->status_name );
235
236                         status_text_node = xmlNewChild( status_node, NULL, BAD_CAST "domainObjectAttr", NULL );
237                         xmlSetProp( status_text_node, BAD_CAST "name", BAD_CAST "status" );
238                         xmlSetProp( status_text_node, BAD_CAST "value", BAD_CAST msg->status_text);
239
240                         status_code_node = xmlNewChild( status_node, NULL, BAD_CAST "domainObjectAttr", NULL );
241                         xmlSetProp( status_code_node, BAD_CAST "name", BAD_CAST "statusCode" );
242
243                         char sc[64];
244                         memset(sc,0,64);
245                         sprintf(sc,"%d",msg->status_code);
246                         xmlSetProp( status_code_node, BAD_CAST "value", BAD_CAST sc);
247                         
248                         break;
249
250                 case REQUEST:
251
252                         xmlSetProp( type_node, BAD_CAST "name", "type" );
253                         xmlSetProp( type_node, BAD_CAST "value", "REQUEST" );
254                         method_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
255                         xmlSetProp( method_node, BAD_CAST "name", BAD_CAST "oilsMethod" );
256
257                         if( msg->method_name != NULL ) {
258
259                                 method_name_node = xmlNewChild( method_node, NULL, BAD_CAST "domainObjectAttr", NULL );
260                                 xmlSetProp( method_name_node, BAD_CAST "name", BAD_CAST "method" );
261                                 xmlSetProp( method_name_node, BAD_CAST "value", BAD_CAST msg->method_name );
262
263                                 if( msg->params != NULL ) {
264                                         params_node = xmlNewChild( method_node, NULL, 
265                                                 BAD_CAST "params", BAD_CAST json_object_to_json_string( msg->params ) );
266                                 }
267                         }
268
269                         break;
270
271                 case RESULT:
272
273                         xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
274                         xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "RESULT" );
275                         result_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
276                         xmlSetProp( result_node, BAD_CAST "name", BAD_CAST "oilsResult" );
277
278                         status_text_node = xmlNewChild( result_node, NULL, BAD_CAST "domainObjectAttr", NULL );
279                         xmlSetProp( status_text_node, BAD_CAST "name", BAD_CAST "status" );
280                         xmlSetProp( status_text_node, BAD_CAST "value", BAD_CAST msg->status_text);
281
282                         status_code_node = xmlNewChild( result_node, NULL, BAD_CAST "domainObjectAttr", NULL );
283                         xmlSetProp( status_code_node, BAD_CAST "name", BAD_CAST "statusCode" );
284
285                         char stc[64];
286                         memset(stc,0,64);
287                         sprintf(stc,"%d",msg->status_code);
288                         xmlSetProp( status_code_node, BAD_CAST "value", BAD_CAST stc);
289
290                         content_node = xmlNewChild( result_node, NULL, 
291                                         BAD_CAST "domainObject", BAD_CAST json_object_to_json_string( msg->result_content ) );
292                         xmlSetProp( content_node, BAD_CAST "name", BAD_CAST "oilsScalar" );
293
294                         break;
295
296                 default:
297                         warning_handler( "Recieved bogus message type" );
298                         return NULL;
299         }
300
301
302         // -----------------------------------------------------
303         // Dump the XML doc to a string and remove the 
304         // xml declaration
305         // -----------------------------------------------------
306
307         /* passing in a '1' means we want to retain the formatting */
308         xmlDocDumpFormatMemory( doc, &xmlbuf, &bufsize, 0 );
309         encoded_msg = strdup( (char*) xmlbuf );
310
311         if( encoded_msg == NULL ) 
312                 fatal_handler("message_to_xml(): Out of Memory");
313
314         xmlFree(xmlbuf);
315         xmlFreeDoc( doc );
316         xmlCleanupParser();
317
318
319         /*** remove the XML declaration */
320         int len = strlen(encoded_msg);
321         char tmp[len];
322         memset( tmp, 0, len );
323         int i;
324         int found_at = 0;
325
326         /* when we reach the first >, take everything after it */
327         for( i = 0; i!= len; i++ ) {
328                 if( encoded_msg[i] == 62) { /* ascii > */
329
330                         /* found_at holds the starting index of the rest of the doc*/
331                         found_at = i + 1; 
332                         break;
333                 }
334         }
335
336         if( found_at ) {
337                 /* move the shortened doc into the tmp buffer */
338                 strncpy( tmp, encoded_msg + found_at, len - found_at );
339                 /* move the tmp buffer back into the allocated space */
340                 memset( encoded_msg, 0, len );
341                 strcpy( encoded_msg, tmp );
342         }
343
344         return encoded_msg;
345
346 }
347
348
349 int osrf_message_from_xml( char* xml, osrf_message* msgs[] ) {
350
351         if(!xml) return 0;
352
353         xmlKeepBlanksDefault(0);
354
355         xmlNodePtr      message_node;
356         xmlDocPtr       doc = xmlReadDoc( 
357                         BAD_CAST xml, NULL, NULL, XML_PARSE_NSCLEAN );
358
359         xmlNodePtr root =xmlDocGetRootElement(doc);
360         if(!root) {
361                 warning_handler( "Attempt to build message from incomplete xml %s", xml );
362                 return 0;
363         }
364
365         int msg_index = 0;
366         message_node = root->children; /* since it's the only child */
367
368         if(!message_node) {
369                 warning_handler( "Attempt to build message from incomplete xml %s", xml );
370                 return 0;
371         }
372
373         while( message_node != NULL ) {
374
375                 xmlNodePtr cur_node = message_node->children;
376                 osrf_message* new_msg = safe_malloc(sizeof(osrf_message));
377         
378
379                 while( cur_node ) {
380
381                         xmlChar* name = NULL; 
382                         xmlChar* value = NULL;
383                         
384                         /* we're a domainObjectAttr */
385                         if( !strcmp((char*)cur_node->name,"domainObjectAttr" )) {
386                                 name = xmlGetProp( cur_node, BAD_CAST "name");
387         
388                                 if(name) {
389         
390                                         value = xmlGetProp( cur_node, BAD_CAST "value" );
391                                         if(value) {
392         
393                                                 if( (!strcmp((char*)name, "type")) ) { /* what type are we? */
394         
395                                                         if(!strcmp((char*)value, "CONNECT"))
396                                                                 new_msg->m_type = CONNECT;
397         
398                                                         if(!strcmp((char*)value, "DISCONNECT"))
399                                                                 new_msg->m_type = DISCONNECT;
400                 
401                                                         if(!strcmp((char*)value, "STATUS"))
402                                                                 new_msg->m_type = STATUS;
403                 
404                                                         if(!strcmp((char*)value, "REQUEST"))
405                                                                 new_msg->m_type = REQUEST;
406                                                         
407                                                         if(!strcmp((char*)value, "RESULT"))
408                                                                 new_msg->m_type = RESULT;
409                         
410                                                 } else if((!strcmp((char*)name, "threadTrace"))) {
411                                                         new_msg->thread_trace = atoi( (char*) value );
412                         
413                                                 } else if((!strcmp((char*)name, "protocol"))) {
414                                                         new_msg->protocol = atoi( (char*) value );
415                                                 }
416         
417                                                 xmlFree(value);
418                                         }
419                                         xmlFree(name);
420                                 }
421                         }
422         
423                         /* we're a domainObject */
424                         if( !strcmp((char*)cur_node->name,"domainObject" )) {
425         
426                                 name = xmlGetProp( cur_node, BAD_CAST "name");
427         
428                                 if(name) {
429
430                                         if( !strcmp(name,"oilsMethod") ) {
431         
432                                                 xmlNodePtr meth_node = cur_node->children;
433         
434                                                 while( meth_node != NULL ) {
435         
436                                                         if( !strcmp((char*)meth_node->name,"domainObjectAttr" )) {
437                                                                 char* meth_name = xmlGetProp( meth_node, BAD_CAST "value" );
438                                                                 if(meth_name) {
439                                                                         new_msg->method_name = strdup(meth_name);
440                                                                         xmlFree(meth_name);
441                                                                 }
442                                                         }
443         
444                                                         if( !strcmp((char*)meth_node->name,"params" ) && meth_node->children->content ) 
445                                                                 //new_msg->params = json_object_new_string( meth_node->children->content );
446                                                                 new_msg->params = json_tokener_parse(meth_node->children->content);
447         
448                                                         meth_node = meth_node->next;
449                                                 }
450                                         } //oilsMethod
451         
452                                         if( !strcmp(name,"oilsResult") || new_msg->m_type == STATUS ) {
453         
454                                                 xmlNodePtr result_nodes = cur_node->children;
455         
456                                                 while( result_nodes ) {
457         
458                                                         if(!strcmp(result_nodes->name,"domainObjectAttr")) {
459         
460                                                                 xmlChar* result_attr_name = xmlGetProp( result_nodes, BAD_CAST "name");
461                                                                 if(result_attr_name) {
462                                                                         xmlChar* result_attr_value = xmlGetProp( result_nodes, BAD_CAST "value" );
463         
464                                                                         if( result_attr_value ) {
465                                                                                 if((!strcmp((char*)result_attr_name, "status"))) 
466                                                                                         new_msg->status_text = strdup((char*) result_attr_value );
467         
468                                                                                 else if((!strcmp((char*)result_attr_name, "statusCode"))) 
469                                                                                         new_msg->status_code = atoi((char*) result_attr_value );
470                                                                                 xmlFree(result_attr_value);
471                                                                         }
472         
473                                                                         xmlFree(result_attr_name);
474                                                                 }
475         
476                                                         }
477                                                 
478         
479                                                         if(!strcmp(result_nodes->name,"domainObject")) {
480                                                                 xmlChar* r_name = xmlGetProp( result_nodes, BAD_CAST "name" );
481                                                                 if(r_name) {
482                                                                         if( !strcmp((char*)r_name,"oilsScalar") && result_nodes->children->content ) 
483                                                                                 new_msg->result_content = json_tokener_parse(result_nodes->children->content);
484                                                                         xmlFree(r_name);
485                                                                 }
486                                                         }
487                                                         result_nodes = result_nodes->next;
488                                                 }
489                                         }
490                                         
491                                         if( new_msg->m_type == STATUS ) 
492                                                 new_msg->status_name = strdup(name); 
493
494                                         xmlFree(name);
495                                 }
496                         }
497         
498                         /* we're a params node */
499                         if( !strcmp((char*)cur_node->name,"params" )) {
500         
501                         }
502         
503                         cur_node = cur_node->next;
504                 }
505         
506                 msgs[msg_index] = new_msg;
507                 msg_index++;
508                 message_node = message_node->next;
509
510         } // while message_node != null
511
512         xmlCleanupCharEncodingHandlers();
513         xmlFreeDoc( doc );
514         xmlCleanupParser();
515
516         return msg_index;
517
518 }
519
520