some api changes
authorerickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Thu, 15 Sep 2005 22:57:18 +0000 (22:57 +0000)
committererickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Thu, 15 Sep 2005 22:57:18 +0000 (22:57 +0000)
tested the cache stuff better
added #define for enforcing argc on methods
system methods are registered through the same facility as regular methods

git-svn-id: svn://svn.open-ils.org/ILS/trunk@1831 dcc99617-32d9-48b4-a31d-7c20da2025e4

OpenSRF/src/c-apps/osrf_dbmath.c
OpenSRF/src/c-apps/osrf_math.c
OpenSRF/src/c-apps/osrf_version.c
OpenSRF/src/libstack/Makefile
OpenSRF/src/libstack/osrf_application.c
OpenSRF/src/libstack/osrf_application.h
OpenSRF/src/libstack/osrf_cache.c
OpenSRF/src/libstack/osrf_message.c

index 07cf0f6..0acecaf 100644 (file)
@@ -3,17 +3,45 @@
 #include "objson/object.h"
 #include "opensrf/osrf_log.h"
 
+#define MODULENAME "opensrf.dbmath"
+
 int osrfAppInitialize();
 int osrfAppChildInit();
 int osrfMathRun( osrfMethodContext* );
 
 
 int osrfAppInitialize() {
-       osrfLogInit("opensrf.dbmath");
-       osrfAppRegisterMethod( "opensrf.dbmath", "add", "osrfMathRun", "send 2 numbers and I'll add them", 2 );
-       osrfAppRegisterMethod( "opensrf.dbmath", "sub", "osrfMathRun", "send 2 numbers and I'll divide them", 2 );
-       osrfAppRegisterMethod( "opensrf.dbmath", "mult", "osrfMathRun", "send 2 numbers and I'll multiply them", 2 );
-       osrfAppRegisterMethod( "opensrf.dbmath", "div", "osrfMathRun", "send 2 numbers and I'll subtract them", 2 );
+
+       osrfLogInit(MODULENAME);
+
+       osrfAppRegisterMethod( 
+                       MODULENAME, 
+                       "add", 
+                       "osrfMathRun", 
+                       "Addss two numbers",
+                       "[ num1, num2 ]", 2 );
+
+       osrfAppRegisterMethod( 
+                       MODULENAME, 
+                       "sub", 
+                       "osrfMathRun", 
+                       "Subtracts two numbers",
+                       "[ num1, num2 ]", 2 );
+
+       osrfAppRegisterMethod( 
+                       MODULENAME, 
+                       "mult", 
+                       "osrfMathRun", 
+                       "Multiplies two numbers",
+                       "[ num1, num2 ]", 2 );
+
+       osrfAppRegisterMethod( 
+                       MODULENAME, 
+                       "div", 
+                       "osrfMathRun", 
+                       "Divides two numbers",
+                       "[ num1, num2 ]", 2 );
+
        return 0;
 }
 
index 9cb22aa..78a9ddc 100644 (file)
@@ -3,18 +3,44 @@
 #include "objson/object.h"
 #include "opensrf/osrf_log.h"
 
+#define MODULENAME "opensrf.math"
+
 int osrfAppInitialize();
 int osrfAppChildInit();
 int osrfMathRun( osrfMethodContext* );
 
 
 int osrfAppInitialize() {
-       osrfLogInit("opensrf.math");
-       /* tell the server about the methods we handle */
-       osrfAppRegisterMethod( "opensrf.math", "add", "osrfMathRun", "send 2 numbers and I'll add them", 2 );
-       osrfAppRegisterMethod( "opensrf.math", "sub", "osrfMathRun", "send 2 numbers and I'll divide them", 2 );
-       osrfAppRegisterMethod( "opensrf.math", "mult", "osrfMathRun", "send 2 numbers and I'll multiply them", 2 );
-       osrfAppRegisterMethod( "opensrf.math", "div", "osrfMathRun", "send 2 numbers and I'll subtract them", 2 );
+       osrfLogInit(MODULENAME);
+
+       osrfAppRegisterMethod( 
+                       MODULENAME, 
+                       "add", 
+                       "osrfMathRun", 
+                       "Addss two numbers",
+                       "( num1, num2 )", 2 );
+
+       osrfAppRegisterMethod( 
+                       MODULENAME, 
+                       "sub", 
+                       "osrfMathRun", 
+                       "Subtracts two numbers",
+                       "( num1, num2 )", 2 );
+
+       osrfAppRegisterMethod( 
+                       MODULENAME, 
+                       "mult", 
+                       "osrfMathRun", 
+                       "Multiplies two numbers",
+                       "( num1, num2 )", 2 );
+
+       osrfAppRegisterMethod( 
+                       MODULENAME, 
+                       "div", 
+                       "osrfMathRun", 
+                       "Divides two numbers",
+                       "( num1, num2 )", 2 );
+
        return 0;
 }
 
