]> git.evergreen-ils.org Git - Evergreen.git/blob - OpenSRF/src/libstack/osrf_message.c
changed lame code to smarter code -> dumping document element instead of
[Evergreen.git] / OpenSRF / src / libstack / osrf_message.c
1 #include "osrf_message.h"
2
3 /* default to true */
4 int parse_json_result = 1;
5 int parse_json_params = 1;
6
7 /* utility function for debugging a DOM doc */
8 static void recurse_doc( xmlNodePtr node ) {
9         if( node == NULL ) return;
10         debug_handler("Recurse: %s =>  %s", node->name, node->content );
11         xmlNodePtr t = node->children;
12         while(t) {
13                 recurse_doc(t);
14                 t = t->next;
15         }
16 }
17
18
19
20 osrf_message* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol ) {
21
22         osrf_message* msg                       = (osrf_message*) safe_malloc(sizeof(osrf_message));
23         msg->m_type                                     = type;
24         msg->thread_trace                       = thread_trace;
25         msg->protocol                           = protocol;
26         msg->next                                       = NULL;
27         msg->is_exception                       = 0;
28         msg->parse_json_result  = parse_json_result;
29         msg->parse_json_params  = parse_json_params;
30         msg->parray                                     = init_string_array(16); /* start out with a slot for 16 params. can grow */
31         msg->params                                     = NULL;
32
33         return msg;
34 }
35
36
37 void osrf_message_set_json_parse_result( int ibool ) {
38         parse_json_result = ibool;
39 }
40
41 void osrf_message_set_json_parse_params( int ibool ) {
42         parse_json_params = ibool;
43 }
44
45 void osrf_message_set_request_info( 
46                 osrf_message* msg, char* method_name, json* json_params ) {
47
48         if( msg == NULL || method_name == NULL )
49                 fatal_handler( "Bad params to osrf_message_set_request_params()" );
50
51         if(msg->parse_json_params) {
52                 if( json_params != NULL ) {
53                         msg->params = json_tokener_parse(json_object_to_json_string(json_params));
54                         msg->_params = json_parse_string(json_object_to_json_string(json_params));
55                 } else {
56                         msg->params = json_tokener_parse("[]");
57                         msg->_params = json_parse_string("[]");
58                 }
59         }
60
61         msg->method_name = strdup( method_name );
62 }
63
64
65 /* only works of parse_json_params is false */
66 void osrf_message_add_param( osrf_message* msg, char* param_string ) {
67         if(msg == NULL || param_string == NULL)
68                 return;
69         if(!msg->parse_json_params)
70                 string_array_add(msg->parray, param_string);
71 }
72
73
74 void osrf_message_set_status_info( 
75                 osrf_message* msg, char* status_name, char* status_text, int status_code ) {
76
77         if( msg == NULL )
78                 fatal_handler( "Bad params to osrf_message_set_status_info()" );
79
80         if( status_name != NULL ) 
81                 msg->status_name = strdup( status_name );
82
83         if( status_text != NULL )
84                 msg->status_text = strdup( status_text );
85
86         msg->status_code = status_code;
87 }
88
89
90 void osrf_message_set_result_content( osrf_message* msg, char* json_string ) {
91         if( msg == NULL || json_string == NULL)
92                 warning_handler( "Bad params to osrf_message_set_result_content()" );
93
94         msg->result_string =    strdup(json_string);
95
96         /* ----------------------------------------------------- */
97         object* o = json_parse_string(json_string);
98         char* string = o->to_json(o);
99         debug_handler("---------------------------------------------------");
100         debug_handler("Parsed JSON string \n%s\n", string);
101         if(o->classname)
102                 debug_handler("Class is %s\n", o->classname);
103         debug_handler("---------------------------------------------------");
104         free_object(o);
105         free(string);
106         /* ----------------------------------------------------- */
107
108         debug_handler( "Message Parse JSON is set to: %d",  msg->parse_json_result );
109
110         if(msg->parse_json_result) {
111                 msg->result_content = json_tokener_parse(msg->result_string);
112                 msg->_result_content = json_parse_string(msg->result_string);
113
114                 char* j = object_to_json(msg->_result_content);
115                 debug_handler("PARSE json result content %s", j);
116                 free(j);
117         } 
118 }
119
120
121
122 void osrf_message_free( osrf_message* msg ) {
123         if( msg == NULL )
124                 return;
125
126         if( msg->status_name != NULL )
127                 free(msg->status_name);
128
129         if( msg->status_text != NULL )
130                 free(msg->status_text);
131
132         if( msg->result_content != NULL )
133                 json_object_put( msg->result_content );
134
135         if( msg->_result_content != NULL )
136                 free_object( msg->_result_content );
137
138         if( msg->result_string != NULL )
139                 free( msg->result_string);
140
141         if( msg->method_name != NULL )
142                 free(msg->method_name);
143
144         if( msg->params != NULL )
145                 json_object_put( msg->params );
146
147         if( msg->_params != NULL )
148                 free_object(msg->_params);
149
150
151         string_array_destroy(msg->parray);
152
153         free(msg);
154 }
155
156
157                 
158 /* here's where things get interesting */
159 char* osrf_message_to_xml( osrf_message* msg ) {
160
161         if( msg == NULL )
162                 return NULL;
163
164         //int                   bufsize;
165         //xmlChar*              xmlbuf;
166         //char*                 encoded_msg;
167
168         xmlKeepBlanksDefault(0);
169
170         xmlNodePtr      message_node;
171         xmlNodePtr      type_node;
172         xmlNodePtr      thread_trace_node;
173         xmlNodePtr      protocol_node;
174         xmlNodePtr      status_node;
175         xmlNodePtr      status_text_node;
176         xmlNodePtr      status_code_node;
177         xmlNodePtr      method_node = NULL;
178         xmlNodePtr      method_name_node;
179         xmlNodePtr      params_node = NULL;
180         xmlNodePtr      result_node;
181         xmlNodePtr      content_node;
182
183
184         xmlDocPtr       doc = xmlReadDoc( 
185                         BAD_CAST "<oils:root xmlns:oils='http://open-ils.org/xml/namespaces/oils_v1'>"
186                         "<oils:domainObject name='oilsMessage'/></oils:root>", 
187                         NULL, NULL, XML_PARSE_NSCLEAN );
188
189         message_node = xmlDocGetRootElement(doc)->children; /* since it's the only child */
190         type_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
191         thread_trace_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
192         protocol_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
193
194         char tt[64];
195         memset(tt,0,64);
196         sprintf(tt,"%d",msg->thread_trace);
197         xmlSetProp( thread_trace_node, BAD_CAST "name", BAD_CAST "threadTrace" );
198         xmlSetProp( thread_trace_node, BAD_CAST "value", BAD_CAST tt );
199
200         char prot[64];
201         memset(prot,0,64);
202         sprintf(prot,"%d",msg->protocol);
203         xmlSetProp( protocol_node, BAD_CAST "name", BAD_CAST "protocol" );
204         xmlSetProp( protocol_node, BAD_CAST "value", BAD_CAST prot );
205
206         switch(msg->m_type) {
207
208                 case CONNECT: 
209                         xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
210                         xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "CONNECT" );
211                         break;
212
213                 case DISCONNECT:
214                         xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
215                         xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "DISCONNECT" );
216                         break;
217
218                 case STATUS:
219
220                         xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
221                         xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "STATUS" );
222                         status_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
223                         xmlSetProp( status_node, BAD_CAST "name", BAD_CAST msg->status_name );
224
225                         status_text_node = xmlNewChild( status_node, NULL, BAD_CAST "domainObjectAttr", NULL );
226                         xmlSetProp( status_text_node, BAD_CAST "name", BAD_CAST "status" );
227                         xmlSetProp( status_text_node, BAD_CAST "value", BAD_CAST msg->status_text);
228
229                         status_code_node = xmlNewChild( status_node, NULL, BAD_CAST "domainObjectAttr", NULL );
230                         xmlSetProp( status_code_node, BAD_CAST "name", BAD_CAST "statusCode" );
231
232                         char sc[64];
233                         memset(sc,0,64);
234                         sprintf(sc,"%d",msg->status_code);
235                         xmlSetProp( status_code_node, BAD_CAST "value", BAD_CAST sc);
236                         
237                         break;
238
239                 case REQUEST:
240
241                         xmlSetProp( type_node, BAD_CAST "name", "type" );
242                         xmlSetProp( type_node, BAD_CAST "value", "REQUEST" );
243                         method_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
244                         xmlSetProp( method_node, BAD_CAST "name", BAD_CAST "oilsMethod" );
245
246                         if( msg->method_name != NULL ) {
247
248                                 method_name_node = xmlNewChild( method_node, NULL, BAD_CAST "domainObjectAttr", NULL );
249                                 xmlSetProp( method_name_node, BAD_CAST "name", BAD_CAST "method" );
250                                 xmlSetProp( method_name_node, BAD_CAST "value", BAD_CAST msg->method_name );
251
252                                 if( msg->parse_json_params ) {
253                                         if( msg->params != NULL ) {
254
255                                                 //char* jj = json_object_to_json_string( msg->params );
256                                                 char* jj = msg->_params->to_json(msg->_params); 
257                                                 params_node = xmlNewChild( method_node, NULL, BAD_CAST "params", NULL );
258                                                 xmlNodePtr tt = xmlNewDocTextLen( doc, BAD_CAST jj, strlen(jj) );
259                                                 xmlAddChild(params_node, tt);
260                                         }
261
262                                 } else {
263                                         if( msg->parray != NULL ) {
264
265                                                 /* construct the json array for the params */
266                                                 growing_buffer* buf = buffer_init(128);
267                                                 buffer_add( buf, "[");
268                                                 int k;
269                                                 for( k=0; k!= msg->parray->size; k++) {
270                                                         buffer_add( buf, string_array_get_string(msg->parray, k) );
271                                                         if(string_array_get_string(msg->parray, k+1))
272                                                                 buffer_add( buf, "," );
273                                                 }
274
275                                                 buffer_add( buf, "]");
276
277                                                 char* tmp = safe_malloc( (buf->n_used + 1) * sizeof(char));
278                                                 memcpy(tmp, buf->buf, buf->n_used);
279
280                                                 params_node = xmlNewChild( method_node, NULL, 
281                                                         BAD_CAST "params", NULL );
282                                                 
283                                                 xmlNodePtr tt = xmlNewDocTextLen( doc, BAD_CAST tmp, strlen(tmp) );
284                                                 xmlAddChild(params_node, tt);
285
286                                                 buffer_free(buf);
287                                         }
288                                 }
289                         }
290
291                         break;
292
293                 case RESULT:
294
295                         xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
296                         xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "RESULT" );
297                         result_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
298                         xmlSetProp( result_node, BAD_CAST "name", BAD_CAST "oilsResult" );
299
300                         status_text_node = xmlNewChild( result_node, NULL, BAD_CAST "domainObjectAttr", NULL );
301                         xmlSetProp( status_text_node, BAD_CAST "name", BAD_CAST "status" );
302                         xmlSetProp( status_text_node, BAD_CAST "value", BAD_CAST msg->status_text);
303
304                         status_code_node = xmlNewChild( result_node, NULL, BAD_CAST "domainObjectAttr", NULL );
305                         xmlSetProp( status_code_node, BAD_CAST "name", BAD_CAST "statusCode" );
306
307                         char stc[64];
308                         memset(stc,0,64);
309                         sprintf(stc,"%d",msg->status_code);
310                         xmlSetProp( status_code_node, BAD_CAST "value", BAD_CAST stc);
311
312                         content_node = xmlNewChild( result_node, NULL, 
313                                         BAD_CAST "domainObject", BAD_CAST msg->result_string );
314                         xmlSetProp( content_node, BAD_CAST "name", BAD_CAST "oilsScalar" );
315
316                         break;
317
318                 default:
319                         warning_handler( "Recieved bogus message type" );
320                         return NULL;
321         }
322
323
324         // -----------------------------------------------------
325         // Dump the XML doc to a string and remove the 
326         // xml declaration
327         // -----------------------------------------------------
328
329         /* passing in a '1' means we want to retain the formatting */
330
331         //xmlDocDumpFormatMemory( doc, &xmlbuf, &bufsize, 0 );
332         //xmlDocDumpMemoryEnc( doc, &xmlbuf, &bufsize, "UTF-8" );
333
334
335
336         /*
337         xmlDocDumpMemoryEnc( doc, &xmlbuf, &bufsize, "UTF-8" );
338
339         encoded_msg = strdup( (char*) xmlbuf );
340
341
342         if( encoded_msg == NULL ) 
343                 fatal_handler("message_to_xml(): Out of Memory");
344
345         xmlFree(xmlbuf);
346         xmlFreeDoc( doc );
347         xmlCleanupParser();
348         */
349
350
351         /***/
352         xmlBufferPtr xmlbuf = xmlBufferCreate();
353         xmlNodeDump( xmlbuf, doc, xmlDocGetRootElement(doc), 0, 0);
354
355         char* xml = strdup( (char*) (xmlBufferContent(xmlbuf)));
356         xmlBufferFree(xmlbuf);
357
358         int l = strlen(xml)-1;
359         if( xml[l] == 10 || xml[l] == 13 )
360                 xml[l] = '\0';
361
362         return xml;
363         /***/
364
365
366
367         /*
368         int len = strlen(encoded_msg);
369         char tmp[len];
370         memset( tmp, 0, len );
371         int i;
372         int found_at = 0;
373
374         for( i = 0; i!= len; i++ ) {
375                 if( encoded_msg[i] == 62) { 
376
377                         found_at = i + 1; 
378                         break;
379                 }
380         }
381
382         if( found_at ) {
383                 strncpy( tmp, encoded_msg + found_at, len - found_at );
384                 memset( encoded_msg, 0, len );
385                 strcpy( encoded_msg, tmp );
386         }
387
388         return encoded_msg;
389         */
390
391 }
392
393
394
395
396 int osrf_message_from_xml( char* xml, osrf_message* msgs[] ) {
397
398         if(!xml) return 0;
399
400         xmlKeepBlanksDefault(0);
401
402         xmlNodePtr      message_node;
403         xmlDocPtr       doc = xmlReadDoc( 
404                         BAD_CAST xml, NULL, NULL, XML_PARSE_NSCLEAN );
405
406         xmlNodePtr root =xmlDocGetRootElement(doc);
407         if(!root) {
408                 warning_handler( "Attempt to build message from incomplete xml %s", xml );
409                 return 0;
410         }
411
412         int msg_index = 0;
413         message_node = root->children; /* since it's the only child */
414
415         if(!message_node) {
416                 warning_handler( "Attempt to build message from incomplete xml %s", xml );
417                 return 0;
418         }
419
420         while( message_node != NULL ) {
421
422                 xmlNodePtr cur_node = message_node->children;
423                 osrf_message* new_msg = safe_malloc(sizeof(osrf_message));
424                 new_msg->parse_json_result = parse_json_result;
425         
426
427                 while( cur_node ) {
428
429                         xmlChar* name = NULL; 
430                         xmlChar* value = NULL;
431                         
432                         /* we're a domainObjectAttr */
433                         if( !strcmp((char*)cur_node->name,"domainObjectAttr" )) {
434                                 name = xmlGetProp( cur_node, BAD_CAST "name");
435         
436                                 if(name) {
437         
438                                         value = xmlGetProp( cur_node, BAD_CAST "value" );
439                                         if(value) {
440         
441                                                 if( (!strcmp((char*)name, "type")) ) { /* what type are we? */
442         
443                                                         if(!strcmp((char*)value, "CONNECT"))
444                                                                 new_msg->m_type = CONNECT;
445         
446                                                         if(!strcmp((char*)value, "DISCONNECT"))
447                                                                 new_msg->m_type = DISCONNECT;
448                 
449                                                         if(!strcmp((char*)value, "STATUS"))
450                                                                 new_msg->m_type = STATUS;
451                 
452                                                         if(!strcmp((char*)value, "REQUEST"))
453                                                                 new_msg->m_type = REQUEST;
454                                                         
455                                                         if(!strcmp((char*)value, "RESULT"))
456                                                                 new_msg->m_type = RESULT;
457                         
458                                                 } else if((!strcmp((char*)name, "threadTrace"))) {
459                                                         new_msg->thread_trace = atoi( (char*) value );
460                         
461                                                 } else if((!strcmp((char*)name, "protocol"))) {
462                                                         new_msg->protocol = atoi( (char*) value );
463                                                 }
464         
465                                                 xmlFree(value);
466                                         }
467                                         xmlFree(name);
468                                 }
469                         }
470         
471                         /* we're a domainObject */
472                         if( !strcmp((char*)cur_node->name,"domainObject" )) {
473         
474                                 name = xmlGetProp( cur_node, BAD_CAST "name");
475         
476                                 if(name) {
477
478                                         if( !strcmp(name,"oilsMethod") ) {
479         
480                                                 xmlNodePtr meth_node = cur_node->children;
481         
482                                                 while( meth_node != NULL ) {
483         
484                                                         if( !strcmp((char*)meth_node->name,"domainObjectAttr" )) {
485                                                                 char* meth_name = xmlGetProp( meth_node, BAD_CAST "value" );
486                                                                 if(meth_name) {
487                                                                         new_msg->method_name = strdup(meth_name);
488                                                                         xmlFree(meth_name);
489                                                                 }
490                                                         }
491         
492                                                         if( !strcmp((char*)meth_node->name,"params" ) && meth_node->children->content ) {
493                                                                 //new_msg->params = json_object_new_string( meth_node->children->content );
494                                                                 if( new_msg->parse_json_params) {
495                                                                         new_msg->params = json_tokener_parse(meth_node->children->content);
496                                                                         new_msg->_params = json_parse_string(meth_node->children->content);
497                                                                 } else {
498                                                                         /* XXX this will have to parse the JSON to 
499                                                                                 grab the strings for full support! This should only be 
500                                                                                 necessary for server support of 
501                                                                                 non-json-param-parsing, though. Ugh. */
502                                                                         new_msg->params = json_tokener_parse(meth_node->children->content);
503                                                                         new_msg->_params = json_parse_string(meth_node->children->content);
504                                                                 }       
505                                                         }
506
507                                                         meth_node = meth_node->next;
508                                                 }
509                                         } //oilsMethod
510         
511                                         if( !strcmp(name,"oilsResult") || new_msg->m_type == STATUS ) {
512         
513                                                 xmlNodePtr result_nodes = cur_node->children;
514         
515                                                 while( result_nodes ) {
516         
517                                                         if(!strcmp(result_nodes->name,"domainObjectAttr")) {
518         
519                                                                 xmlChar* result_attr_name = xmlGetProp( result_nodes, BAD_CAST "name");
520                                                                 if(result_attr_name) {
521                                                                         xmlChar* result_attr_value = xmlGetProp( result_nodes, BAD_CAST "value" );
522         
523                                                                         if( result_attr_value ) {
524                                                                                 if((!strcmp((char*)result_attr_name, "status"))) 
525                                                                                         new_msg->status_text = strdup((char*) result_attr_value );
526         
527                                                                                 else if((!strcmp((char*)result_attr_name, "statusCode"))) 
528                                                                                         new_msg->status_code = atoi((char*) result_attr_value );
529                                                                                 xmlFree(result_attr_value);
530                                                                         }
531         
532                                                                         xmlFree(result_attr_name);
533                                                                 }
534         
535                                                         }
536                                                 
537         
538                                                         if(!strcmp(result_nodes->name,"domainObject")) {
539                                                                 xmlChar* r_name = xmlGetProp( result_nodes, BAD_CAST "name" );
540                                                                 if(r_name) {
541                                                                         if( !strcmp((char*)r_name,"oilsScalar") && result_nodes->children->content ) {
542                                                                                 osrf_message_set_result_content( new_msg, result_nodes->children->content);
543                                                                         }
544                                                                         xmlFree(r_name);
545                                                                 }
546                                                         }
547                                                         result_nodes = result_nodes->next;
548                                                 }
549                                         }
550                                         
551                                         if( new_msg->m_type == STATUS ) 
552                                                 new_msg->status_name = strdup(name); 
553
554                                         xmlFree(name);
555                                 }
556                         }
557         
558                         /* we're a params node */
559                         if( !strcmp((char*)cur_node->name,"params" )) {
560         
561                         }
562         
563                         cur_node = cur_node->next;
564                 }
565         
566                 msgs[msg_index] = new_msg;
567                 msg_index++;
568                 message_node = message_node->next;
569
570         } // while message_node != null
571
572         xmlCleanupCharEncodingHandlers();
573         xmlFreeDoc( doc );
574         xmlCleanupParser();
575
576         return msg_index;
577
578 }
579
580