]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/libstack/osrf_message.c
added a field to store the original JSON string received from a request
[OpenSRF.git] / src / libstack / osrf_message.c
1 #include "opensrf/osrf_message.h"
2
3
4 osrf_message* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol ) {
5
6         osrf_message* msg = safe_malloc(sizeof(osrf_message));
7         msg->m_type = type;
8         msg->thread_trace = thread_trace;
9         msg->protocol = protocol;
10         msg->next = NULL;
11         msg->is_exception = 0;
12
13         return msg;
14 }
15
16
17 void osrf_message_set_request_info( osrf_message* msg, char* method_name, json* json_params ) {
18         if( msg == NULL || method_name == NULL )
19                 fatal_handler( "Bad params to osrf_message_set_request_params()" );
20
21         if( json_params != NULL )
22                 msg->params = json_tokener_parse(json_object_to_json_string(json_params));
23         else
24                 msg->params = json_tokener_parse("[]");
25
26         msg->method_name = strdup( method_name );
27 }
28
29
30
31 void osrf_message_set_status_info( 
32                 osrf_message* msg, char* status_name, char* status_text, int status_code ) {
33
34         if( msg == NULL )
35                 fatal_handler( "Bad params to osrf_message_set_status_info()" );
36
37         if( status_name != NULL ) 
38                 msg->status_name = strdup( status_name );
39
40         if( status_text != NULL )
41                 msg->status_text = strdup( status_text );
42
43         msg->status_code = status_code;
44 }
45
46
47 void osrf_message_set_result_content( osrf_message* msg, json* result_content ) {
48         if( msg == NULL )
49                 fatal_handler( "Bad params to osrf_message_set_result_content()" );
50         msg->result_string =    strdup(json_object_to_json_string(result_content));
51         debug_handler("Setting result_string to %s\n", msg->result_string );
52         msg->result_content = json_tokener_parse(msg->result_string);
53 }
54
55
56
57 void osrf_message_free( osrf_message* msg ) {
58         if( msg == NULL )
59                 return;
60
61         if( msg->status_name != NULL )
62                 free(msg->status_name);
63
64         if( msg->status_text != NULL )
65                 free(msg->status_text);
66
67         if( msg->result_content != NULL )
68                 json_object_put( msg->result_content );
69
70         if( msg->result_string != NULL )
71                 free( msg->result_string);
72
73         if( msg->method_name != NULL )
74                 free(msg->method_name);
75
76         if( msg->params != NULL )
77                 json_object_put( msg->params );
78
79         free(msg);
80 }
81
82
83                 
84 /* here's where things get interesting */
85 char* osrf_message_to_xml( osrf_message* msg ) {
86
87         if( msg == NULL )
88                 return NULL;
89
90         int                     bufsize;
91         xmlChar*                xmlbuf;
92         char*                   encoded_msg;
93
94         xmlKeepBlanksDefault(0);
95
96         xmlNodePtr      message_node;
97         xmlNodePtr      type_node;
98         xmlNodePtr      thread_trace_node;
99         xmlNodePtr      protocol_node;
100         xmlNodePtr      status_node;
101         xmlNodePtr      status_text_node;
102         xmlNodePtr      status_code_node;
103         xmlNodePtr      method_node;
104         xmlNodePtr      method_name_node;
105         xmlNodePtr      params_node;
106         xmlNodePtr      result_node;
107         xmlNodePtr      content_node;
108
109
110         xmlDocPtr       doc = xmlReadDoc( 
111                         BAD_CAST "<oils:root xmlns:oils='http://open-ils.org/xml/namespaces/oils_v1'>"
112                         "<oils:domainObject name='oilsMessage'/></oils:root>", 
113                         NULL, NULL, XML_PARSE_NSCLEAN );
114
115         message_node = xmlDocGetRootElement(doc)->children; /* since it's the only child */
116         type_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
117         thread_trace_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
118         protocol_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObjectAttr", NULL );
119
120         char tt[64];
121         memset(tt,0,64);
122         sprintf(tt,"%d",msg->thread_trace);
123         xmlSetProp( thread_trace_node, BAD_CAST "name", BAD_CAST "threadTrace" );
124         xmlSetProp( thread_trace_node, BAD_CAST "value", BAD_CAST tt );
125
126         char prot[64];
127         memset(prot,0,64);
128         sprintf(prot,"%d",msg->protocol);
129         xmlSetProp( protocol_node, BAD_CAST "name", BAD_CAST "protocol" );
130         xmlSetProp( protocol_node, BAD_CAST "value", BAD_CAST prot );
131
132         switch(msg->m_type) {
133
134                 case CONNECT: 
135                         xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
136                         xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "CONNECT" );
137                         break;
138
139                 case DISCONNECT:
140                         xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
141                         xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "DISCONNECT" );
142                         break;
143
144                 case STATUS:
145
146                         xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
147                         xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "STATUS" );
148                         status_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
149                         xmlSetProp( status_node, BAD_CAST "name", BAD_CAST msg->status_name );
150
151                         status_text_node = xmlNewChild( status_node, NULL, BAD_CAST "domainObjectAttr", NULL );
152                         xmlSetProp( status_text_node, BAD_CAST "name", BAD_CAST "status" );
153                         xmlSetProp( status_text_node, BAD_CAST "value", BAD_CAST msg->status_text);
154
155                         status_code_node = xmlNewChild( status_node, NULL, BAD_CAST "domainObjectAttr", NULL );
156                         xmlSetProp( status_code_node, BAD_CAST "name", BAD_CAST "statusCode" );
157
158                         char sc[64];
159                         memset(sc,0,64);
160                         sprintf(sc,"%d",msg->status_code);
161                         xmlSetProp( status_code_node, BAD_CAST "value", BAD_CAST sc);
162                         
163                         break;
164
165                 case REQUEST:
166
167                         xmlSetProp( type_node, BAD_CAST "name", "type" );
168                         xmlSetProp( type_node, BAD_CAST "value", "REQUEST" );
169                         method_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
170                         xmlSetProp( method_node, BAD_CAST "name", BAD_CAST "oilsMethod" );
171
172                         if( msg->method_name != NULL ) {
173
174                                 method_name_node = xmlNewChild( method_node, NULL, BAD_CAST "domainObjectAttr", NULL );
175                                 xmlSetProp( method_name_node, BAD_CAST "name", BAD_CAST "method" );
176                                 xmlSetProp( method_name_node, BAD_CAST "value", BAD_CAST msg->method_name );
177
178                                 if( msg->params != NULL ) {
179                                         params_node = xmlNewChild( method_node, NULL, 
180                                                 BAD_CAST "params", BAD_CAST json_object_to_json_string( msg->params ) );
181                                 }
182                         }
183
184                         break;
185
186                 case RESULT:
187
188                         xmlSetProp( type_node, BAD_CAST "name", BAD_CAST "type" );
189                         xmlSetProp( type_node, BAD_CAST "value", BAD_CAST "RESULT" );
190                         result_node = xmlNewChild( message_node, NULL, BAD_CAST "domainObject", NULL );
191                         xmlSetProp( result_node, BAD_CAST "name", BAD_CAST "oilsResult" );
192
193                         status_text_node = xmlNewChild( result_node, NULL, BAD_CAST "domainObjectAttr", NULL );
194                         xmlSetProp( status_text_node, BAD_CAST "name", BAD_CAST "status" );
195                         xmlSetProp( status_text_node, BAD_CAST "value", BAD_CAST msg->status_text);
196
197                         status_code_node = xmlNewChild( result_node, NULL, BAD_CAST "domainObjectAttr", NULL );
198                         xmlSetProp( status_code_node, BAD_CAST "name", BAD_CAST "statusCode" );
199
200                         char stc[64];
201                         memset(stc,0,64);
202                         sprintf(stc,"%d",msg->status_code);
203                         xmlSetProp( status_code_node, BAD_CAST "value", BAD_CAST stc);
204
205                         content_node = xmlNewChild( result_node, NULL, 
206                                         BAD_CAST "domainObject", BAD_CAST msg->result_string );
207                         xmlSetProp( content_node, BAD_CAST "name", BAD_CAST "oilsScalar" );
208
209                         break;
210
211                 default:
212                         warning_handler( "Recieved bogus message type" );
213                         return NULL;
214         }
215
216
217         // -----------------------------------------------------
218         // Dump the XML doc to a string and remove the 
219         // xml declaration
220         // -----------------------------------------------------
221
222         /* passing in a '1' means we want to retain the formatting */
223         xmlDocDumpFormatMemory( doc, &xmlbuf, &bufsize, 0 );
224         encoded_msg = strdup( (char*) xmlbuf );
225
226         if( encoded_msg == NULL ) 
227                 fatal_handler("message_to_xml(): Out of Memory");
228
229         xmlFree(xmlbuf);
230         xmlFreeDoc( doc );
231         xmlCleanupParser();
232
233
234         /*** remove the XML declaration */
235         int len = strlen(encoded_msg);
236         char tmp[len];
237         memset( tmp, 0, len );
238         int i;
239         int found_at = 0;
240
241         /* when we reach the first >, take everything after it */
242         for( i = 0; i!= len; i++ ) {
243                 if( encoded_msg[i] == 62) { /* ascii > */
244
245                         /* found_at holds the starting index of the rest of the doc*/
246                         found_at = i + 1; 
247                         break;
248                 }
249         }
250
251         if( found_at ) {
252                 /* move the shortened doc into the tmp buffer */
253                 strncpy( tmp, encoded_msg + found_at, len - found_at );
254                 /* move the tmp buffer back into the allocated space */
255                 memset( encoded_msg, 0, len );
256                 strcpy( encoded_msg, tmp );
257         }
258
259         return encoded_msg;
260
261 }
262
263
264 int osrf_message_from_xml( char* xml, osrf_message* msgs[] ) {
265
266         if(!xml) return 0;
267
268         xmlKeepBlanksDefault(0);
269
270         xmlNodePtr      message_node;
271         xmlDocPtr       doc = xmlReadDoc( 
272                         BAD_CAST xml, NULL, NULL, XML_PARSE_NSCLEAN );
273
274         xmlNodePtr root =xmlDocGetRootElement(doc);
275         if(!root) {
276                 warning_handler( "Attempt to build message from incomplete xml %s", xml );
277                 return 0;
278         }
279
280         int msg_index = 0;
281         message_node = root->children; /* since it's the only child */
282
283         if(!message_node) {
284                 warning_handler( "Attempt to build message from incomplete xml %s", xml );
285                 return 0;
286         }
287
288         while( message_node != NULL ) {
289
290                 xmlNodePtr cur_node = message_node->children;
291                 osrf_message* new_msg = safe_malloc(sizeof(osrf_message));
292         
293
294                 while( cur_node ) {
295
296                         xmlChar* name = NULL; 
297                         xmlChar* value = NULL;
298                         
299                         /* we're a domainObjectAttr */
300                         if( !strcmp((char*)cur_node->name,"domainObjectAttr" )) {
301                                 name = xmlGetProp( cur_node, BAD_CAST "name");
302         
303                                 if(name) {
304         
305                                         value = xmlGetProp( cur_node, BAD_CAST "value" );
306                                         if(value) {
307         
308                                                 if( (!strcmp((char*)name, "type")) ) { /* what type are we? */
309         
310                                                         if(!strcmp((char*)value, "CONNECT"))
311                                                                 new_msg->m_type = CONNECT;
312         
313                                                         if(!strcmp((char*)value, "DISCONNECT"))
314                                                                 new_msg->m_type = DISCONNECT;
315                 
316                                                         if(!strcmp((char*)value, "STATUS"))
317                                                                 new_msg->m_type = STATUS;
318                 
319                                                         if(!strcmp((char*)value, "REQUEST"))
320                                                                 new_msg->m_type = REQUEST;
321                                                         
322                                                         if(!strcmp((char*)value, "RESULT"))
323                                                                 new_msg->m_type = RESULT;
324                         
325                                                 } else if((!strcmp((char*)name, "threadTrace"))) {
326                                                         new_msg->thread_trace = atoi( (char*) value );
327                         
328                                                 } else if((!strcmp((char*)name, "protocol"))) {
329                                                         new_msg->protocol = atoi( (char*) value );
330                                                 }
331         
332                                                 xmlFree(value);
333                                         }
334                                         xmlFree(name);
335                                 }
336                         }
337         
338                         /* we're a domainObject */
339                         if( !strcmp((char*)cur_node->name,"domainObject" )) {
340         
341                                 name = xmlGetProp( cur_node, BAD_CAST "name");
342         
343                                 if(name) {
344
345                                         if( !strcmp(name,"oilsMethod") ) {
346         
347                                                 xmlNodePtr meth_node = cur_node->children;
348         
349                                                 while( meth_node != NULL ) {
350         
351                                                         if( !strcmp((char*)meth_node->name,"domainObjectAttr" )) {
352                                                                 char* meth_name = xmlGetProp( meth_node, BAD_CAST "value" );
353                                                                 if(meth_name) {
354                                                                         new_msg->method_name = strdup(meth_name);
355                                                                         xmlFree(meth_name);
356                                                                 }
357                                                         }
358         
359                                                         if( !strcmp((char*)meth_node->name,"params" ) && meth_node->children->content ) 
360                                                                 //new_msg->params = json_object_new_string( meth_node->children->content );
361                                                                 new_msg->params = json_tokener_parse(meth_node->children->content);
362         
363                                                         meth_node = meth_node->next;
364                                                 }
365                                         } //oilsMethod
366         
367                                         if( !strcmp(name,"oilsResult") || new_msg->m_type == STATUS ) {
368         
369                                                 xmlNodePtr result_nodes = cur_node->children;
370         
371                                                 while( result_nodes ) {
372         
373                                                         if(!strcmp(result_nodes->name,"domainObjectAttr")) {
374         
375                                                                 xmlChar* result_attr_name = xmlGetProp( result_nodes, BAD_CAST "name");
376                                                                 if(result_attr_name) {
377                                                                         xmlChar* result_attr_value = xmlGetProp( result_nodes, BAD_CAST "value" );
378         
379                                                                         if( result_attr_value ) {
380                                                                                 if((!strcmp((char*)result_attr_name, "status"))) 
381                                                                                         new_msg->status_text = strdup((char*) result_attr_value );
382         
383                                                                                 else if((!strcmp((char*)result_attr_name, "statusCode"))) 
384                                                                                         new_msg->status_code = atoi((char*) result_attr_value );
385                                                                                 xmlFree(result_attr_value);
386                                                                         }
387         
388                                                                         xmlFree(result_attr_name);
389                                                                 }
390         
391                                                         }
392                                                 
393         
394                                                         if(!strcmp(result_nodes->name,"domainObject")) {
395                                                                 xmlChar* r_name = xmlGetProp( result_nodes, BAD_CAST "name" );
396                                                                 if(r_name) {
397                                                                         if( !strcmp((char*)r_name,"oilsScalar") && result_nodes->children->content ) {
398                                                                                 new_msg->result_string = strdup(result_nodes->children->content);
399                                                                                 new_msg->result_content = json_tokener_parse(result_nodes->children->content);
400                                                                         }
401                                                                         xmlFree(r_name);
402                                                                 }
403                                                         }
404                                                         result_nodes = result_nodes->next;
405                                                 }
406                                         }
407                                         
408                                         if( new_msg->m_type == STATUS ) 
409                                                 new_msg->status_name = strdup(name); 
410
411                                         xmlFree(name);
412                                 }
413                         }
414         
415                         /* we're a params node */
416                         if( !strcmp((char*)cur_node->name,"params" )) {
417         
418                         }
419         
420                         cur_node = cur_node->next;
421                 }
422         
423                 msgs[msg_index] = new_msg;
424                 msg_index++;
425                 message_node = message_node->next;
426
427         } // while message_node != null
428
429         xmlCleanupCharEncodingHandlers();
430         xmlFreeDoc( doc );
431         xmlCleanupParser();
432
433         return msg_index;
434
435 }
436
437