index 6785315..2936607 100644 (file)
@@ -13,14 +13,15 @@ int osrfVersion( osrfMethodContext* );
 
 int osrfAppInitialize() {
        osrfLogInit("opensrf.version");
+
        osrfAppRegisterMethod( 
                        "opensrf.version", 
                        "opensrf.version.verify", 
                        "osrfVersion", 
-                       "Send the service, method, and params as paramters to this method "
-                       "The data for this service/method/params combination will be retrieved "
+                       "The data for a service/method/params combination will be retrieved "
                        "from the necessary server and the MD5 sum of the total values received "
-                       "will be returned", 2 );
+                       "will be returned", 
+                       "( serviceName, methodName, [param1, ...] )", 2 );
        
        return 0;
 }
index 1ff362a..b6b76de 100644 (file)
@@ -1,5 +1,8 @@
+# OSRF_LOG_PARAMS log all incoming method params at OSRF_INFO log level. 
+# OSRF_STRICT_PARAMS instructs the app handler to return an error if the number of method arguments
+#      provided to any method is not at least as large as the 'argc' setting for the method
 
-CFLAGS +=  -DASSUME_STATELESS  -DOSRF_LOG_PARAMS -rdynamic -fno-strict-aliasing
+CFLAGS +=  -DASSUME_STATELESS  -DOSRF_LOG_PARAMS -DOSRF_STRICT_PARAMS -rdynamic -fno-strict-aliasing
 LDLIBS += -lxml2 -lobjson -ldl -lmemcache
 
 TARGETS = osrf_message.o \
index 4aa3369..e919208 100644 (file)
@@ -48,6 +48,7 @@ int osrfAppRegisterApplication( char* appName, char* soFile ) {
                }
        }
 
+       __osrfAppRegisterSysMethods(appName);
 
        info_handler("Application %s registered successfully", appName );
 
@@ -55,21 +56,18 @@ int osrfAppRegisterApplication( char* appName, char* soFile ) {
        return 0;
 }
 
