1 #include "opensrf/osrf_message.h"
4 int parse_json_result = 1;
5 int parse_json_params = 1;
7 osrf_message* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol ) {
9 osrf_message* msg = (osrf_message*) safe_malloc(sizeof(osrf_message));
11 msg->thread_trace = thread_trace;
12 msg->protocol = protocol;
14 msg->is_exception = 0;
15 msg->parse_json_result = parse_json_result;
16 msg->parse_json_params = parse_json_params;
17 msg->parray = init_string_array(16); /* start out with a slot for 16 params. can grow */
19 msg->full_param_string = NULL;
25 void osrf_message_set_json_parse_result( int ibool ) {
26 parse_json_result = ibool;
29 void osrf_message_set_json_parse_params( int ibool ) {
30 parse_json_params = ibool;
33 void osrf_message_set_request_info(
34 osrf_message* msg, char* method_name, json* json_params ) {
36 if( msg == NULL || method_name == NULL )
37 fatal_handler( "Bad params to osrf_message_set_request_params()" );
39 if(msg->parse_json_params) {
40 if( json_params != NULL )
41 msg->params = json_tokener_parse(json_object_to_json_string(json_params));
43 msg->params = json_tokener_parse("[]");
46 msg->method_name = strdup( method_name );
50 /* only works of parse_json_params is false */
51 void osrf_message_add_param( osrf_message* msg, char* param_string ) {
52 if(msg == NULL || param_string == NULL)
54 if(!msg->parse_json_params)
55 string_array_add(msg->parray, param_string);
59 void osrf_message_set_status_info(
60 osrf_message* msg, char* status_name, char* status_text, int status_code ) {
63 fatal_handler( "Bad params to osrf_message_set_status_info()" );
65 if( status_name != NULL )
66 msg->status_name = strdup( status_name );
68 if( status_text != NULL )
69 msg->status_text = strdup( status_text );
71 msg->status_code = status_code;
75 void osrf_message_set_result_content( osrf_message* msg, char* json_string ) {
76 if( msg == NULL || json_string == NULL)
77 warning_handler( "Bad params to osrf_message_set_result_content()" );
79 msg->result_string = strdup(json_string);
80 debug_handler("Setting result_string to %s\n", msg->result_string );
82 debug_handler( "Message Parse JSON is set to: %d", msg->parse_json_result );
84 if(msg->parse_json_result)
85 msg->result_content = json_tokener_parse(msg->result_string);
90 void osrf_message_free( osrf_message* msg ) {
94 if( msg->status_name != NULL )
95 free(msg->status_name);
97 if( msg->status_text != NULL )
98 free(msg->status_text);
100 if( msg->result_content != NULL )
101 json_object_put( msg->result_content );
103 if( msg->result_string != NULL )
104 free( msg->result_string);
106 if( msg->method_name != NULL )
107 free(msg->method_name);
109 if(msg->full_param_string)
110 free(msg->full_param_string);
112 if( msg->params != NULL )
113 json_object_put( msg->params );
115 string_array_destroy(msg->parray);
122 /* here's where things get interesting */
123 char* osrf_message_to_xml( osrf_message* msg ) {
132 xmlKeepBlanksDefault(0);
134 xmlNodePtr message_node;
135 xmlNodePtr type_node;
136 xmlNodePtr thread_trace_node;
137 xmlNodePtr protocol_node;
138 xmlNodePtr status_node;
139 xmlNodePtr status_text_node;
140 xmlNodePtr status_code_node;
141 xmlNodePtr method_node;
142 xmlNodePtr method_name_node;
143 xmlNodePtr params_node;
144 xmlNodePtr result_node;
145 xmlNodePtr content_node;
148 xmlDocPtr doc = xmlReadDoc(
149 BAD_CAST "<oils:root xmlns:oils='http://open-ils.org/xml/namespaces/oils_v1'>"
150 "<oils:domainObject name='oilsMessage'/></oils:root>",
151 NULL, NULL, XML_PARSE_NSCLEAN );
153 message_node = xmlDocGetRootElement(doc)->children; /* since it's the only child */
154 type_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
155 thread_trace_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
156 protocol_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
160 sprintf(tt,"%d",msg->thread_trace);
161 xmlSetProp( thread_trace_node, BAD_CAST "name", BAD_CAST "threadTrace" );
162 xmlSetProp( thread_trace_node, BAD_CAST "value", BAD_CAST tt );
166 sprintf(prot,"%d",msg->protocol);
167 xmlSetProp( protocol_node, BAD_CAST "name", BAD_CAST "protocol" );
168 xmlSetProp( protocol_node, BAD_CAST "value", BAD_CAST prot );
170 switch(msg->m_type) {
173 xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
174 xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "CONNECT" );
178 xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
179 xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "DISCONNECT" );
184 xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
185 xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "STATUS" );
186 status_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
187 xmlSetProp( status_node, BAD_CAST "name", BAD_CAST msg->status_name );
189 status_text_node = xmlNewChild( status_node, NULL, BAD_CAST "domainObjectAttr", NULL );
190 xmlSetProp( status_text_node, BAD_CAST "name", BAD_CAST "status" );
191 xmlSetProp( status_text_node, BAD_CAST "value", BAD_CAST msg->status_text);
193 status_code_node = xmlNewChild( status_node, NULL, BAD_CAST "domainObjectAttr", NULL );
194 xmlSetProp( status_code_node, BAD_CAST "name", BAD_CAST "statusCode" );
198 sprintf(sc,"%d",msg->status_code);
199 xmlSetProp( status_code_node, BAD_CAST "value", BAD_CAST sc);
205 xmlSetProp( type_node, BAD_CAST "name", "type" );
206 xmlSetProp( type_node, BAD_CAST "value", "REQUEST" );
207 method_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
208 xmlSetProp( method_node, BAD_CAST "name", BAD_CAST "oilsMethod" );
210 if( msg->method_name != NULL ) {
212 method_name_node = xmlNewChild( method_node, NULL, BAD_CAST "domainObjectAttr", NULL );
213 xmlSetProp( method_name_node, BAD_CAST "name", BAD_CAST "method" );
214 xmlSetProp( method_name_node, BAD_CAST "value", BAD_CAST msg->method_name );
216 if( msg->parse_json_params ) {
217 if( msg->params != NULL ) {
218 params_node = xmlNewChild( method_node, NULL,
219 BAD_CAST "params", BAD_CAST json_object_to_json_string( msg->params ) );
222 if( msg->parray != NULL ) {
223 /* construct the json array for the params */
224 growing_buffer* buf = buffer_init(128);
225 buffer_add( buf, "[");
227 for( k=0; k!= msg->parray->size; k++) {
228 buffer_add( buf, string_array_get_string(msg->parray, k) );
229 buffer_add( buf, "," );
232 /* remove trailing comma */
233 if(buf->buf[buf->n_used - 1] == ',') {
234 buf->buf[buf->n_used - 1] = '\0';
237 buffer_add( buf, "]");
238 msg->full_param_string = buffer_data(buf);
241 params_node = xmlNewChild( method_node, NULL,
242 BAD_CAST "params", BAD_CAST buf->buf );
253 xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
254 xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "RESULT" );
255 result_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
256 xmlSetProp( result_node, BAD_CAST "name", BAD_CAST "oilsResult" );
258 status_text_node = xmlNewChild( result_node, NULL, BAD_CAST "domainObjectAttr", NULL );
259 xmlSetProp( status_text_node, BAD_CAST "name", BAD_CAST "status" );
260 xmlSetProp( status_text_node, BAD_CAST "value", BAD_CAST msg->status_text);
262 status_code_node = xmlNewChild( result_node, NULL, BAD_CAST "domainObjectAttr", NULL );
263 xmlSetProp( status_code_node, BAD_CAST "name", BAD_CAST "statusCode" );
267 sprintf(stc,"%d",msg->status_code);
268 xmlSetProp( status_code_node, BAD_CAST "value", BAD_CAST stc);
270 content_node = xmlNewChild( result_node, NULL,
271 BAD_CAST "domainObject", BAD_CAST msg->result_string );
272 xmlSetProp( content_node, BAD_CAST "name", BAD_CAST "oilsScalar" );
277 warning_handler( "Recieved bogus message type" );
282 // -----------------------------------------------------
283 // Dump the XML doc to a string and remove the
285 // -----------------------------------------------------
287 /* passing in a '1' means we want to retain the formatting */
288 xmlDocDumpFormatMemory( doc, &xmlbuf, &bufsize, 0 );
289 encoded_msg = strdup( (char*) xmlbuf );
291 if( encoded_msg == NULL )
292 fatal_handler("message_to_xml(): Out of Memory");
299 /*** remove the XML declaration */
300 int len = strlen(encoded_msg);
302 memset( tmp, 0, len );
306 /* when we reach the first >, take everything after it */
307 for( i = 0; i!= len; i++ ) {
308 if( encoded_msg[i] == 62) { /* ascii > */
310 /* found_at holds the starting index of the rest of the doc*/
317 /* move the shortened doc into the tmp buffer */
318 strncpy( tmp, encoded_msg + found_at, len - found_at );
319 /* move the tmp buffer back into the allocated space */
320 memset( encoded_msg, 0, len );
321 strcpy( encoded_msg, tmp );
329 int osrf_message_from_xml( char* xml, osrf_message* msgs[] ) {
333 xmlKeepBlanksDefault(0);
335 xmlNodePtr message_node;
336 xmlDocPtr doc = xmlReadDoc(
337 BAD_CAST xml, NULL, NULL, XML_PARSE_NSCLEAN );
339 xmlNodePtr root =xmlDocGetRootElement(doc);
341 warning_handler( "Attempt to build message from incomplete xml %s", xml );
346 message_node = root->children; /* since it's the only child */
349 warning_handler( "Attempt to build message from incomplete xml %s", xml );
353 while( message_node != NULL ) {
355 xmlNodePtr cur_node = message_node->children;
356 osrf_message* new_msg = safe_malloc(sizeof(osrf_message));
357 new_msg->parse_json_result = parse_json_result;
362 xmlChar* name = NULL;
363 xmlChar* value = NULL;
365 /* we're a domainObjectAttr */
366 if( !strcmp((char*)cur_node->name,"domainObjectAttr" )) {
367 name = xmlGetProp( cur_node, BAD_CAST "name");
371 value = xmlGetProp( cur_node, BAD_CAST "value" );
374 if( (!strcmp((char*)name, "type")) ) { /* what type are we? */
376 if(!strcmp((char*)value, "CONNECT"))
377 new_msg->m_type = CONNECT;
379 if(!strcmp((char*)value, "DISCONNECT"))
380 new_msg->m_type = DISCONNECT;
382 if(!strcmp((char*)value, "STATUS"))
383 new_msg->m_type = STATUS;
385 if(!strcmp((char*)value, "REQUEST"))
386 new_msg->m_type = REQUEST;
388 if(!strcmp((char*)value, "RESULT"))
389 new_msg->m_type = RESULT;
391 } else if((!strcmp((char*)name, "threadTrace"))) {
392 new_msg->thread_trace = atoi( (char*) value );
394 } else if((!strcmp((char*)name, "protocol"))) {
395 new_msg->protocol = atoi( (char*) value );
404 /* we're a domainObject */
405 if( !strcmp((char*)cur_node->name,"domainObject" )) {
407 name = xmlGetProp( cur_node, BAD_CAST "name");
411 if( !strcmp(name,"oilsMethod") ) {
413 xmlNodePtr meth_node = cur_node->children;
415 while( meth_node != NULL ) {
417 if( !strcmp((char*)meth_node->name,"domainObjectAttr" )) {
418 char* meth_name = xmlGetProp( meth_node, BAD_CAST "value" );
420 new_msg->method_name = strdup(meth_name);
425 if( !strcmp((char*)meth_node->name,"params" ) && meth_node->children->content ) {
426 //new_msg->params = json_object_new_string( meth_node->children->content );
427 if( new_msg->parse_json_params) {
428 new_msg->params = json_tokener_parse(meth_node->children->content);
430 /* XXX this will have to parse the JSON to
431 grab the strings for full support! This should only be
432 necessary for server support of
433 non-json-param-parsing, though. Ugh. */
434 new_msg->params = json_tokener_parse(meth_node->children->content);
438 meth_node = meth_node->next;
442 if( !strcmp(name,"oilsResult") || new_msg->m_type == STATUS ) {
444 xmlNodePtr result_nodes = cur_node->children;
446 while( result_nodes ) {
448 if(!strcmp(result_nodes->name,"domainObjectAttr")) {
450 xmlChar* result_attr_name = xmlGetProp( result_nodes, BAD_CAST "name");
451 if(result_attr_name) {
452 xmlChar* result_attr_value = xmlGetProp( result_nodes, BAD_CAST "value" );
454 if( result_attr_value ) {
455 if((!strcmp((char*)result_attr_name, "status")))
456 new_msg->status_text = strdup((char*) result_attr_value );
458 else if((!strcmp((char*)result_attr_name, "statusCode")))
459 new_msg->status_code = atoi((char*) result_attr_value );
460 xmlFree(result_attr_value);
463 xmlFree(result_attr_name);
469 if(!strcmp(result_nodes->name,"domainObject")) {
470 xmlChar* r_name = xmlGetProp( result_nodes, BAD_CAST "name" );
472 if( !strcmp((char*)r_name,"oilsScalar") && result_nodes->children->content ) {
473 osrf_message_set_result_content( new_msg, result_nodes->children->content);
478 result_nodes = result_nodes->next;
482 if( new_msg->m_type == STATUS )
483 new_msg->status_name = strdup(name);
489 /* we're a params node */
490 if( !strcmp((char*)cur_node->name,"params" )) {
494 cur_node = cur_node->next;
497 msgs[msg_index] = new_msg;
499 message_node = message_node->next;
501 } // while message_node != null
503 xmlCleanupCharEncodingHandlers();