1 #include "osrf_message.h"
4 int parse_json_result = 1;
5 int parse_json_params = 1;
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;
20 osrf_message* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol ) {
22 osrf_message* msg = (osrf_message*) safe_malloc(sizeof(osrf_message));
24 msg->thread_trace = thread_trace;
25 msg->protocol = protocol;
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 */
32 msg->_result_content = NULL;
38 void osrf_message_set_json_parse_result( int ibool ) {
39 parse_json_result = ibool;
42 void osrf_message_set_json_parse_params( int ibool ) {
43 parse_json_params = ibool;
47 void osrf_message_set_request_info(
48 osrf_message* msg, char* method_name, json* json_params ) {
50 if( msg == NULL || method_name == NULL )
51 fatal_handler( "Bad params to osrf_message_set_request_params()" );
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));
58 msg->params = json_tokener_parse("[]");
59 msg->_params = json_parse_string("[]");
63 msg->method_name = strdup( method_name );
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 );
73 /* uses the object passed in directly, do not FREE! */
74 void osrf_message_add_object_param( osrf_message* msg, object* o ) {
76 if(msg->parse_json_params) {
78 msg->_params = json_parse_string("[]");
79 msg->_params->push(msg->_params, json_parse_string(o->to_json(o)));
83 void osrf_message_set_params( osrf_message* msg, object* o ) {
84 if(!msg || !o) return;
86 char* j = object_to_json(o);
87 debug_handler("Setting params to\n%s", j);
90 if(msg->parse_json_params) {
92 warning_handler("passing non-array to osrf_message_set_params()");
95 if(msg->_params) free_object(msg->_params);
96 char* j = o->to_json(o);
97 msg->_params = json_parse_string(j);
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)
107 if(!msg->parse_json_params)
108 string_array_add(msg->parray, param_string);
112 void osrf_message_set_status_info(
113 osrf_message* msg, char* status_name, char* status_text, int status_code ) {
116 fatal_handler( "Bad params to osrf_message_set_status_info()" );
118 if( status_name != NULL )
119 msg->status_name = strdup( status_name );
121 if( status_text != NULL )
122 msg->status_text = strdup( status_text );
124 msg->status_code = status_code;
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()" );
132 msg->result_string = strdup(json_string);
134 /* ----------------------------------------------------- */
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);
141 debug_handler("Class is %s\n", o->classname);
142 debug_handler("---------------------------------------------------");
146 /* ----------------------------------------------------- */
148 debug_handler( "Message Parse JSON result is set to: %d", msg->parse_json_result );
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);
158 void osrf_message_free( osrf_message* msg ) {
162 if( msg->status_name != NULL )
163 free(msg->status_name);
165 if( msg->status_text != NULL )
166 free(msg->status_text);
169 if( msg->result_content != NULL )
170 json_object_put( msg->result_content );
173 if( msg->_result_content != NULL )
174 free_object( msg->_result_content );
176 if( msg->result_string != NULL )
177 free( msg->result_string);
179 if( msg->method_name != NULL )
180 free(msg->method_name);
183 if( msg->params != NULL )
184 json_object_put( msg->params );
187 if( msg->_params != NULL )
188 free_object(msg->_params);
191 string_array_destroy(msg->parray);
198 /* here's where things get interesting */
199 char* osrf_message_to_xml( osrf_message* msg ) {
208 xmlKeepBlanksDefault(0);
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;
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 );
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 );
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 );
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 );
246 switch(msg->m_type) {
249 xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
250 xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "CONNECT" );
254 xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
255 xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "DISCONNECT" );
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 );
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);
269 status_code_node = xmlNewChild( status_node, NULL, BAD_CAST "domainObjectAttr", NULL );
270 xmlSetProp( status_code_node, BAD_CAST "name", BAD_CAST "statusCode" );
274 sprintf(sc,"%d",msg->status_code);
275 xmlSetProp( status_code_node, BAD_CAST "value", BAD_CAST sc);
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" );
286 if( msg->method_name != NULL ) {
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 );
292 if( msg->parse_json_params ) {
293 if( msg->_params != NULL ) {
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);
303 if( msg->parray != NULL ) {
305 /* construct the json array for the params */
306 growing_buffer* buf = buffer_init(128);
307 buffer_add( buf, "[");
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, "," );
315 buffer_add( buf, "]");
317 char* tmp = safe_malloc( (buf->n_used + 1) * sizeof(char));
318 memcpy(tmp, buf->buf, buf->n_used);
320 params_node = xmlNewChild( method_node, NULL,
321 BAD_CAST "params", NULL );
323 xmlNodePtr tt = xmlNewDocTextLen( doc, BAD_CAST tmp, strlen(tmp) );
324 xmlAddChild(params_node, tt);
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" );
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);
344 status_code_node = xmlNewChild( result_node, NULL, BAD_CAST "domainObjectAttr", NULL );
345 xmlSetProp( status_code_node, BAD_CAST "name", BAD_CAST "statusCode" );
349 sprintf(stc,"%d",msg->status_code);
350 xmlSetProp( status_code_node, BAD_CAST "value", BAD_CAST stc);
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" );
359 warning_handler( "Recieved bogus message type" );
364 // -----------------------------------------------------
365 // Dump the XML doc to a string and remove the
367 // -----------------------------------------------------
369 /* passing in a '1' means we want to retain the formatting */
371 //xmlDocDumpFormatMemory( doc, &xmlbuf, &bufsize, 0 );
372 //xmlDocDumpMemoryEnc( doc, &xmlbuf, &bufsize, "UTF-8" );
377 xmlDocDumpMemoryEnc( doc, &xmlbuf, &bufsize, "UTF-8" );
379 encoded_msg = strdup( (char*) xmlbuf );
382 if( encoded_msg == NULL )
383 fatal_handler("message_to_xml(): Out of Memory");
392 xmlBufferPtr xmlbuf = xmlBufferCreate();
393 xmlNodeDump( xmlbuf, doc, xmlDocGetRootElement(doc), 0, 0);
395 char* xml = strdup( (char*) (xmlBufferContent(xmlbuf)));
396 xmlBufferFree(xmlbuf);
398 int l = strlen(xml)-1;
399 if( xml[l] == 10 || xml[l] == 13 )
408 int len = strlen(encoded_msg);
410 memset( tmp, 0, len );
414 for( i = 0; i!= len; i++ ) {
415 if( encoded_msg[i] == 62) {
423 strncpy( tmp, encoded_msg + found_at, len - found_at );
424 memset( encoded_msg, 0, len );
425 strcpy( encoded_msg, tmp );
436 int osrf_message_from_xml( char* xml, osrf_message* msgs[] ) {
440 xmlKeepBlanksDefault(0);
442 xmlNodePtr message_node;
443 xmlDocPtr doc = xmlReadDoc(
444 BAD_CAST xml, NULL, NULL, XML_PARSE_NSCLEAN );
446 xmlNodePtr root =xmlDocGetRootElement(doc);
448 warning_handler( "Attempt to build message from incomplete xml %s", xml );
453 message_node = root->children; /* since it's the only child */
456 warning_handler( "Attempt to build message from incomplete xml %s", xml );
460 while( message_node != NULL ) {
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;
469 xmlChar* name = NULL;
470 xmlChar* value = NULL;
472 /* we're a domainObjectAttr */
473 if( !strcmp((char*)cur_node->name,"domainObjectAttr" )) {
474 name = xmlGetProp( cur_node, BAD_CAST "name");
478 value = xmlGetProp( cur_node, BAD_CAST "value" );
481 if( (!strcmp((char*)name, "type")) ) { /* what type are we? */
483 if(!strcmp((char*)value, "CONNECT"))
484 new_msg->m_type = CONNECT;
486 if(!strcmp((char*)value, "DISCONNECT"))
487 new_msg->m_type = DISCONNECT;
489 if(!strcmp((char*)value, "STATUS"))
490 new_msg->m_type = STATUS;
492 if(!strcmp((char*)value, "REQUEST"))
493 new_msg->m_type = REQUEST;
495 if(!strcmp((char*)value, "RESULT"))
496 new_msg->m_type = RESULT;
498 } else if((!strcmp((char*)name, "threadTrace"))) {
499 new_msg->thread_trace = atoi( (char*) value );
501 } else if((!strcmp((char*)name, "protocol"))) {
502 new_msg->protocol = atoi( (char*) value );
511 /* we're a domainObject */
512 if( !strcmp((char*)cur_node->name,"domainObject" )) {
514 name = xmlGetProp( cur_node, BAD_CAST "name");
518 if( !strcmp(name,"oilsMethod") ) {
520 xmlNodePtr meth_node = cur_node->children;
522 while( meth_node != NULL ) {
524 if( !strcmp((char*)meth_node->name,"domainObjectAttr" )) {
525 char* meth_name = xmlGetProp( meth_node, BAD_CAST "value" );
527 new_msg->method_name = strdup(meth_name);
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);
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);
547 meth_node = meth_node->next;
551 if( !strcmp(name,"oilsResult") || new_msg->m_type == STATUS ) {
553 xmlNodePtr result_nodes = cur_node->children;
555 while( result_nodes ) {
557 if(!strcmp(result_nodes->name,"domainObjectAttr")) {
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" );
563 if( result_attr_value ) {
564 if((!strcmp((char*)result_attr_name, "status")))
565 new_msg->status_text = strdup((char*) result_attr_value );
567 else if((!strcmp((char*)result_attr_name, "statusCode")))
568 new_msg->status_code = atoi((char*) result_attr_value );
569 xmlFree(result_attr_value);
572 xmlFree(result_attr_name);
578 if(!strcmp(result_nodes->name,"domainObject")) {
579 xmlChar* r_name = xmlGetProp( result_nodes, BAD_CAST "name" );
581 if( !strcmp((char*)r_name,"oilsScalar") && result_nodes->children->content ) {
582 osrf_message_set_result_content( new_msg, result_nodes->children->content);
587 result_nodes = result_nodes->next;
591 if( new_msg->m_type == STATUS )
592 new_msg->status_name = strdup(name);
598 /* we're a params node */
599 if( !strcmp((char*)cur_node->name,"params" )) {
603 cur_node = cur_node->next;
606 msgs[msg_index] = new_msg;
608 message_node = message_node->next;
610 } // while message_node != null
612 xmlCleanupCharEncodingHandlers();