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