-
 int osrfAppRegisterMethod( char* appName, 
-               char* methodName, char* symbolName, char* notes, int argc ) {
+               char* methodName, char* symbolName, char* notes, char* params, int argc ) {
+
        if( !appName || ! methodName || ! symbolName ) return -1;
 
        osrfApplication* app = _osrfAppFindApplication(appName);
        if(!app) return warning_handler("Unable to locate application %s", appName );
 
-       debug_handler("Registering method %s for app %s", appName, methodName );
+       debug_handler("Registering method %s for app %s", methodName, appName );
 
-       osrfMethod* method = safe_malloc(sizeof(osrfMethod));
-       method->name = strdup(methodName);
-       method->symbol = strdup(symbolName);
-       if(notes) method->notes = strdup(notes);
-       method->argc = argc;
+       osrfMethod* method = _osrfAppBuildMethod(
+               methodName, symbolName, notes, params, argc, 0 );               
 
        /* plug the method into the list of methods */
        method->next = app->methods;
@@ -77,6 +75,52 @@ int osrfAppRegisterMethod( char* appName,
        return 0;
 }
 
+
+osrfMethod* _osrfAppBuildMethod( char* methodName, 
+       char* symbolName, char* notes, char* params, int argc, int sysmethod ) {
+
+       osrfMethod* method                                      = safe_malloc(sizeof(osrfMethod));
+       if(methodName) method->name             = strdup(methodName);
+       if(symbolName) method->symbol           = strdup(symbolName);
+       if(notes) method->notes                         = strdup(notes);
+       if(params) method->paramNotes           = strdup(params);
+       method->argc                                                    = argc;
+       method->sysmethod                                               = sysmethod;
+       return method;
+}
+
+
+int _osrfAppRegisterSystemMethod( char* appName, char* methodName, 
+               char* notes, char* params, int argc ) {
+       if(!(appName && methodName)) return -1;
+       osrfApplication* app = _osrfAppFindApplication(appName);
+       if(!app) return warning_handler("Unable to locate application %s", appName );
+       debug_handler("Registering system method %s for app %s", methodName, appName );
+       osrfMethod* method = _osrfAppBuildMethod(
+               methodName, NULL, notes, params, argc, 1 );             
+
+       /* plug the method into the list of methods */
+       method->next = app->methods;
+       app->methods = method;
+       return 0;
+
+}
+
+int __osrfAppRegisterSysMethods( char* app ) {
+
+       _osrfAppRegisterSystemMethod( 
+                       app, OSRF_SYSMETHOD_INTROSPECT, 
+                       "Return a list of methods whose names have the same initial "
+                       "substring as that of the provided method name",
+                       "( methodNameSubstring )", 1 );
+
+       _osrfAppRegisterSystemMethod( 
+                       app, OSRF_SYSMETHOD_INTROSPECT_ALL, 
+                       "Returns a complete list of methods", "()", 0 ); 
+
+       return 0;
+}
+
 osrfApplication* _osrfAppFindApplication( char* name ) {
        if(!name) return NULL;
        osrfApplication* app = __osrfAppList;
@@ -105,9 +149,9 @@ osrfMethod* _osrfAppFindMethod( char* appName, char* methodName ) {
 }
 
 
+int osrfAppRunMethod( char* appName, char* methodName, 
+               osrfAppSession* ses, int reqId, jsonObject* params ) {
 
-
-int osrfAppRunMethod( char* appName, char* methodName, osrfAppSession* ses, int reqId, jsonObject* params ) {
        if( !(appName && methodName && ses) ) return -1;
 
        char* error;
@@ -126,53 +170,82 @@ int osrfAppRunMethod( char* appName, char* methodName, osrfAppSession* ses, int
                        "thread trace %s", methodName, appName, reqId, ses->session_id );
 
        if( !(app = _osrfAppFindApplication(appName)) )
-               return warning_handler( "Application not found: %s", appName );
-
+               return osrfAppRequestRespondException( ses, 
+                               reqId, "Application not found: %s", appName );
        
-       if( !(method = __osrfAppFindMethod( app, methodName )) ) {
-               /* see if the unfound method is a system method */
-               info_handler("Method %s not found, checking to see if it's a system method...", methodName );
-               osrfMethod meth;
-               meth.name = methodName;
-               context.method = &meth;
+       if( !(method = __osrfAppFindMethod( app, methodName )) ) 
+               return osrfAppRequestRespondException( ses, reqId, 
+                               "Method [%s] not found for service %s", methodName, appName );
+
+       context.method = method;
+
+       #ifdef OSRF_STRICT_PARAMS
+       if( method->argc > 0 ) {
+               if(!params || params->type != JSON_ARRAY || params->size < method->argc )
+                       return osrfAppRequestRespondException( ses, reqId, 
+                               "Not enough params for method %s / service %s", methodName, appName );
+       }
+       #endif
+
+       if( method->sysmethod ) {
+
                int sysres = __osrfAppRunSystemMethod(&context);
                if(sysres == 0) return 0;
-               if(sysres > 0) {
-                       osrfAppSessionStatus( ses, OSRF_STATUS_COMPLETE,  "osrfConnectStatus", reqId, "Request Complete" );
-                       return 0;
-               }
-               return warning_handler( "NOT FOUND: app %s / method %s", appName, methodName );
+
+               if(sysres > 0) 
+                       return osrfAppSessionStatus( ses, OSRF_STATUS_COMPLETE,  
+                                       "osrfConnectStatus", reqId, "Request Complete" );
+
+               if(sysres < 0) 
+                       return osrfAppRequestRespondException( 
+                               ses, reqId, "An unknown server error occurred" );
        }
 
 
-       context.method = method;
-       
        /* open the method */
        *(void **) (&meth) = dlsym(app->handle, method->symbol);
 
        if( (error = dlerror()) != NULL ) {
-               return warning_handler("Unable to locate method symbol [%s] "
-                               "for method %s and app %s", method->symbol, method->name, app->name );
+               return osrfAppRequestRespondException( ses, reqId, 
+                               "Unable to execute method [%s]  for service %s", methodName, appName );
        }
 
        /* run the method */
-       int ret = (*meth) (&context);
-
-       debug_handler("method returned %d", ret );
-
-       if(ret == -1) {
-               osrfAppSessionStatus( ses, OSRF_STATUS_INTERNALSERVERERROR,  
-                       "Server Error", reqId, "An unknown server error occurred" );
-               return -1;
-       }
+       int ret;
+       if( (ret = (*meth) (&context)) < 0 )
+               return osrfAppRequestRespondException( 
+                               ses, reqId, "An unknown server error occurred" );
 
        if( ret > 0 ) 
-               osrfAppSessionStatus( ses, OSRF_STATUS_COMPLETE,  "osrfConnectStatus", reqId, "Request Complete" );
+               osrfAppSessionStatus( ses, OSRF_STATUS_COMPLETE,  
+                               "osrfConnectStatus", reqId, "Request Complete" );
+
+       return 0;
+}
 
+int osrfAppRequestRespondException( osrfAppSession* ses, int request, char* msg, ... ) {
+       if(!ses) return -1;
+       if(!msg) msg = "";
+       VA_LIST_TO_STRING(msg);
+       osrfLog( OSRF_WARN, "Returning method exception with message: %s", VA_BUF );
+       osrfAppSessionStatus( ses, OSRF_STATUS_NOTFOUND, "osrfMethodException", request,  VA_BUF );
        return 0;
 }
 
 
+static void __osrfAppSetIntrospectMethod( osrfMethodContext* ctx, osrfMethod* method, jsonObject* resp ) {
+       if(!(ctx && resp)) return;
+       jsonObjectSetKey(resp, "api_name", jsonNewObject(method->name));
+       jsonObjectSetKey(resp, "method", jsonNewObject(method->symbol));
+       jsonObjectSetKey(resp, "service", jsonNewObject(ctx->session->remote_service));
+       jsonObjectSetKey(resp, "notes", jsonNewObject(method->notes));
+       jsonObjectSetKey(resp, "argc", jsonNewNumberObject(method->argc));
+       jsonObjectSetKey(resp, "params", jsonNewObject(method->paramNotes) );
+       jsonObjectSetKey(resp, "sysmethod", jsonNewNumberObject(method->sysmethod) );
+       jsonObjectSetClass(resp, "method");
+}
+
+
 
 int __osrfAppRunSystemMethod(osrfMethodContext* ctx) {
        OSRF_METHOD_VERIFY_CONTEXT(ctx);
@@ -185,15 +258,39 @@ int __osrfAppRunSystemMethod(osrfMethodContext* ctx) {
                        osrfMethod* method = app->methods;
                        while(method) {
                                resp = jsonNewObject(NULL);
-                               jsonObjectSetKey(resp, "api_name", jsonNewObject(method->name));
-                               jsonObjectSetKey(resp, "method", jsonNewObject(method->symbol));
-                               jsonObjectSetKey(resp, "service", jsonNewObject(ctx->session->remote_service));
-                               jsonObjectSetKey(resp, "notes", jsonNewObject(method->notes));
-                               jsonObjectSetKey(resp, "argc", jsonNewNumberObject(method->argc));
+                               __osrfAppSetIntrospectMethod( ctx, method, resp );
                                osrfAppRequestRespond(ctx->session, ctx->request, resp);
-                               method = method->next;
-                               jsonObjectSetClass(resp, "method");
                                jsonObjectFree(resp);
+                               method = method->next;
+                       }
+                       return 1;
+               }
+
+               return -1;
+       }
+
+
+       if( !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT )) {
+
+               jsonObject* resp = NULL;
+               char* methodSubstring = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0) );
+               osrfApplication* app = _osrfAppFindApplication( ctx->session->remote_service );
+               int len = 0;
+
+               if(!methodSubstring) return 1; /* respond with no methods */
+
+               if(app) {
+                       osrfMethod* method = app->methods;
+                       while(method) {
+                               if( (len = strlen(methodSubstring)) <= strlen(method->name) ) {
+                                       if( !strncmp( method->name, methodSubstring, len) ) {
+                                               resp = jsonNewObject(NULL);
+                                               __osrfAppSetIntrospectMethod( ctx, method, resp );
+                                               osrfAppRequestRespond(ctx->session, ctx->request, resp);
+                                               jsonObjectFree(resp);
+                                       }
+                               }
+                               method = method->next;
                        }
                        return 1;
                }
index 23e5a30..451450b 100644 (file)
@@ -1,4 +1,3 @@
-
 #include <stdio.h>
 #include <dlfcn.h>
 #include "opensrf/utils.h"
@@ -7,10 +6,21 @@
 #include "osrf_app_session.h"
 
 
-/** 
-  This macro verifies methods receive the correct parameters 
+/**
+  All OpenSRF methods take the signature
+  int methodName( osrfMethodContext* );
+  If a negative number is returned, it means an unknown error occured and an exception
+  will be returned to the client automatically.
+  If a positive number is returned, it means that libopensrf should send a 'Request Complete'
+  message following any messages sent by the method.
+  If 0 is returned, it tells libopensrf that the method completed successfully and 
+  there is no need to send any further data to the client.
   */
 
+
+
+/** 
+  This macro verifies methods receive the correct parameters */
 #define _OSRF_METHOD_VERIFY_CONTEXT(d) \
        if(!d) return -1; \
        if(!d->session) { osrfLog( OSRF_ERROR, "Session is NULL in app reqeust" ); return -1; }\
@@ -21,7 +31,6 @@
                return -1; }\
        if( !d->method->name ) { osrfLog(OSRF_ERROR, "Method name is NULL"); return -1; } 
 
-
 #ifdef OSRF_LOG_PARAMS 
 #define OSRF_METHOD_VERIFY_CONTEXT(d) \
        _OSRF_METHOD_VERIFY_CONTEXT(d); \
 
 
 
-#define OSRF_SYSMETHOD_INTROSPECT "opensrf.system.method"
-#define OSRF_SYSMETHOD_INTROSPECT_ALL "opensrf.system.method.all"
+/* used internally to make sure the method description provided is OK */
+#define OSRF_METHOD_VERIFY_DESCRIPTION(app, d) \
+       if(!app) return -1; \
+       if(!d) return -1;\
+       if(!d->name) { osrfLog( OSRF_ERROR, "No method name provided in description" ), return -1; } \
+       if(!d->symbol) { osrfLog( OSRF_ERROR, "No method symbol provided in description" ), return -1; } \
+       if(!d->notes) d->notes = ""; \
+       if(!d->paramNotes) d->paramNotes = "";\
+       if(!d->returnNotes) d->returnNotes = "";
 
 
-       
+
+/* Some well known parameters */
+#define OSRF_SYSMETHOD_INTROSPECT "opensrf.system.method"
+#define OSRF_SYSMETHOD_INTROSPECT_ALL "opensrf.system.method.all"
 
        
 
 struct _osrfApplicationStruct {
-       char* name; /* the name of our application */
-       void* handle; /* the lib handle */
-       struct _osrfMethodStruct* methods;      /* list of methods */
-       struct _osrfApplicationStruct* next; /* next application */
+       char* name;                                                                             /* the name of our application */
+       void* handle;                                                                   /* the lib handle */
+       struct _osrfMethodStruct* methods;              /* list of methods */
+       struct _osrfApplicationStruct* next;    /* next application */
 };
 typedef struct _osrfApplicationStruct osrfApplication;
 
 
 struct _osrfMethodStruct {
-       char* name;                             /* the method name */
-       char* symbol;                   /* the symbol name (function) */
-       char* notes;                    /* public method documentation */
-       int argc;                               /* how many args this method expects */
-       void* methodHandle;     /* cached version of the method handle */
-       struct _osrfMethodStruct* next;
+       char* name;                                     /* the method name */
+       char* symbol;                           /* the symbol name (function) */
+       char* notes;                            /* public method documentation */
+       int argc;                                       /* how many args this method expects */
+       char* paramNotes;                       /* Description of the params expected for this method */
+       struct _osrfMethodStruct* next; /* nest method in the list */
+       int sysmethod;                          /* true if this is a system method */
 }; 
 typedef struct _osrfMethodStruct osrfMethod;
 
 struct _osrfMethodContextStruct {
-       osrfAppSession* session;
-       osrfMethod* method;
-       jsonObject* params;
-       int request;
+       osrfAppSession* session;        /* the current session */
+       osrfMethod* method;                     /* the requested method */      
+       jsonObject* params;                     /* the params to the method */
+       int request;                                    /* request id */
 };
 typedef struct _osrfMethodContextStruct osrfMethodContext;
 
 
+
 /** 
   Register an application
   @param appName The name of the application
@@ -87,11 +108,28 @@ int osrfAppRegisterApplication( char* appName, char* soFile );
   @param methodName The fully qualified name of the method
   @param symbolName The symbol name (function) that implements the method
   @param notes Public documentation for this method.
+  @params params String description description of the params expected
   @params argc The number of arguments this method expects 
   @return 0 on success, -1 on error
   */
 int osrfAppRegisterMethod( char* appName, 
-               char* methodName, char* symbolName, char* notes, int argc );
+               char* methodName, char* symbolName, char* notes, char* params, int argc );
+
+int _osrfAppRegisterSystemMethod( char* appName, char* methodName, 
+               char* notes, char* params, int argc );
+
+osrfMethod* _osrfAppBuildMethod( char* methodName, 
+               char* symbolName, char* notes, char* params, int argc, int sysmethod );
+
+/**
+  Registher a method
+  @param appName The name of the application that implements the method
+  @params desc The method description
+  @return 0 on success, -1 on error
+  */
+/*
+int osrfAppRegisterMethod( char* appName, osrfMethodDescription* desc );
+*/
 
 /**
   Finds the given app in the list of apps
@@ -136,9 +174,27 @@ int osrfAppRunMethod( char* appName, char* methodName,
   A system method is a well known method that all
   servers implement.  
   @param context The current method context
-  @return 0 if the method is run, -1 otherwise
+  @return 0 if the method is run successfully, return < 0 means
+  the method was not run, return > 0 means the method was run
+  and the application code now needs to send a 'request complete' 
+  message
   */
 int __osrfAppRunSystemMethod(osrfMethodContext* context);
 
