]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/libopensrf/osrf_message.c
ed1e62045e6c3360957e61205d16970ab6a0b600
[OpenSRF.git] / src / libopensrf / osrf_message.c
1 #include <opensrf/osrf_message.h>
2
3 static char default_locale[17] = "en-US\0\0\0\0\0\0\0\0\0\0\0\0";
4 static char* current_locale = NULL;
5
6 osrfMessage* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol ) {
7
8         osrfMessage* msg                        = (osrfMessage*) safe_malloc(sizeof(osrfMessage));
9         msg->m_type                                     = type;
10         msg->thread_trace                       = thread_trace;
11         msg->protocol                           = protocol;
12         msg->status_name                        = NULL;
13         msg->status_text                        = NULL;
14         msg->status_code                        = 0;
15         msg->next                                       = NULL;
16         msg->is_exception                       = 0;
17         msg->_params                            = NULL;
18         msg->_result_content            = NULL;
19         msg->result_string                      = NULL;
20         msg->method_name                        = NULL;
21         msg->full_param_string          = NULL;
22         msg->sender_locale              = NULL;
23         msg->sender_tz_offset           = 0;
24
25         return msg;
26 }
27
28
29 const char* osrf_message_get_last_locale() {
30         return current_locale;
31 }
32
33 char* osrf_message_set_locale( osrfMessage* msg, const char* locale ) {
34         if( msg == NULL || locale == NULL ) return NULL;
35         return msg->sender_locale = strdup( locale );
36 }
37
38 const char* osrf_message_set_default_locale( const char* locale ) {
39         if( locale == NULL ) return NULL;
40         if( strlen(locale) > sizeof(default_locale) - 1 ) return NULL;
41
42         strcpy( default_locale, locale );
43         return (const char*) default_locale;
44 }
45
46 void osrf_message_set_method( osrfMessage* msg, const char* method_name ) {
47         if( msg == NULL || method_name == NULL ) return;
48         msg->method_name = strdup( method_name );
49 }
50
51
52 /**
53         @brief Wrap a copy of a jsonObject in a JSON_ARRAY and store it in an osrfMessage.
54         @param msg Pointer to the osrfMessage.
55         @param o Pointer to the jsonObject of which a copy is to be stored.
56
57         Make a copy of the input jsonObject, with all classnames encoded with
58         JSON_CLASS_KEY and JSON_DATA_KEY.  Append it to a JSON_ARRAY stored at
59         msg->_params.
60
61         If there is nothing at msg->_params, create a new JSON_ARRAY
62         for it and add the new object as the first element.
63 */
64 void osrf_message_add_object_param( osrfMessage* msg, const jsonObject* o ) {
65         if(!msg|| !o) return;
66         if(!msg->_params)
67                 msg->_params = jsonNewObjectType( JSON_ARRAY );
68         jsonObjectPush(msg->_params, jsonObjectDecodeClass( o ));
69 }
70
71 void osrf_message_set_params( osrfMessage* msg, const jsonObject* o ) {
72         if(!msg || !o) return;
73
74         if(o->type != JSON_ARRAY) {
75                 osrfLogDebug( OSRF_LOG_MARK, "passing non-array to osrf_message_set_params(), fixing...");
76                 if(msg->_params) jsonObjectFree(msg->_params);
77                 jsonObject* clone = jsonObjectClone(o);
78                 msg->_params = jsonNewObject(NULL);
79                 jsonObjectPush(msg->_params, clone);
80                 return;
81         }
82
83         if(msg->_params) jsonObjectFree(msg->_params);
84         msg->_params = jsonObjectClone(o);
85 }
86
87
88 /* only works if parse_json_params is false */
89 void osrf_message_add_param( osrfMessage* msg, const char* param_string ) {
90         if(msg == NULL || param_string == NULL) return;
91         if(!msg->_params) msg->_params = jsonNewObjectType( JSON_ARRAY );
92         jsonObjectPush(msg->_params, jsonParseString(param_string));
93 }
94
95
96 void osrf_message_set_status_info( osrfMessage* msg,
97                 const char* status_name, const char* status_text, int status_code ) {
98         if(!msg) return;
99
100         if( status_name != NULL ) 
101                 msg->status_name = strdup( status_name );
102
103         if( status_text != NULL )
104                 msg->status_text = strdup( status_text );
105
106         msg->status_code = status_code;
107 }
108
109
110 void osrf_message_set_result_content( osrfMessage* msg, const char* json_string ) {
111         if( msg == NULL || json_string == NULL) return;
112         msg->result_string =    strdup(json_string);
113         msg->_result_content = jsonParseString(json_string);
114 }
115
116
117
118 void osrfMessageFree( osrfMessage* msg ) {
119         if( msg == NULL )
120                 return;
121
122         if( msg->status_name != NULL )
123                 free(msg->status_name);
124
125         if( msg->status_text != NULL )
126                 free(msg->status_text);
127
128         if( msg->_result_content != NULL )
129                 jsonObjectFree( msg->_result_content );
130
131         if( msg->result_string != NULL )
132                 free( msg->result_string);
133
134         if( msg->method_name != NULL )
135                 free(msg->method_name);
136
137         if( msg->sender_locale != NULL )
138                 free(msg->sender_locale);
139
140         if( msg->_params != NULL )
141                 jsonObjectFree(msg->_params);
142
143         free(msg);
144 }
145
146
147 char* osrfMessageSerializeBatch( osrfMessage* msgs [], int count ) {
148         if( !msgs ) return NULL;
149
150         char* j;
151         int i = 0;
152         const osrfMessage* msg = NULL;
153         jsonObject* wrapper = jsonNewObject(NULL);
154
155         while( ((msg = msgs[i]) && (i++ < count)) ) 
156                 jsonObjectPush(wrapper, osrfMessageToJSON( msg ));
157
158         j = jsonObjectToJSON(wrapper);
159         jsonObjectFree(wrapper);
160
161         return j;       
162 }
163
164
165 char* osrf_message_serialize(const osrfMessage* msg) {
166
167         if( msg == NULL ) return NULL;
168         char* j = NULL;
169
170         jsonObject* json = osrfMessageToJSON( msg );
171
172         if(json) {
173                 jsonObject* wrapper = jsonNewObject(NULL);
174                 jsonObjectPush(wrapper, json);
175                 j = jsonObjectToJSON(wrapper);
176                 jsonObjectFree(wrapper);
177         }
178
179         return j;
180 }
181
182
183 jsonObject* osrfMessageToJSON( const osrfMessage* msg ) {
184
185         jsonObject* json = jsonNewObject(NULL);
186         jsonObjectSetClass(json, "osrfMessage");
187         jsonObject* payload;
188         char sc[64];
189         osrf_clearbuf(sc, sizeof(sc));
190
191         INT_TO_STRING(msg->thread_trace);
192         jsonObjectSetKey(json, "threadTrace", jsonNewObject(INTSTR));
193
194         if (msg->sender_locale != NULL) {
195                 jsonObjectSetKey(json, "locale", jsonNewObject(msg->sender_locale));
196         } else if (current_locale != NULL) {
197                 jsonObjectSetKey(json, "locale", jsonNewObject(current_locale));
198         } else {
199                 jsonObjectSetKey(json, "locale", jsonNewObject(default_locale));
200         }
201
202         switch(msg->m_type) {
203                 
204                 case CONNECT: 
205                         jsonObjectSetKey(json, "type", jsonNewObject("CONNECT"));
206                         break;
207
208                 case DISCONNECT: 
209                         jsonObjectSetKey(json, "type", jsonNewObject("DISCONNECT"));
210                         break;
211
212                 case STATUS:
213                         jsonObjectSetKey(json, "type", jsonNewObject("STATUS"));
214                         payload = jsonNewObject(NULL);
215                         jsonObjectSetClass(payload, msg->status_name);
216                         jsonObjectSetKey(payload, "status", jsonNewObject(msg->status_text));
217                         snprintf(sc, sizeof(sc), "%d", msg->status_code);
218                         jsonObjectSetKey(payload, "statusCode", jsonNewObject(sc));
219                         jsonObjectSetKey(json, "payload", payload);
220                         break;
221
222                 case REQUEST:
223                         jsonObjectSetKey(json, "type", jsonNewObject("REQUEST"));
224                         payload = jsonNewObject(NULL);
225                         jsonObjectSetClass(payload, "osrfMethod");
226                         jsonObjectSetKey(payload, "method", jsonNewObject(msg->method_name));
227                         jsonObjectSetKey( payload, "params", jsonObjectDecodeClass( msg->_params ) );
228                         jsonObjectSetKey(json, "payload", payload);
229
230                         break;
231
232                 case RESULT:
233                         jsonObjectSetKey(json, "type", jsonNewObject("RESULT"));
234                         payload = jsonNewObject(NULL);
235                         jsonObjectSetClass(payload,"osrfResult");
236                         jsonObjectSetKey(payload, "status", jsonNewObject(msg->status_text));
237                         snprintf(sc, sizeof(sc), "%d", msg->status_code);
238                         jsonObjectSetKey(payload, "statusCode", jsonNewObject(sc));
239                         jsonObjectSetKey(payload, "content", jsonObjectDecodeClass( msg->_result_content ));
240                         jsonObjectSetKey(json, "payload", payload);
241                         break;
242         }
243
244         return json;
245 }
246
247
248 int osrf_message_deserialize(const char* string, osrfMessage* msgs[], int count) {
249
250         if(!string || !msgs || count <= 0) return 0;
251         int numparsed = 0;
252
253         jsonObject* json = jsonParseString(string);
254
255         if(!json) {
256                 osrfLogWarning( OSRF_LOG_MARK, 
257                         "osrf_message_deserialize() unable to parse data: \n%s\n", string);
258                 return 0;
259         }
260
261         int x;
262
263         for( x = 0; x < json->size && x < count; x++ ) {
264
265                 const jsonObject* message = jsonObjectGetIndex(json, x);
266
267                 if(message && message->type != JSON_NULL && 
268                         message->classname && !strcmp(message->classname, "osrfMessage")) {
269
270                         osrfMessage* new_msg = safe_malloc(sizeof(osrfMessage));
271                         new_msg->m_type = 0;
272                         new_msg->thread_trace = 0;
273                         new_msg->protocol = 0;
274                         new_msg->status_name = NULL;
275                         new_msg->status_text = NULL;
276                         new_msg->status_code = 0;
277                         new_msg->is_exception = 0;
278                         new_msg->_result_content = NULL;
279                         new_msg->result_string = NULL;
280                         new_msg->method_name = NULL;
281                         new_msg->_params = NULL;
282                         new_msg->next = NULL;
283                         new_msg->full_param_string = NULL;
284                         new_msg->sender_locale = NULL;
285                         new_msg->sender_tz_offset = 0;
286
287                         const jsonObject* tmp = jsonObjectGetKeyConst(message, "type");
288
289                         const char* t;
290                         if( ( t = jsonObjectGetString(tmp)) ) {
291
292                                 if(!strcmp(t, "CONNECT"))               new_msg->m_type = CONNECT;
293                                 else if(!strcmp(t, "DISCONNECT"))       new_msg->m_type = DISCONNECT;
294                                 else if(!strcmp(t, "STATUS"))           new_msg->m_type = STATUS;
295                                 else if(!strcmp(t, "REQUEST"))          new_msg->m_type = REQUEST;
296                                 else if(!strcmp(t, "RESULT"))           new_msg->m_type = RESULT;
297                         }
298
299                         tmp = jsonObjectGetKeyConst(message, "threadTrace");
300                         if(tmp) {
301                                 char* tt = jsonObjectToSimpleString(tmp);
302                                 if(tt) {
303                                         new_msg->thread_trace = atoi(tt);
304                                         free(tt);
305                                 }
306                         }
307
308                         /* use the sender's locale, or the global default */
309                         if (current_locale)
310                                 free( current_locale );
311
312                         tmp = jsonObjectGetKeyConst(message, "locale");
313
314                         if(tmp && (new_msg->sender_locale = jsonObjectToSimpleString(tmp))) {
315                                 current_locale = strdup( new_msg->sender_locale );
316                         } else {
317                                 current_locale = NULL;
318                         }
319
320                         tmp = jsonObjectGetKeyConst(message, "protocol");
321
322                         if(tmp) {
323                                 char* proto = jsonObjectToSimpleString(tmp);
324                                 if(proto) {
325                                         new_msg->protocol = atoi(proto);
326                                         free(proto);
327                                 }
328                         }
329
330                         tmp = jsonObjectGetKeyConst(message, "payload");
331                         if(tmp) {
332                                 if(tmp->classname)
333                                         new_msg->status_name = strdup(tmp->classname);
334
335                                 const jsonObject* tmp0 = jsonObjectGetKeyConst(tmp,"method");
336                                 const char* tmp_str = jsonObjectGetString(tmp0);
337                                 if(tmp_str)
338                                         new_msg->method_name = strdup(tmp_str);
339
340                                 tmp0 = jsonObjectGetKeyConst(tmp,"params");
341                                 if(tmp0) {
342                                         new_msg->_params = jsonObjectDecodeClass( tmp0 );
343                                         if(new_msg->_params && new_msg->_params->type == JSON_NULL) 
344                                                 new_msg->_params->type = JSON_ARRAY;
345                                 }
346
347                                 tmp0 = jsonObjectGetKeyConst(tmp,"status");
348                                 tmp_str = jsonObjectGetString(tmp0);
349                                 if(tmp_str)
350                                         new_msg->status_text = strdup(tmp_str);
351
352                                 tmp0 = jsonObjectGetKeyConst(tmp,"statusCode");
353                                 if(tmp0) {
354                                         tmp_str = jsonObjectGetString(tmp0);
355                                         if(tmp_str)
356                                                 new_msg->status_code = atoi(tmp_str);
357                                         if(tmp0->type == JSON_NUMBER)
358                                                 new_msg->status_code = (int) jsonObjectGetNumber(tmp0);
359                                 }
360
361                                 tmp0 = jsonObjectGetKeyConst(tmp,"content");
362                                 if(tmp0) {
363                                         new_msg->_result_content = jsonObjectDecodeClass( tmp0 );
364                                 }
365
366                         }
367                         msgs[numparsed++] = new_msg;
368                 }
369         }
370
371         jsonObjectFree(json);
372         return numparsed;
373 }
374
375
376
377 jsonObject* osrfMessageGetResult( osrfMessage* msg ) {
378         if(msg) return msg->_result_content;
379         return NULL;
380 }
381