initial sender_locale support ... probably going to break stuff; also, patch from...
authormiker <miker@9efc2488-bf62-4759-914b-345cdb29e865>
Thu, 2 Aug 2007 02:49:53 +0000 (02:49 +0000)
committermiker <miker@9efc2488-bf62-4759-914b-345cdb29e865>
Thu, 2 Aug 2007 02:49:53 +0000 (02:49 +0000)
git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@1066 9efc2488-bf62-4759-914b-345cdb29e865

include/opensrf/osrf_app_session.h
include/opensrf/osrf_message.h
src/gateway/osrf_json_gateway.c
src/libopensrf/opensrf.c
src/libopensrf/osrf_app_session.c
src/libopensrf/osrf_application.c
src/libopensrf/osrf_message.c
src/perlmods/OpenSRF/AppSession.pm
src/perlmods/OpenSRF/DomainObject/oilsMessage.pm

index 3cdbcb6..561454e 100644 (file)
@@ -75,6 +75,9 @@ struct osrf_app_session_struct {
        /** SERVER or CLIENT */
        enum OSRF_SESSION_TYPE type;
 
+       /** the current locale for this session **/
+       char* session_locale;
+
        /* let the user use the session to store their own session data */
        void* userData;
 
@@ -99,6 +102,9 @@ osrf_app_session* osrf_app_client_session_init( char* remote_service );
 osrf_app_session* osrf_app_server_session_init( 
                char* session_id, char* our_app, char* remote_id );
 
+/** sets the default locale for a session **/
+char* osrf_app_session_set_locale( osrf_app_session*, const char* );
+
 /** returns a session from the global session hash */
 osrf_app_session* osrf_app_session_find_session( char* session_id );
 
@@ -114,6 +120,14 @@ int osrf_app_session_make_req(
                osrf_app_session* session, jsonObject* params, 
                char* method_name, int protocol, string_array* param_strings);
 
+int osrfAppSessionMakeLocaleRequest(
+               osrf_app_session* session, jsonObject* params, 
+               char* method_name, int protocol, string_array* param_strings, char* locale);
+
+int osrf_app_session_make_locale_req( 
+               osrf_app_session* session, jsonObject* params, 
+               char* method_name, int protocol, string_array* param_strings, char* locale);
+
 /** Sets the given request to complete state */
 void osrf_app_session_set_complete( osrf_app_session* session, int request_id );
 
index ca79082..e8d5b75 100644 (file)
@@ -75,10 +75,31 @@ struct osrf_message_struct {
 
        char* full_param_string;
 
+       /* magical LOCALE hint */
+       char* sender_locale;
+
+       /* timezone offset from GMT of sender, in seconds */
+       int sender_tz_offset;
+
 };
 typedef struct osrf_message_struct osrf_message;
 typedef struct osrf_message_struct osrfMessage;
 
+/* Set the locale hint for this message.
+   default_locale is used if not set.
+   Returns NULL if msg or locale is not set, char* to msg->sender_locale on success.
+*/
+char* osrf_message_set_locale( osrf_message* msg, const char* locale );
+
+/* Set the default locale hint to be used for future outgoing messages.
+   Returns NULL if locale is NULL, const char* to default_locale otherwise.
+*/
+const char* osrf_message_set_default_locale( const char* locale );
+
+/* Get the current locale hint -- either the default or most recently received locale.
+   Returns const char* to current_locale.
+*/
+const char* osrf_message_get_current_locale(void);
 
 osrf_message* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol );
 //void osrf_message_set_request_info( osrf_message*, char* param_name, json* params );
index 9dfa5d3..49c0f1a 100644 (file)
@@ -8,10 +8,12 @@
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <unistd.h>
+#include <strings.h>
 
 
 #define MODULE_NAME "osrf_json_gateway_module"
 #define GATEWAY_CONFIG "OSRFGatewayConfig"
+#define DEFAULT_LOCALE "OSRFDefaultLocale"
 #define CONFIG_CONTEXT "gateway"
 #define JSON_PROTOCOL "OSRFGatewayLegacyJSON"
 #define GATEWAY_USE_LEGACY_JSON 1