+/**
+  Registers all of the system methods for this app so that they may be
+  treated the same as other methods */
+int __osrfAppRegisterSysMethods( char* app );
+
+
+
+/**
+  Responds to the client with a method exception
+  @param ses The current session
+  @param request The request id
+  @param msg The debug message to send to the client
+  @return 0 on successfully sending of the message, -1 otherwise
+  */
+int osrfAppRequestRespondException( osrfAppSession* ses, int request, char* msg, ... );
 
 
index f676419..df5199a 100644 (file)
@@ -35,7 +35,8 @@ int osrfCachePutObject( char* key, const jsonObject* obj, time_t seconds ) {
        if( !(key && obj) ) return -1;
        char* s = jsonObjectToJSON( obj );
        if( seconds < 0 ) seconds = __osrfCacheMaxSeconds;
-       mc_add(__osrfCache, key, strlen(key), s, strlen(s), seconds, 0);
+
+       mc_set(__osrfCache, key, strlen(key), s, strlen(s), seconds, 0);
        free(s);
        return 0;
 }
@@ -43,7 +44,7 @@ int osrfCachePutObject( char* key, const jsonObject* obj, time_t seconds ) {
 int osrfCachePutString( char* key, const char* value, time_t seconds ) {
        if( !(key && value) ) return -1;
        if( seconds < 0 ) seconds = __osrfCacheMaxSeconds;
-       mc_add(__osrfCache, key, strlen(key), value, strlen(value), seconds, 0 );
+       mc_set(__osrfCache, key, strlen(key), value, strlen(value), seconds, 0);
        return 0;
 }
 
index 603f5a7..371bd7d 100644 (file)
@@ -33,16 +33,18 @@ void osrf_message_add_object_param( osrf_message* msg, jsonObject* o ) {
 void osrf_message_set_params( osrf_message* msg, jsonObject* o ) {
        if(!msg || !o) return;
 
-       if(!o->type == JSON_ARRAY) {
-               warning_handler("passing non-array to osrf_message_set_params()");
+       if(o->type != JSON_ARRAY) {
+               warning_handler("passing non-array to osrf_message_set_params(), fixing...");
+               jsonObject* clone = jsonObjectClone(o);
+               o = jsonNewObject(NULL);
+               jsonObjectPush(o, clone);
+               if(msg->_params) jsonObjectFree(msg->_params);
+               msg->_params = o;
                return;
        }
 
        if(msg->_params) jsonObjectFree(msg->_params);
-
-       char* j = jsonObjectToJSON(o);
-       msg->_params = jsonParseString(j);
-       free(j);
+       msg->_params = jsonObjectClone(o);
 }