1 #include "opensrf/osrf_message.h"
4 int parse_json_result = 1;
5 int parse_json_params = 1;
7 static void recurse_doc( xmlNodePtr node ) {
8 if( node == NULL ) return;
9 debug_handler("Recurse: %s => %s", node->name, node->content );
10 xmlNodePtr t = node->children;
19 osrf_message* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol ) {
21 osrf_message* msg = (osrf_message*) safe_malloc(sizeof(osrf_message));
23 msg->thread_trace = thread_trace;
24 msg->protocol = protocol;
26 msg->is_exception = 0;
27 msg->parse_json_result = parse_json_result;
28 msg->parse_json_params = parse_json_params;
29 msg->parray = init_string_array(16); /* start out with a slot for 16 params. can grow */
36 void osrf_message_set_json_parse_result( int ibool ) {
37 parse_json_result = ibool;
40 void osrf_message_set_json_parse_params( int ibool ) {
41 parse_json_params = ibool;
44 void osrf_message_set_request_info(
45 osrf_message* msg, char* method_name, json* json_params ) {
47 if( msg == NULL || method_name == NULL )
48 fatal_handler( "Bad params to osrf_message_set_request_params()" );
50 if(msg->parse_json_params) {
51 if( json_params != NULL )
52 msg->params = json_tokener_parse(json_object_to_json_string(json_params));
54 msg->params = json_tokener_parse("[]");
57 msg->method_name = strdup( method_name );
61 /* only works of parse_json_params is false */
62 void osrf_message_add_param( osrf_message* msg, char* param_string ) {
63 if(msg == NULL || param_string == NULL)
65 if(!msg->parse_json_params)
66 string_array_add(msg->parray, param_string);
70 void osrf_message_set_status_info(
71 osrf_message* msg, char* status_name, char* status_text, int status_code ) {
74 fatal_handler( "Bad params to osrf_message_set_status_info()" );
76 if( status_name != NULL )
77 msg->status_name = strdup( status_name );
79 if( status_text != NULL )
80 msg->status_text = strdup( status_text );
82 msg->status_code = status_code;
86 void osrf_message_set_result_content( osrf_message* msg, char* json_string ) {
87 if( msg == NULL || json_string == NULL)
88 warning_handler( "Bad params to osrf_message_set_result_content()" );
90 msg->result_string = strdup(json_string);
92 debug_handler( "Message Parse JSON is set to: %d", msg->parse_json_result );
94 if(msg->parse_json_result)
95 msg->result_content = json_tokener_parse(msg->result_string);
100 void osrf_message_free( osrf_message* msg ) {
104 if( msg->status_name != NULL )
105 free(msg->status_name);
107 if( msg->status_text != NULL )
108 free(msg->status_text);
110 if( msg->result_content != NULL )
111 json_object_put( msg->result_content );
113 if( msg->result_string != NULL )
114 free( msg->result_string);
116 if( msg->method_name != NULL )
117 free(msg->method_name);
119 if( msg->params != NULL )
120 json_object_put( msg->params );
122 string_array_destroy(msg->parray);
129 /* here's where things get interesting */
130 char* osrf_message_to_xml( osrf_message* msg ) {
139 xmlKeepBlanksDefault(0);
141 xmlNodePtr message_node;
142 xmlNodePtr type_node;
143 xmlNodePtr thread_trace_node;
144 xmlNodePtr protocol_node;
145 xmlNodePtr status_node;
146 xmlNodePtr status_text_node;
147 xmlNodePtr status_code_node;
148 xmlNodePtr method_node = NULL;
149 xmlNodePtr method_name_node;
150 xmlNodePtr params_node = NULL;
151 xmlNodePtr result_node;
152 xmlNodePtr content_node;
155 xmlDocPtr doc = xmlReadDoc(
156 BAD_CAST "<oils:root xmlns:oils='http://open-ils.org/xml/namespaces/oils_v1'>"
157 "<oils:domainObject name='oilsMessage'/></oils:root>",
158 NULL, NULL, XML_PARSE_NSCLEAN );
160 message_node = xmlDocGetRootElement(doc)->children; /* since it's the only child */
161 type_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
162 thread_trace_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
163 protocol_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
167 sprintf(tt,"%d",msg->thread_trace);
168 xmlSetProp( thread_trace_node, BAD_CAST "name", BAD_CAST "threadTrace" );
169 xmlSetProp( thread_trace_node, BAD_CAST "value", BAD_CAST tt );
173 sprintf(prot,"%d",msg->protocol);
174 xmlSetProp( protocol_node, BAD_CAST "name", BAD_CAST "protocol" );
175 xmlSetProp( protocol_node, BAD_CAST "value", BAD_CAST prot );
177 switch(msg->m_type) {
180 xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
181 xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "CONNECT" );
185 xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
186 xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "DISCONNECT" );
191 xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
192 xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "STATUS" );
193 status_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
194 xmlSetProp( status_node, BAD_CAST "name", BAD_CAST msg->status_name );
196 status_text_node = xmlNewChild( status_node, NULL, BAD_CAST "domainObjectAttr", NULL );
197 xmlSetProp( status_text_node, BAD_CAST "name", BAD_CAST "status" );
198 xmlSetProp( status_text_node, BAD_CAST "value", BAD_CAST msg->status_text);
200 status_code_node = xmlNewChild( status_node, NULL, BAD_CAST "domainObjectAttr", NULL );
201 xmlSetProp( status_code_node, BAD_CAST "name", BAD_CAST "statusCode" );
205 sprintf(sc,"%d",msg->status_code);
206 xmlSetProp( status_code_node, BAD_CAST "value", BAD_CAST sc);
212 xmlSetProp( type_node, BAD_CAST "name", "type" );
213 xmlSetProp( type_node, BAD_CAST "value", "REQUEST" );
214 method_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
215 xmlSetProp( method_node, BAD_CAST "name", BAD_CAST "oilsMethod" );
217 if( msg->method_name != NULL ) {
219 method_name_node = xmlNewChild( method_node, NULL, BAD_CAST "domainObjectAttr", NULL );
220 xmlSetProp( method_name_node, BAD_CAST "name", BAD_CAST "method" );
221 xmlSetProp( method_name_node, BAD_CAST "value", BAD_CAST msg->method_name );
223 if( msg->parse_json_params ) {
224 if( msg->params != NULL ) {
225 params_node = xmlNewChild( method_node, NULL,
226 BAD_CAST "params", BAD_CAST json_object_to_json_string( msg->params ) );
229 if( msg->parray != NULL ) {
231 /* construct the json array for the params */
232 growing_buffer* buf = buffer_init(128);
233 buffer_add( buf, "[");
235 for( k=0; k!= msg->parray->size; k++) {
236 buffer_add( buf, string_array_get_string(msg->parray, k) );
237 if(string_array_get_string(msg->parray, k+1))
238 buffer_add( buf, "," );
241 buffer_add( buf, "]");
243 char* tmp = safe_malloc( (buf->n_used + 1) * sizeof(char));
244 memcpy(tmp, buf->buf, buf->n_used);
246 params_node = xmlNewChild( method_node, NULL,
247 BAD_CAST "params", NULL );
249 xmlNodePtr tt = xmlNewDocTextLen( doc, BAD_CAST tmp, strlen(tmp) );
250 xmlAddChild(params_node, tt);
261 xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
262 xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "RESULT" );
263 result_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
264 xmlSetProp( result_node, BAD_CAST "name", BAD_CAST "oilsResult" );
266 status_text_node = xmlNewChild( result_node, NULL, BAD_CAST "domainObjectAttr", NULL );
267 xmlSetProp( status_text_node, BAD_CAST "name", BAD_CAST "status" );
268 xmlSetProp( status_text_node, BAD_CAST "value", BAD_CAST msg->status_text);
270 status_code_node = xmlNewChild( result_node, NULL, BAD_CAST "domainObjectAttr", NULL );
271 xmlSetProp( status_code_node, BAD_CAST "name", BAD_CAST "statusCode" );
275 sprintf(stc,"%d",msg->status_code);
276 xmlSetProp( status_code_node, BAD_CAST "value", BAD_CAST stc);
278 content_node = xmlNewChild( result_node, NULL,
279 BAD_CAST "domainObject", BAD_CAST msg->result_string );
280 xmlSetProp( content_node, BAD_CAST "name", BAD_CAST "oilsScalar" );
285 warning_handler( "Recieved bogus message type" );
290 // -----------------------------------------------------
291 // Dump the XML doc to a string and remove the
293 // -----------------------------------------------------
295 /* passing in a '1' means we want to retain the formatting */
297 //xmlDocDumpFormatMemory( doc, &xmlbuf, &bufsize, 0 );
298 //xmlDocDumpMemoryEnc( doc, &xmlbuf, &bufsize, "UTF-8" );
299 xmlDocDumpMemoryEnc( doc, &xmlbuf, &bufsize, "UTF-8" );
301 encoded_msg = strdup( (char*) xmlbuf );
304 if( encoded_msg == NULL )
305 fatal_handler("message_to_xml(): Out of Memory");
312 /*** remove the XML declaration */
313 int len = strlen(encoded_msg);
315 memset( tmp, 0, len );
319 /* when we reach the first >, take everything after it */
320 for( i = 0; i!= len; i++ ) {
321 if( encoded_msg[i] == 62) { /* ascii > */
323 /* found_at holds the starting index of the rest of the doc*/
330 /* move the shortened doc into the tmp buffer */
331 strncpy( tmp, encoded_msg + found_at, len - found_at );
332 /* move the tmp buffer back into the allocated space */
333 memset( encoded_msg, 0, len );
334 strcpy( encoded_msg, tmp );
344 int osrf_message_from_xml( char* xml, osrf_message* msgs[] ) {
348 xmlKeepBlanksDefault(0);
350 xmlNodePtr message_node;
351 xmlDocPtr doc = xmlReadDoc(
352 BAD_CAST xml, NULL, NULL, XML_PARSE_NSCLEAN );
354 xmlNodePtr root =xmlDocGetRootElement(doc);
356 warning_handler( "Attempt to build message from incomplete xml %s", xml );
361 message_node = root->children; /* since it's the only child */
364 warning_handler( "Attempt to build message from incomplete xml %s", xml );
368 while( message_node != NULL ) {
370 xmlNodePtr cur_node = message_node->children;
371 osrf_message* new_msg = safe_malloc(sizeof(osrf_message));
372 new_msg->parse_json_result = parse_json_result;
377 xmlChar* name = NULL;
378 xmlChar* value = NULL;
380 /* we're a domainObjectAttr */
381 if( !strcmp((char*)cur_node->name,"domainObjectAttr" )) {
382 name = xmlGetProp( cur_node, BAD_CAST "name");
386 value = xmlGetProp( cur_node, BAD_CAST "value" );
389 if( (!strcmp((char*)name, "type")) ) { /* what type are we? */
391 if(!strcmp((char*)value, "CONNECT"))
392 new_msg->m_type = CONNECT;
394 if(!strcmp((char*)value, "DISCONNECT"))
395 new_msg->m_type = DISCONNECT;
397 if(!strcmp((char*)value, "STATUS"))
398 new_msg->m_type = STATUS;
400 if(!strcmp((char*)value, "REQUEST"))
401 new_msg->m_type = REQUEST;
403 if(!strcmp((char*)value, "RESULT"))
404 new_msg->m_type = RESULT;
406 } else if((!strcmp((char*)name, "threadTrace"))) {
407 new_msg->thread_trace = atoi( (char*) value );
409 } else if((!strcmp((char*)name, "protocol"))) {
410 new_msg->protocol = atoi( (char*) value );
419 /* we're a domainObject */
420 if( !strcmp((char*)cur_node->name,"domainObject" )) {
422 name = xmlGetProp( cur_node, BAD_CAST "name");
426 if( !strcmp(name,"oilsMethod") ) {
428 xmlNodePtr meth_node = cur_node->children;
430 while( meth_node != NULL ) {
432 if( !strcmp((char*)meth_node->name,"domainObjectAttr" )) {
433 char* meth_name = xmlGetProp( meth_node, BAD_CAST "value" );
435 new_msg->method_name = strdup(meth_name);
440 if( !strcmp((char*)meth_node->name,"params" ) && meth_node->children->content ) {
441 //new_msg->params = json_object_new_string( meth_node->children->content );
442 if( new_msg->parse_json_params) {
443 new_msg->params = json_tokener_parse(meth_node->children->content);
445 /* XXX this will have to parse the JSON to
446 grab the strings for full support! This should only be
447 necessary for server support of
448 non-json-param-parsing, though. Ugh. */
449 new_msg->params = json_tokener_parse(meth_node->children->content);
453 meth_node = meth_node->next;
457 if( !strcmp(name,"oilsResult") || new_msg->m_type == STATUS ) {
459 xmlNodePtr result_nodes = cur_node->children;
461 while( result_nodes ) {
463 if(!strcmp(result_nodes->name,"domainObjectAttr")) {
465 xmlChar* result_attr_name = xmlGetProp( result_nodes, BAD_CAST "name");
466 if(result_attr_name) {
467 xmlChar* result_attr_value = xmlGetProp( result_nodes, BAD_CAST "value" );
469 if( result_attr_value ) {
470 if((!strcmp((char*)result_attr_name, "status")))
471 new_msg->status_text = strdup((char*) result_attr_value );
473 else if((!strcmp((char*)result_attr_name, "statusCode")))
474 new_msg->status_code = atoi((char*) result_attr_value );
475 xmlFree(result_attr_value);
478 xmlFree(result_attr_name);
484 if(!strcmp(result_nodes->name,"domainObject")) {
485 xmlChar* r_name = xmlGetProp( result_nodes, BAD_CAST "name" );
487 if( !strcmp((char*)r_name,"oilsScalar") && result_nodes->children->content ) {
488 osrf_message_set_result_content( new_msg, result_nodes->children->content);
493 result_nodes = result_nodes->next;
497 if( new_msg->m_type == STATUS )
498 new_msg->status_name = strdup(name);
504 /* we're a params node */
505 if( !strcmp((char*)cur_node->name,"params" )) {
509 cur_node = cur_node->next;
512 msgs[msg_index] = new_msg;
514 message_node = message_node->next;
516 } // while message_node != null
518 xmlCleanupCharEncodingHandlers();