@@ -31,11 +33,17 @@ typedef struct {
 
 module AP_MODULE_DECLARE_DATA osrf_json_gateway_module;
 
+char* osrf_json_default_locale = "en-US";
 char* osrf_json_gateway_config_file = NULL;
 int bootstrapped = 0;
 int numserved = 0;
 osrfStringArray* allowedServices = NULL;
 
+static const char* osrf_json_gateway_set_default_locale(cmd_parms *parms, void *config, const char *arg) {
+       osrf_json_default_locale = (char*) arg;
+       return NULL;
+}
+
 static const char* osrf_json_gateway_set_config(cmd_parms *parms, void *config, const char *arg) {
        osrf_json_gateway_config  *cfg;
        cfg = ap_get_module_config(parms->server->module_config, &osrf_json_gateway_module);
@@ -54,6 +62,8 @@ static const char* osrf_json_gateway_set_json_proto(cmd_parms *parms, void *conf
 static const command_rec osrf_json_gateway_cmds[] = {
        AP_INIT_TAKE1( GATEWAY_CONFIG, osrf_json_gateway_set_config, 
                        NULL, RSRC_CONF, "osrf json gateway config file"),
+       AP_INIT_TAKE1( DEFAULT_LOCALE, osrf_json_gateway_set_default_locale, 
+                       NULL, RSRC_CONF, "osrf json gateway default locale"),
        AP_INIT_TAKE1( JSON_PROTOCOL, osrf_json_gateway_set_json_proto,
                        NULL, ACCESS_CONF, "osrf json gateway config file"),
        {NULL}
@@ -137,6 +147,8 @@ static int osrf_json_gateway_method_handler (request_rec *r) {
 
        osrfLogSetAppname("osrf_json_gw");
 
+       char* osrf_locale       = NULL;
+       char* param_locale      = NULL; /* locale for this call */
        char* service           = NULL; /* service to connect to */
        char* method            = NULL; /* method to perform */
        char* format            = NULL; /* method to perform */
@@ -151,6 +163,7 @@ static int osrf_json_gateway_method_handler (request_rec *r) {
        osrfLogDebug(OSRF_LOG_MARK, "osrf gateway: parsing URL params");
        string_array* mparams   = NULL;
        string_array* params            = apacheParseParms(r); /* free me */
+       param_locale            = apacheGetFirstParamValue( params, "locale" );
        service         = apacheGetFirstParamValue( params, "service" );
        method          = apacheGetFirstParamValue( params, "method" ); 
        format          = apacheGetFirstParamValue( params, "format" ); 
@@ -184,6 +197,38 @@ static int osrf_json_gateway_method_handler (request_rec *r) {
 
        int ret = OK;
 
+       /* ----------------------------------------------------------------- */
+       /* Grab the requested locale using the Accept-Language header*/
+
+
+       if ( !param_locale ) {
+               if ( apr_table_get(r->headers_in, "X-OpenSRF-Language") ) {
+                       param_locale = strdup( apr_table_get(r->headers_in, "X-OpenSRF-Language") );
+               } else if ( apr_table_get(r->headers_in, "Accept-Language") ) {
+                       param_locale = strdup( apr_table_get(r->headers_in, "Accept-Language") );
+               }
+       }
+
+
+       if (param_locale) {
+               growing_buffer* osrf_locale_buf = buffer_init(16);      
+               if (index(param_locale, ',')) {
+                       int ind = index(param_locale, ',') - param_locale;
+                       int i;
+                       for ( i = 0; i < ind - 1 && i < 128; i++ )
+                               buffer_add_char( osrf_locale_buf, param_locale[i] );
+               } else {
+                       buffer_add( osrf_locale_buf, param_locale );
+               }
+
+               free(param_locale);
+               osrf_locale = buffer_release( osrf_locale_buf );
+       } else {
+               osrf_locale = strdup( osrf_json_default_locale );
+       }
+       /* ----------------------------------------------------------------- */
+
+
        if(!(service && method) || 
                !osrfStringArrayContains(allowedServices, service)) {
 
@@ -205,6 +250,7 @@ static int osrf_json_gateway_method_handler (request_rec *r) {
                */
 
                osrfAppSession* session = osrf_app_client_session_init(service);
+               osrf_app_session_set_locale(session, osrf_locale);
 
                double starttime = get_timestamp_millis();
                int req_id = -1;
@@ -294,7 +340,6 @@ static int osrf_json_gateway_method_handler (request_rec *r) {
                                if (isXML) {
                                        output = jsonObjectToXML( res );
                                } else {
-                                       //output = jsonObjectToJSON( res );
                     output = jsonToStringFunc( res );
                                        if( morethan1 ) ap_rputs(",", r); /* comma between JSON array items */
                                }
@@ -342,7 +387,6 @@ static int osrf_json_gateway_method_handler (request_rec *r) {
                                snprintf(bb, l,  "%s : %s", statusname, statustext);
                                jsonObject* tmp = jsonNewObject(bb);
                 char* j = jsonToStringFunc(tmp);
-                               //char* j = jsonObjectToJSON(tmp);
                                snprintf( buf, l, ",\"debug\": %s", j);
                                free(j);
                                jsonObjectFree(tmp);
@@ -374,6 +418,7 @@ static int osrf_json_gateway_method_handler (request_rec *r) {
        }
 
        osrfLogInfo(OSRF_LOG_MARK, "Completed processing service=%s, method=%s", service, method);
+       free(osrf_locale);
        string_array_destroy(params);
        string_array_destroy(mparams);
 
index 3b6f6fd..e7215d2 100644 (file)
@@ -1,6 +1,4 @@
 #include <opensrf/osrf_system.h>
-//#include <opensrf/osrf_hash.h>
-//#include <opensrf/osrf_list.h>
 
 int main( int argc, char* argv[] ) {
 
index ef16ce5..308048d 100644 (file)
@@ -204,6 +204,11 @@ osrf_app_session* osrfAppSessionClientInit( char* remote_service ) {
 
 osrf_app_session* osrf_app_client_session_init( char* remote_service ) {
 
+       if (!remote_service) {
+               osrfLogWarning( OSRF_LOG_MARK, "No remote service specified in osrf_app_client_session_init");
+               return NULL;
+       }
+
        osrf_app_session* session = safe_malloc(sizeof(osrf_app_session));      
 
        session->transport_handle = osrf_system_get_transport_client();
@@ -213,14 +218,28 @@ osrf_app_session* osrf_app_client_session_init( char* remote_service ) {
                return NULL;
        }
 
-       char target_buf[512];
-       target_buf[ 0 ] = '\0';
-
        osrfStringArray* arr = osrfNewStringArray(8);
        osrfConfigGetValueList(NULL, arr, "/domains/domain");
        char* domain = osrfStringArrayGetString(arr, 0);
+
+       if (!domain) {
+               osrfLogWarning( OSRF_LOG_MARK, "No domains specified in the OpenSRF config file");
+               free( session );
+               osrfStringArrayFree(arr);
+               return NULL;
+       }
+
        char* router_name = osrfConfigGetValue(NULL, "/router_name");
-       
+       if (!router_name) {
+               osrfLogWarning( OSRF_LOG_MARK, "No router name specified in the OpenSRF config file");
+               free( session );
+               osrfStringArrayFree(arr);
+               return NULL;
+       }
+
+       char target_buf[512];
+       target_buf[ 0 ] = '\0';
+
        int len = snprintf( target_buf, 512, "%s@%s/%s",
                        router_name ? router_name : "(null)",
                        domain ? domain : "(null)",
index b69659f..c70d446 100644 (file)
@@ -12,7 +12,7 @@ int osrfAppRegisterApplication( char* appName, char* soFile ) {
 
        osrfApplication* app = safe_malloc(sizeof(osrfApplication));
        app->handle = dlopen (soFile, RTLD_NOW);
-   app->onExit = NULL;
+       app->onExit = NULL;
 
        if(!app->handle) {
                osrfLogWarning( OSRF_LOG_MARK, "Failed to dlopen library file %s: %s", soFile, dlerror() );
@@ -51,28 +51,27 @@ int osrfAppRegisterApplication( char* appName, char* soFile ) {
 
        osrfLogSetAppname(appName);
 
-   osrfAppSetOnExit(app, appName);
+       osrfAppSetOnExit(app, appName);
 
        return 0;
 }
 
 
 void osrfAppSetOnExit(osrfApplication* app, char* appName) {
-   if(!(app && appName)) return;
+       if(!(app && appName)) return;
 
        /* see if we can run the initialize method */
-   char* error;
+       char* error;
        void (*onExit) (void);
        *(void **) (&onExit) = dlsym(app->handle, "osrfAppChildExit");
 
        if( (error = dlerror()) != NULL ) {
-      osrfLogDebug(OSRF_LOG_MARK, "No exit handler defined for %s", appName);
-      return;
-   }
+               osrfLogDebug(OSRF_LOG_MARK, "No exit handler defined for %s", appName);
+               return;
+       }
 
-   osrfLogInfo(OSRF_LOG_MARK, "registering exit handler for %s", appName);
-   app->onExit = (*onExit);
-   //if( (ret = (*onExit)()) ) {
+       osrfLogInfo(OSRF_LOG_MARK, "registering exit handler for %s", appName);
+       app->onExit = (*onExit);
 }
 
 
@@ -102,14 +101,14 @@ int osrfAppRunChildInit(char* appname) {
 
 
 void osrfAppRunExitCode() { 
-   osrfHashIterator* itr = osrfNewHashIterator(__osrfAppHash);
-   osrfApplication* app;
-   while( (app = osrfHashIteratorNext(itr)) ) {
-      if( app->onExit ) {
-         osrfLogInfo(OSRF_LOG_MARK, "Running onExit handler for app %s", itr->current);
-         app->onExit();
-      }
-   }
+       osrfHashIterator* itr = osrfNewHashIterator(__osrfAppHash);
+       osrfApplication* app;
+       while( (app = osrfHashIteratorNext(itr)) ) {
+               if( app->onExit ) {
+                       osrfLogInfo(OSRF_LOG_MARK, "Running onExit handler for app %s", itr->current);
+                       app->onExit();
+               }
+       }
 }
 
 
index 313216a..57d2bd5 100644 (file)
@@ -1,5 +1,8 @@
 #include <opensrf/osrf_message.h>
 
+static char default_locale[17] = "en-US\0\0\0\0\0\0\0\0\0\0\0\0";
+static char* current_locale = default_locale;
+
 osrf_message* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol ) {
 
        osrf_message* msg                       = (osrf_message*) safe_malloc(sizeof(osrf_message));
@@ -10,11 +13,30 @@ osrf_message* osrf_message_init( enum M_TYPE type, int thread_trace, int protoco
        msg->is_exception                       = 0;
        msg->_params                            = NULL;
        msg->_result_content            = NULL;
+       msg->sender_locale              = NULL;
 
        return msg;
 }
 
 
+const char* osrf_message_get_last_locale() {
+       return current_locale;
+}
+
+char* osrf_message_set_locale( osrf_message* msg, const char* locale ) {
+       if( msg == NULL || locale == NULL ) return NULL;
+       return msg->sender_locale = strdup( locale );
+}
+
+const char* osrf_message_set_default_locale( const char* locale ) {
+       if( locale == NULL ) return NULL;
+       if( strlen(locale) > 16 ) return NULL;
+
+       memcpy( default_locale, locale, strlen(locale) );
+       default_locale[strlen(locale)] = '\0';
+       return (const char*) default_locale;
+}
+
 void osrf_message_set_method( osrf_message* msg, char* method_name ) {
        if( msg == NULL || method_name == NULL ) return;
        msg->method_name = strdup( method_name );
@@ -101,6 +123,9 @@ void osrf_message_free( osrf_message* msg ) {
        if( msg->method_name != NULL )
                free(msg->method_name);
 
+       if( msg->sender_locale != NULL )
+               free(msg->sender_locale);
+
        if( msg->_params != NULL )
                jsonObjectFree(msg->_params);
 
@@ -156,6 +181,14 @@ jsonObject* osrfMessageToJSON( osrfMessage* msg ) {
        INT_TO_STRING(msg->thread_trace);
        jsonObjectSetKey(json, "threadTrace", jsonNewObject(INTSTR));
 
+       if (msg->sender_locale != NULL) {
+               jsonObjectSetKey(json, "locale", jsonNewObject(msg->sender_locale));
+       } else if (current_locale != NULL) {
+               jsonObjectSetKey(json, "locale", jsonNewObject(current_locale));
+       } else {
+               jsonObjectSetKey(json, "locale", jsonNewObject(default_locale));
+       }
+
        switch(msg->m_type) {
                
                case CONNECT: 
@@ -249,14 +282,14 @@ int osrf_message_deserialize(char* string, osrf_message* msgs[], int count) {
                                        new_msg->thread_trace = atoi(tt);
                                        free(tt);
                                }
-                               /*
-                               if(tmp->type == JSON_NUMBER)
-                                       new_msg->thread_trace = (int) jsonObjectGetNumber(tmp);
-                               if(tmp->type == JSON_STRING)
-                                       new_msg->thread_trace = atoi(jsonObjectGetString(tmp));
-                                       */
                        }
 
+                       /* use the sender's locale, or the global default */
+                       tmp = jsonObjectGetKey(message, "locale");
+                       if(tmp)
+                               new_msg->sender_locale = jsonObjectToSimpleString(tmp);
+
+                       current_locale = new_msg->sender_locale;
 
                        tmp = jsonObjectGetKey(message, "protocol");
 
@@ -266,13 +299,6 @@ int osrf_message_deserialize(char* string, osrf_message* msgs[], int count) {
                                        new_msg->protocol = atoi(proto);
                                        free(proto);
                                }
-
-                               /*
-                               if(tmp->type == JSON_NUMBER)
-                                       new_msg->protocol = (int) jsonObjectGetNumber(tmp);
-                               if(tmp->type == JSON_STRING)
-                                       new_msg->protocol = atoi(jsonObjectGetString(tmp));
-                                       */
                        }
 
                        tmp = jsonObjectGetKey(message, "payload");
index 9b2017a..3b79359 100644 (file)
@@ -156,6 +156,14 @@ sub last_sent_payload {
        return $self->{'last_sent_payload'};
 }
 
+sub session_locale {
+       my( $self, $type ) = @_;
+       if( $type ) {
+               return $self->{'session_locale'} = $type;
+       }
+       return $self->{'session_locale'};
+}
+
 sub last_sent_type {
        my( $self, $type ) = @_;
        if( $type ) {
@@ -192,9 +200,6 @@ sub stateless {
 }
 
 # When we're a client and we want to connect to a remote service
-# create( $app, username => $user, secret => $passwd );
-#    OR
-# create( $app, sysname => $user, secret => $shared_secret );
 sub create {
        my $class = shift;
        $class = ref($class) || $class;
@@ -202,6 +207,7 @@ sub create {
        my $app = shift;
         my $api_level = shift;
        my $quiet = shift;
+       my $locale = shift;
 
        $api_level = 1 if (!defined($api_level));
                                
@@ -237,6 +243,7 @@ sub create {
                           session_id  => $sess_id,
                           remote_id   => $r_id,
                           raise_error   => $quiet ? 0 : 1,
+                          session_locale   => $locale,
                           api_level   => $api_level,
                           orig_remote_id   => $r_id,
                                peer_handle => $peer_handle,
@@ -494,6 +501,7 @@ sub send {
        
                $msg->api_level($self->api_level);
                $msg->payload($payload) if $payload;
+               $msg->sender_locale($self->session_locale) if $self->session_locale;
        
                push @doc, $msg;
 
@@ -742,7 +750,13 @@ sub recv {
        $logger->debug( "Number of matched responses: " . @list, DEBUG );
        $self->queue_wait(0); # check for statuses
        
-       return $list[0] unless (wantarray);
+       if (!wantarray) {
+               $self->session_locale( $list[0]->sender_locale );
+               return $list[0];
+       } else {
+               $self->session_locale( $list[-1]->sender_locale );
+       }
+
        return @list;
 }
 
index 1374e28..495e33a 100644 (file)
@@ -86,6 +86,24 @@ sub api_level {
        return $self->{api_level};
 }
 
+=head2 OpenSRF::DomainObject::oilsMessage->sender_locale( [$locale] );
+
+=over 4
+
+Sets or gets the current message locale hint.  Useful for telling the
+server how you see the world.
+
+=back
+
+=cut
+
+sub sender_locale {
+       my $self = shift;
+       my $val = shift;
+       $self->{sender_locale} = $val if (defined $val);
+       return $self->{sender_locale};
+}
+
 =head2 OpenSRF::DomainObject::oilsMessage->threadTrace( [$new_threadTrace] );
 
 =over 4